From: Vitaliy Makkoveev Subject: Re: sysctl(2): unlock sysctl_malloc() To: tech@openbsd.org, Martin Pieuchot Date: Sat, 28 Dec 2024 08:28:36 +0300 On Tue, Dec 17, 2024 at 01:33:26AM +0300, Vitaliy Makkoveev wrote: > Except KERN_MALLOC_BUCKETS case it is already mp-safe. This case does > read-only access to `buckstring' which is immutable since is is > initialized at first usage. This is not the fast path, moreover it never > be visited in the most cases, so use existing `sysctl_kmemlock' > rwlock(9) to protect `buckstring' initialization in the way of > KERN_MALLOC_KMEMNAMES case. > The new one. Against previous, statically allocated `buckstring' became dynamically allocated each time when KERN_MALLOC_BUCKETS case visited. This string filled with immutable data, no extra locks required. This diff makes kern.malloc.buckets access a little bit longer, but as I said before, this path visited very rare. Martin, malloc(9) is a part of VM area, so I ask you to review. Index: sys/kern/kern_malloc.c =================================================================== RCS file: /cvs/src/sys/kern/kern_malloc.c,v diff -u -p -r1.152 kern_malloc.c --- sys/kern/kern_malloc.c 26 Jun 2024 01:40:49 -0000 1.152 +++ sys/kern/kern_malloc.c 28 Dec 2024 04:47:10 -0000 @@ -50,6 +50,12 @@ #include #endif +/* + * Locks used to protect data: + * M malloc_mtx + * S sysctl_kmemlock + */ + static #ifndef SMALL_KERNEL __inline__ @@ -89,17 +95,15 @@ struct vm_map *kmem_map = NULL; u_int nkmempages = NKMEMPAGES; struct mutex malloc_mtx = MUTEX_INITIALIZER(IPL_VM); -struct kmembuckets bucket[MINBUCKET + 16]; +struct kmembuckets bucket[MINBUCKET + 16]; /* [M] */ #ifdef KMEMSTATS -struct kmemstats kmemstats[M_LAST]; +struct kmemstats kmemstats[M_LAST]; /* [M] */ #endif struct kmemusage *kmemusage; char *kmembase, *kmemlimit; -char buckstring[16 * sizeof("123456,")]; -int buckstring_init = 0; #if defined(KMEMSTATS) || defined(DIAGNOSTIC) char *memname[] = INITKMEMNAMES; -char *memall = NULL; +char *memall = NULL; /* [S] */ struct rwlock sysctl_kmemlock = RWLOCK_INITIALIZER("sysctlklk"); #endif @@ -601,23 +605,26 @@ sysctl_malloc(int *name, u_int namelen, return (ENOTDIR); /* overloaded */ switch (name[0]) { - case KERN_MALLOC_BUCKETS: - /* Initialize the first time */ - if (buckstring_init == 0) { - buckstring_init = 1; - memset(buckstring, 0, sizeof(buckstring)); - for (siz = 0, i = MINBUCKET; i < MINBUCKET + 16; i++) { - snprintf(buckstring + siz, - sizeof buckstring - siz, - "%d,", (u_int)(1< 0 case KERN_AUDIO: return (sysctl_audio(name, namelen, oldp, oldlenp, @@ -452,9 +455,6 @@ kern_sysctl_dirs_locked(int top_name, in return (sysctl_doprof(name, namelen, oldp, oldlenp, newp, newlen)); #endif - case KERN_MALLOCSTATS: - return (sysctl_malloc(name, namelen, oldp, oldlenp, - newp, newlen, p)); case KERN_TTY: return (sysctl_tty(name, namelen, oldp, oldlenp, newp, newlen));