Download raw body.
sysctl(2): unlock sysctl_malloc()
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.
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 16 Dec 2024 22:30:39 -0000
@@ -50,6 +50,12 @@
#include <ddb/db_output.h>
#endif
+/*
+ * Locks used to protect data:
+ * M malloc_mtx
+ * S sysctl_kmemlock
+ */
+
static
#ifndef SMALL_KERNEL
__inline__
@@ -89,20 +95,21 @@ 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;
+char buckstring[16 * sizeof("123456,")]; /* [S] */
+int buckstring_init = 0; /* [S] */
#if defined(KMEMSTATS) || defined(DIAGNOSTIC)
char *memname[] = INITKMEMNAMES;
-char *memall = NULL;
-struct rwlock sysctl_kmemlock = RWLOCK_INITIALIZER("sysctlklk");
+char *memall = NULL; /* [S] */
#endif
+struct rwlock sysctl_kmemlock = RWLOCK_INITIALIZER("sysctlklk");
+
/*
* Normally the freelist structure is used only to hold the list pointer
* for free objects. However, when running with diagnostics, the first
@@ -602,6 +609,9 @@ sysctl_malloc(int *name, u_int namelen,
switch (name[0]) {
case KERN_MALLOC_BUCKETS:
+ error = rw_enter(&sysctl_kmemlock, RW_WRITE|RW_INTR);
+ if (error)
+ return (error);
/* Initialize the first time */
if (buckstring_init == 0) {
buckstring_init = 1;
@@ -616,6 +626,7 @@ sysctl_malloc(int *name, u_int namelen,
if (siz)
buckstring[siz - 1] = '\0';
}
+ rw_exit_write(&sysctl_kmemlock);
return (sysctl_rdstring(oldp, oldlenp, newp, buckstring));
case KERN_MALLOC_BUCKET:
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
diff -u -p -r1.458 kern_sysctl.c
--- sys/kern/kern_sysctl.c 16 Dec 2024 21:22:51 -0000 1.458
+++ sys/kern/kern_sysctl.c 16 Dec 2024 22:30:39 -0000
@@ -403,6 +403,9 @@ kern_sysctl_dirs(int top_name, int *name
int error;
switch (top_name) {
+ case KERN_MALLOCSTATS:
+ return (sysctl_malloc(name, namelen, oldp, oldlenp,
+ newp, newlen, p));
#if NAUDIO > 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));
sysctl(2): unlock sysctl_malloc()