[BACK]Return to kern_mutex.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/kern_mutex.c between version 1.32 and 1.44

version 1.32, 2008/03/28 16:23:39 version 1.44, 2008/10/15 06:51:20
Line 15 
Line 15 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software  
  *    must display the following acknowledgement:  
  *      This product includes software developed by the NetBSD  
  *      Foundation, Inc. and its contributors.  
  * 4. Neither the name of The NetBSD Foundation nor the names of its  
  *    contributors may be used to endorse or promote products derived  
  *    from this software without specific prior written permission.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Line 49 
Line 42 
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include "opt_multiprocessor.h"  
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/mutex.h>  #include <sys/mutex.h>
Line 68  __KERNEL_RCSID(0, "$NetBSD$");
Line 59  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <machine/lock.h>  #include <machine/lock.h>
   
   #include "opt_sa.h"
   
 /*  /*
  * When not running a debug kernel, spin mutexes are not much   * When not running a debug kernel, spin mutexes are not much
  * more than an splraiseipl() and splx() pair.   * more than an splraiseipl() and splx() pair.
Line 83  __KERNEL_RCSID(0, "$NetBSD$");
Line 76  __KERNEL_RCSID(0, "$NetBSD$");
   
 #define MUTEX_WANTLOCK(mtx)                                     \  #define MUTEX_WANTLOCK(mtx)                                     \
     LOCKDEBUG_WANTLOCK(MUTEX_DEBUG_P(mtx), (mtx),               \      LOCKDEBUG_WANTLOCK(MUTEX_DEBUG_P(mtx), (mtx),               \
         (uintptr_t)__builtin_return_address(0), 0)          (uintptr_t)__builtin_return_address(0), false, false)
 #define MUTEX_LOCKED(mtx)                                       \  #define MUTEX_LOCKED(mtx)                                       \
     LOCKDEBUG_LOCKED(MUTEX_DEBUG_P(mtx), (mtx),                 \      LOCKDEBUG_LOCKED(MUTEX_DEBUG_P(mtx), (mtx), NULL,           \
         (uintptr_t)__builtin_return_address(0), 0)          (uintptr_t)__builtin_return_address(0), 0)
 #define MUTEX_UNLOCKED(mtx)                                     \  #define MUTEX_UNLOCKED(mtx)                                     \
     LOCKDEBUG_UNLOCKED(MUTEX_DEBUG_P(mtx), (mtx),               \      LOCKDEBUG_UNLOCKED(MUTEX_DEBUG_P(mtx), (mtx),               \
Line 130  do {        \
Line 123  do {        \
   
 #define MUTEX_SPIN_SPLRAISE(mtx)                                        \  #define MUTEX_SPIN_SPLRAISE(mtx)                                        \
 do {                                                                    \  do {                                                                    \
         struct cpu_info *x__ci = curcpu();                              \          struct cpu_info *x__ci;                                         \
         int x__cnt, s;                                                  \          int x__cnt, s;                                                  \
         x__cnt = x__ci->ci_mtx_count--;                                 \  
         s = splraiseipl(mtx->mtx_ipl);                                  \          s = splraiseipl(mtx->mtx_ipl);                                  \
           x__ci = curcpu();                                               \
           x__cnt = x__ci->ci_mtx_count--;                                 \
           __insn_barrier();                                               \
         if (x__cnt == MUTEX_COUNT_BIAS)                                 \          if (x__cnt == MUTEX_COUNT_BIAS)                                 \
                 x__ci->ci_mtx_oldspl = (s);                             \                  x__ci->ci_mtx_oldspl = (s);                             \
 } while (/* CONSTCOND */ 0)  } while (/* CONSTCOND */ 0)
