I've noted that cpu_lwp_free in the current design must not sleep: src/src/sys/kern/kern_lwp.c:1138 /* * We can no longer block. At this point, lwp_free() may already * be gunning for us. On a multi-CPU system, we may be off p_lwps. * * Free MD LWP resources. */ cpu_lwp_free(l, 0); src/src/sys/kern/kern_exit.c:587 /* Verify that we hold no locks other than the kernel lock. */ LOCKDEBUG_BARRIER(&kernel_lock, 0); /* * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP! */ /* * Give machine-dependent code a chance to free any MD LWP * resources. This must be done before uvm_lwp_exit(), in * case these resources are in the PCB. */ cpu_lwp_free(l, 1); In the following ports we have sleepable locks 1. HPPA sys/arch/hppa/hppa/vm_machdep.c: 183 void 184 cpu_lwp_free(struct lwp *l, int proc) 185 { 186 struct pcb *pcb = lwp_getpcb(l); 187 188 /* 189 * If this thread was using the FPU, disable the FPU and record 190 * that it's unused. 191 */ 192 193 hppa_fpu_flush(l); 194 pool_put(&hppa_fppl, pcb->pcb_fpregs); 195 } pool_put is calling mutex internally src/src/sys/kern/subr_pool.c: void pool_put(struct pool *pp, void *v) { struct pool_pagelist pq; LIST_INIT(&pq); mutex_enter(&pp->pr_lock); pool_do_put(pp, v, &pq); mutex_exit(&pp->pr_lock); pr_pagelist_free(pp, &pq); } 2. SPARC src/sys/arch/sparc/sparc/vm_machdep.c: 291 /* 292 * Cleanup FPU state. 293 */ 294 void 295 cpu_lwp_free(struct lwp *l, int proc) 296 { 297 struct fpstate *fs; 298 299 if ((fs = l->l_md.md_fpstate) != NULL) { 300 struct cpu_info *cpi; 301 int s; 302 303 FPU_LOCK(s); 304 if ((cpi = l->l_md.md_fpu) != NULL) { 305 if (cpi->fplwp != l) 306 panic("FPU(%d): fplwp %p", 307 cpi->ci_cpuid, cpi->fplwp); 308 if (l == cpuinfo.fplwp) 309 savefpstate(fs); 310 #if defined(MULTIPROCESSOR) 311 else 312 XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid); 313 #endif 314 cpi->fplwp = NULL; 315 } 316 l->l_md.md_fpu = NULL; 317 FPU_UNLOCK(s); 318 } 319 } FPU_LOCK() and FPU_UNLOCK wrap regular mutex src/sys/arch/sparc/include/proc.h: 65 /* 66 * FPU context switch lock 67 * Prevent interrupts that grab the kernel lock 68 * XXX mrg: remove (s) argument 69 */ 70 extern kmutex_t fpu_mtx; 71 72 #define FPU_LOCK(s) do { \ 73 (void)&(s); \ 74 mutex_enter(&fpu_mtx); \ 75 } while (/* CONSTCOND */ 0) 76 77 #define FPU_UNLOCK(s) do { \ 78 mutex_exit(&fpu_mtx); \ 79 } while (/* CONSTCOND */ 0) 80 #endif My understanding is that these calls should be moved to cpu_lwp_free2. I was following similar approach from hppa on amd64 with 8 CPUs and I was able to trigger - during distribution build - crash, that LWP went to sleep on lock and once was woken up it faced LSZOMB kernel assertions.
Attachment:
signature.asc
Description: OpenPGP digital signature