Index: ./common/linux/linux_work.c =================================================================== RCS file: /cvsroot/src/sys/external/bsd/common/linux/linux_work.c,v retrieving revision 1.43 diff -p -u -r1.43 linux_work.c --- ./common/linux/linux_work.c 27 Aug 2018 15:25:43 -0000 1.43 +++ ./common/linux/linux_work.c 5 Mar 2019 08:27:01 -0000 @@ -111,6 +111,7 @@ SDT_PROBE_DEFINE1(sdt, linux, work, flus SDT_PROBE_DEFINE1(sdt, linux, work, flush__done, "struct workqueue_struct *"/*wq*/); +static bool workqueue_key_initialized __read_mostly; static specificdata_key_t workqueue_key __read_mostly; struct workqueue_struct *system_wq __read_mostly; @@ -124,6 +125,20 @@ atomic_cas_uintptr(volatile uintptr_t *p return (uintptr_t)atomic_cas_ptr(p, (void *)old, (void *)new); } +static int +linux_workqueue_preinit(void) +{ + int error; + + if (workqueue_key_initialized) + return 0; + error = lwp_specific_key_create(&workqueue_key, NULL); + if (error) + return error; + workqueue_key_initialized = true; + return 0; +} + /* * linux_workqueue_init() * @@ -135,7 +150,7 @@ linux_workqueue_init(void) { int error; - error = lwp_specific_key_create(&workqueue_key, NULL); + error = linux_workqueue_preinit(); if (error) goto fail0; @@ -164,6 +179,7 @@ fail4: __unused fail3: destroy_workqueue(system_long_wq); fail2: destroy_workqueue(system_wq); fail1: lwp_specific_key_delete(workqueue_key); + workqueue_key_initialized = false; fail0: KASSERT(error); return error; } @@ -181,6 +197,7 @@ linux_workqueue_fini(void) destroy_workqueue(system_long_wq); destroy_workqueue(system_wq); lwp_specific_key_delete(workqueue_key); + workqueue_key_initialized = false; } /* @@ -202,6 +219,10 @@ alloc_ordered_workqueue(const char *name KASSERT(flags == 0); + error = linux_workqueue_preinit(); + if (__predict_false(error != 0)) + return NULL; + wq = kmem_zalloc(sizeof(*wq), KM_SLEEP); mutex_init(&wq->wq_lock, MUTEX_DEFAULT, IPL_VM);