Line 261  int mutex_onproc(uintptr_t, struct cpu_i
Line 256  int mutex_onproc(uintptr_t, struct cpu_i
   
 lockops_t mutex_spin_lockops = {  lockops_t mutex_spin_lockops = {
         "Mutex",          "Mutex",
         0,          LOCKOPS_SPIN,
         mutex_dump          mutex_dump
 };  };
   
 lockops_t mutex_adaptive_lockops = {  lockops_t mutex_adaptive_lockops = {
         "Mutex",          "Mutex",
         1,          LOCKOPS_SLEEP,
         mutex_dump          mutex_dump
 };  };
   
Line 313  mutex_dump(volatile void *cookie)
Line 308  mutex_dump(volatile void *cookie)
  *      generates a lot of machine code in the DIAGNOSTIC case, so   *      generates a lot of machine code in the DIAGNOSTIC case, so
  *      we ask the compiler to not inline it.   *      we ask the compiler to not inline it.
  */   */
   void __noinline
 #if __GNUC_PREREQ__(3, 0)  
 __attribute ((noinline)) __attribute ((noreturn))  
 #endif  
 void  
 mutex_abort(kmutex_t *mtx, const char *func, const char *msg)  mutex_abort(kmutex_t *mtx, const char *func, const char *msg)
 {  {
   
         LOCKDEBUG_ABORT(mtx, (MUTEX_SPIN_P(mtx) ?          LOCKDEBUG_ABORT(mtx, (MUTEX_SPIN_P(mtx) ?
             &mutex_spin_lockops : &mutex_adaptive_lockops), func, msg);              &mutex_spin_lockops : &mutex_adaptive_lockops), func, msg);
         /* NOTREACHED */  
 }  }
   
 /*  /*
Line 460  mutex_vector_enter(kmutex_t *mtx)
Line 450  mutex_vector_enter(kmutex_t *mtx)
         struct cpu_info *ci = NULL;          struct cpu_info *ci = NULL;
         u_int count;          u_int count;
 #endif  #endif
   #ifdef KERN_SA
           int f;
   #endif
         LOCKSTAT_COUNTER(spincnt);          LOCKSTAT_COUNTER(spincnt);
         LOCKSTAT_COUNTER(slpcnt);          LOCKSTAT_COUNTER(slpcnt);
         LOCKSTAT_TIMER(spintime);          LOCKSTAT_TIMER(spintime);
Line 533  mutex_vector_enter(kmutex_t *mtx)
Line 526  mutex_vector_enter(kmutex_t *mtx)
          * determine that the owner is not running on a processor,           * determine that the owner is not running on a processor,
          * then we stop spinning, and sleep instead.           * then we stop spinning, and sleep instead.
          */           */
         for (;;) {          for (owner = mtx->mtx_owner;;) {
                 owner = mtx->mtx_owner;  
                 if (!MUTEX_OWNED(owner)) {                  if (!MUTEX_OWNED(owner)) {
                         /*                          /*
                          * Mutex owner clear could mean two things:                           * Mutex owner clear could mean two things:
Line 547  mutex_vector_enter(kmutex_t *mtx)
Line 539  mutex_vector_enter(kmutex_t *mtx)
                          */                           */
                         if (MUTEX_ACQUIRE(mtx, curthread))                          if (MUTEX_ACQUIRE(mtx, curthread))
                                 break;                                  break;
                           owner = mtx->mtx_owner;
                         continue;                          continue;
                 }                  }
   
Line 565  mutex_vector_enter(kmutex_t *mtx)
Line 558  mutex_vector_enter(kmutex_t *mtx)
                         LOCKSTAT_START_TIMER(lsflag, spintime);                          LOCKSTAT_START_TIMER(lsflag, spintime);
                         count = SPINLOCK_BACKOFF_MIN;                          count = SPINLOCK_BACKOFF_MIN;
                         for (;;) {                          for (;;) {
                                   SPINLOCK_BACKOFF(count);
                                 owner = mtx->mtx_owner;                                  owner = mtx->mtx_owner;
                                 if (!mutex_onproc(owner, &ci))                                  if (!mutex_onproc(owner, &ci))
                                         break;                                          break;
                                 SPINLOCK_BACKOFF(count);  
                         }                          }
                         LOCKSTAT_STOP_TIMER(lsflag, spintime);                          LOCKSTAT_STOP_TIMER(lsflag, spintime);
                         LOCKSTAT_COUNT(spincnt, 1);                          LOCKSTAT_COUNT(spincnt, 1);
Line 586  mutex_vector_enter(kmutex_t *mtx)
Line 579  mutex_vector_enter(kmutex_t *mtx)
                  */                   */
                 if (!MUTEX_SET_WAITERS(mtx, owner)) {                  if (!MUTEX_SET_WAITERS(mtx, owner)) {
                         turnstile_exit(mtx);                          turnstile_exit(mtx);
                           owner = mtx->mtx_owner;
                         continue;                          continue;
                 }                  }
   
Line 659  mutex_vector_enter(kmutex_t *mtx)
Line 653  mutex_vector_enter(kmutex_t *mtx)
                  *    value of the waiters flag.                   *    value of the waiters flag.
                  *                   *
                  * 2. The onproc check returns false: the holding LWP is                   * 2. The onproc check returns false: the holding LWP is
                  *    not running.  We now have the oppertunity to check                   *    not running.  We now have the opportunity to check
                  *    if mutex_exit() has blatted the modifications made                   *    if mutex_exit() has blatted the modifications made
                  *    by MUTEX_SET_WAITERS().                   *    by MUTEX_SET_WAITERS().
                  *                   *
Line 686  mutex_vector_enter(kmutex_t *mtx)
Line 680  mutex_vector_enter(kmutex_t *mtx)
                 if ((membar_consumer(), mutex_onproc(owner, &ci)) ||                  if ((membar_consumer(), mutex_onproc(owner, &ci)) ||
                     (membar_consumer(), !MUTEX_HAS_WAITERS(mtx))) {                      (membar_consumer(), !MUTEX_HAS_WAITERS(mtx))) {
                         turnstile_exit(mtx);                          turnstile_exit(mtx);
                           owner = mtx->mtx_owner;
                         continue;                          continue;
                 }                  }
 #endif  /* MULTIPROCESSOR */  #endif  /* MULTIPROCESSOR */
   
   #ifdef KERN_SA
                   /*
                    * Sleeping for a mutex should not generate an upcall.
                    * So set LP_SA_NOBLOCK to indicate this.
                    * f indicates if we should clear LP_SA_NOBLOCK when done.
                    */
                   f = ~curlwp->l_pflag & LP_SA_NOBLOCK;
                   curlwp->l_pflag |= LP_SA_NOBLOCK;
   #endif /* KERN_SA */
   
                 LOCKSTAT_START_TIMER(lsflag, slptime);                  LOCKSTAT_START_TIMER(lsflag, slptime);
   
                 turnstile_block(ts, TS_WRITER_Q, mtx, &mutex_syncobj);                  turnstile_block(ts, TS_WRITER_Q, mtx, &mutex_syncobj);
   
                 LOCKSTAT_STOP_TIMER(lsflag, slptime);                  LOCKSTAT_STOP_TIMER(lsflag, slptime);
                 LOCKSTAT_COUNT(slpcnt, 1);                  LOCKSTAT_COUNT(slpcnt, 1);
   
   #ifdef KERN_SA
                   curlwp->l_pflag ^= f;
   #endif /* KERN_SA */
   
                   owner = mtx->mtx_owner;
         }          }
   
         LOCKSTAT_EVENT(lsflag, mtx, LB_ADAPTIVE_MUTEX | LB_SLEEP1,          LOCKSTAT_EVENT(lsflag, mtx, LB_ADAPTIVE_MUTEX | LB_SLEEP1,
Line 721  mutex_vector_exit(kmutex_t *mtx)
Line 732  mutex_vector_exit(kmutex_t *mtx)
   
         if (MUTEX_SPIN_P(mtx)) {          if (MUTEX_SPIN_P(mtx)) {
 #ifdef FULL  #ifdef FULL
                 if (!__SIMPLELOCK_LOCKED_P(&mtx->mtx_lock))                  if (__predict_false(!__SIMPLELOCK_LOCKED_P(&mtx->mtx_lock))) {
                           if (panicstr != NULL)
                                   return;
                         MUTEX_ABORT(mtx, "exiting unheld spin mutex");                          MUTEX_ABORT(mtx, "exiting unheld spin mutex");
                   }
                 MUTEX_UNLOCKED(mtx);                  MUTEX_UNLOCKED(mtx);
                 __cpu_simple_unlock(&mtx->mtx_lock);                  __cpu_simple_unlock(&mtx->mtx_lock);
 #endif  #endif
Line 809  int
Line 823  int
 mutex_owned(kmutex_t *mtx)  mutex_owned(kmutex_t *mtx)
 {  {
   
           if (mtx == NULL)
                   return 0;
         if (MUTEX_ADAPTIVE_P(mtx))          if (MUTEX_ADAPTIVE_P(mtx))
                 return MUTEX_OWNER(mtx->mtx_owner) == (uintptr_t)curlwp;                  return MUTEX_OWNER(mtx->mtx_owner) == (uintptr_t)curlwp;
 #ifdef FULL  #ifdef FULL

Legend:
Removed from v.1.32  
changed lines
  Added in v.1.44

CVSweb <webmaster@jp.NetBSD.org>