tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Locking in cpu_lwp_free()



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



Home | Main Index | Thread Index | Old Index