Subject: mb_map->lock.can_sleep
To: None <tech-kern@sun-lamp.cs.berkeley.edu>
From: Gordon W. Ross <gwr@jericho.mc.com>
List: tech-kern
Date: 05/02/1994 11:03:33
> From: gwr (Gordon W. Ross)
> Date: Sun, 1 May 94 23:51:38 EDT
> Reply-To: gwr@mc.com (Gordon W. Ross)
>
> OK, I tried clearing lock.can_sleep for both mb_map and kmem_map
> and now it doesn't panic, but it hangs. [...]
Actually, this turned out to be useful. With the lock.can_sleep
member set to FALSE in both mb_map and kmem_map the kernel will
spin-wait on these locks rather than calling sleep. This helped
me find the interrupt enable problem described below.
The reason my kernel was hanging was a recursive interrupt at the
same level, which caused a recursive taking of the mb_map lock.
The second attempt to take the lock either tries to sleep (with
the original code) or spin-waits indefinitely (after I cleared
the lock.can_sleep flag).
As we all know, sleep should never be called from an interrupt
context. For this reason I would be more comfortable if it were
NOT possible for kmem_malloc(..., canwait=0) to call sleep.
It appears that just turning off the lock.can_sleep flag for both
mb_map and kmem_map has this effect without changing the behavior
of kmem_malloc() for calls from user context. Is the true?
Is there a better way to guarantee that kmem_malloc will not
call sleep from an interrupt context?
In case anyone missed it, here are the changes I'm talking about:
*** kern/kern_malloc.c.~1~ Sun Dec 19 21:33:46 1993
--- kern/kern_malloc.c Sun May 1 22:03:30 1994
***************
*** 249,254 ****
--- 249,256 ----
(vm_size_t)(npg * sizeof(struct kmemusage)));
kmem_map = kmem_suballoc(kernel_map, (vm_offset_t *)&kmembase,
(vm_offset_t *)&kmemlimit, (vm_size_t)(npg * NBPG), FALSE);
+ kmem_map->lock.can_sleep = FALSE; /* XXX */
+
#ifdef KMEMSTATS
for (indx = 0; indx < MINBUCKET + 16; indx++) {
if (1 << indx >= CLBYTES)
*** (arch)/machdep.c.~3~ Thu Apr 28 23:26:38 1994
--- (arch)/machdep.c Sun May 1 21:52:56 1994
***************
*** 222,227 ****
--- 222,228 ----
bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
VM_MBUF_SIZE, FALSE);
+ mb_map->lock.can_sleep = FALSE; /* XXX */
/*
* Initialize callouts
------------------------------------------------------------------------------