root/sys/mplock.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. __mp_lock_init
  2. __mp_lock
  3. __mp_lock_try
  4. __mp_unlock
  5. __mp_release_all
  6. __mp_release_all_but_one
  7. __mp_acquire_count
  8. __mp_lock_held

    1 /*      $OpenBSD: mplock.h,v 1.8 2005/06/17 22:33:34 niklas Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2004 Niklas Hallqvist.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #ifndef _MPLOCK_H_
   28 #define _MPLOCK_H_
   29 
   30 /*
   31  * Really simple spinlock implementation with recursive capabilities.
   32  * Correctness is paramount, no fancyness allowed.
   33  */
   34 
   35 struct __mp_lock {
   36         __cpu_simple_lock_t mpl_lock;
   37         cpuid_t mpl_cpu;
   38         int     mpl_count;
   39 };
   40 
   41 static __inline void __mp_lock_init(struct __mp_lock *);
   42 static __inline void __mp_lock(struct __mp_lock *);
   43 static __inline void __mp_unlock(struct __mp_lock *);
   44 static __inline int __mp_release_all(struct __mp_lock *);
   45 static __inline void __mp_acquire_count(struct __mp_lock *, int);
   46 static __inline int __mp_lock_held(struct __mp_lock *);
   47 
   48 /*
   49  * XXX Simplelocks macros used at "trusted" places.
   50  */
   51 #define SIMPLELOCK              __mp_lock
   52 #define SIMPLE_LOCK_INIT        __mp_lock_init
   53 #define SIMPLE_LOCK             __mp_lock
   54 #define SIMPLE_UNLOCK           __mp_unlock
   55 
   56 static __inline void
   57 __mp_lock_init(struct __mp_lock *lock)
   58 {
   59         __cpu_simple_lock_init(&lock->mpl_lock);
   60         lock->mpl_cpu = LK_NOCPU;
   61         lock->mpl_count = 0;
   62 }
   63 
   64 #if defined(MP_LOCKDEBUG)
   65 #ifndef DDB
   66 #error "MP_LOCKDEBUG requires DDB"
   67 #endif
   68 
   69 extern void Debugger(void);
   70 extern int db_printf(const char *, ...)
   71     __attribute__((__format__(__kprintf__,1,2)));
   72 
   73 /* CPU-dependent timing, needs this to be settable from ddb. */
   74 extern int __mp_lock_spinout;
   75 #endif
   76 
   77 static __inline void
   78 __mp_lock(struct __mp_lock *lock)
   79 {
   80         int s = spllock();
   81 
   82         if (lock->mpl_cpu != cpu_number()) {
   83 #ifndef MP_LOCKDEBUG
   84                 __cpu_simple_lock(&lock->mpl_lock);
   85 #else
   86                 {
   87                         int got_it;
   88                         do {
   89                                 int ticks = __mp_lock_spinout;
   90 
   91                                 do {
   92                                         got_it = __cpu_simple_lock_try(
   93                                             &lock->mpl_lock);
   94                                 } while (!got_it && ticks-- > 0);
   95                                 if (!got_it) {
   96                                         db_printf(
   97                                             "__mp_lock(0x%x): lock spun out",
   98                                             lock);
   99                                         Debugger();
  100                                 }
  101                         } while (!got_it);
  102                 }
  103 #endif
  104                 lock->mpl_cpu = cpu_number();
  105         }
  106         lock->mpl_count++;
  107         splx(s);
  108 }
  109 
  110 /*
  111  * Try to acquire the lock, if another cpu has it, fill it in the
  112  * call-by-reference cpu parameter.  Return true if acquired.
  113  */
  114 static __inline int
  115 __mp_lock_try(struct __mp_lock *lock, cpuid_t *cpu)
  116 {
  117         int s = spllock();
  118 
  119         if (lock->mpl_cpu != cpu_number()) {
  120                 if (!__cpu_simple_lock_try(&lock->mpl_lock)) {
  121                         *cpu = lock->mpl_cpu;
  122                         splx(s);
  123                         return 0;
  124                 }
  125                 lock->mpl_cpu = cpu_number();
  126         }
  127         lock->mpl_count++;
  128         splx(s);
  129         return 1;
  130 }
  131 
  132 static __inline void
  133 __mp_unlock(struct __mp_lock *lock)
  134 {
  135         int s = spllock();
  136 
  137 #ifdef MP_LOCKDEBUG
  138         if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
  139                 db_printf("__mp_unlock(0x%x): releasing not locked lock\n",
  140                     lock);
  141                 Debugger();
  142         }
  143 #endif
  144 
  145         if (--lock->mpl_count == 0) {
  146                 lock->mpl_cpu = LK_NOCPU;
  147                 __cpu_simple_unlock(&lock->mpl_lock);
  148         }
  149         splx(s);
  150 }
  151 
  152 static __inline int
  153 __mp_release_all(struct __mp_lock *lock) {
  154         int s = spllock();
  155         int rv = lock->mpl_count;
  156 
  157 #ifdef MP_LOCKDEBUG
  158         if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
  159                 db_printf(
  160                     "__mp_release_all(0x%x): releasing not locked lock\n",
  161                     lock);
  162                 Debugger();
  163         }
  164 #endif
  165 
  166         lock->mpl_cpu = LK_NOCPU;
  167         lock->mpl_count = 0;
  168         __cpu_simple_unlock(&lock->mpl_lock);
  169         splx(s);
  170         return (rv);
  171 }
  172 
  173 static __inline int
  174 __mp_release_all_but_one(struct __mp_lock *lock) {
  175         int s = spllock();
  176         int rv = lock->mpl_count - 1;
  177 
  178 #ifdef MP_LOCKDEBUG
  179         if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
  180                 db_printf(
  181                     "__mp_release_all_but_one(0x%x): releasing not locked lock\n",
  182                     lock);
  183                 Debugger();
  184         }
  185 #endif
  186 
  187         lock->mpl_count = 1;
  188         splx(s);
  189         return (rv);
  190 }
  191 
  192 static __inline void
  193 __mp_acquire_count(struct __mp_lock *lock, int count) {
  194         int s = spllock();
  195 
  196         while (count--)
  197                 __mp_lock(lock);
  198         splx(s);
  199 }
  200 
  201 static __inline int
  202 __mp_lock_held(struct __mp_lock *lock) {
  203         return lock->mpl_count && lock->mpl_cpu == cpu_number();
  204 }
  205 
  206 extern struct __mp_lock kernel_lock;
  207 
  208 #endif /* !_MPLOCK_H */

/* [<][>][^][v][top][bottom][index][help] */