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

------------------------------------------------------------------------------