[BACK]Return to kern_lock.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_lock.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: kern_lock.c,v 1.30 2007/05/31 22:07:53 thib Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1995
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * This code contains ideas from software contributed to Berkeley by
        !             8:  * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
        !             9:  * System project at Carnegie-Mellon University.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  *     @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
        !            36:  */
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/proc.h>
        !            40: #include <sys/lock.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/sched.h>
        !            43:
        !            44: #include <machine/cpu.h>
        !            45:
        !            46: #ifndef spllock
        !            47: #define spllock() splhigh()
        !            48: #endif
        !            49:
        !            50: #ifdef MULTIPROCESSOR
        !            51: #define CPU_NUMBER() cpu_number()
        !            52: #else
        !            53: #define CPU_NUMBER() 0
        !            54: #endif
        !            55:
        !            56: void record_stacktrace(int *, int);
        !            57: void playback_stacktrace(int *, int);
        !            58:
        !            59: /*
        !            60:  * Locking primitives implementation.
        !            61:  * Locks provide shared/exclusive synchronization.
        !            62:  */
        !            63:
        !            64: #ifdef DDB /* { */
        !            65: #ifdef MULTIPROCESSOR
        !            66: int simple_lock_debugger = 1;  /* more serious on MP */
        !            67: #else
        !            68: int simple_lock_debugger = 0;
        !            69: #endif
        !            70: #define        SLOCK_DEBUGGER()        if (simple_lock_debugger) Debugger()
        !            71: #define        SLOCK_TRACE()                                                   \
        !            72:        db_stack_trace_print((db_expr_t)__builtin_frame_address(0),     \
        !            73:            TRUE, 65535, "", lock_printf);
        !            74: #else
        !            75: #define        SLOCK_DEBUGGER()        /* nothing */
        !            76: #define        SLOCK_TRACE()           /* nothing */
        !            77: #endif /* } */
        !            78:
        !            79: /*
        !            80:  * Acquire a resource.
        !            81:  */
        !            82: #define ACQUIRE(lkp, error, extflags, drain, wanted)                   \
        !            83: do {                                                                   \
        !            84:        for (error = 0; wanted; ) {                                     \
        !            85:                if ((drain))                                            \
        !            86:                        (lkp)->lk_flags |= LK_WAITDRAIN;                \
        !            87:                else                                                    \
        !            88:                        (lkp)->lk_waitcount++;                          \
        !            89:                /* XXX Cast away volatile. */                           \
        !            90:                error = tsleep((drain) ?                                \
        !            91:                    (void *)&(lkp)->lk_flags : (void *)(lkp),           \
        !            92:                    (lkp)->lk_prio, (lkp)->lk_wmesg, (lkp)->lk_timo);   \
        !            93:                if ((drain) == 0)                                       \
        !            94:                        (lkp)->lk_waitcount--;                          \
        !            95:                if (error)                                              \
        !            96:                        break;                                          \
        !            97:                if ((extflags) & LK_SLEEPFAIL) {                        \
        !            98:                        error = ENOLCK;                                 \
        !            99:                        break;                                          \
        !           100:                }                                                       \
        !           101:        }                                                               \
        !           102: } while (0)
        !           103:
        !           104: #define        SETHOLDER(lkp, pid, cpu_id)                                     \
        !           105:        (lkp)->lk_lockholder = (pid)
        !           106:
        !           107: #define        WEHOLDIT(lkp, pid, cpu_id)                                      \
        !           108:        (lkp)->lk_lockholder == (pid)
        !           109:
        !           110: #define        WAKEUP_WAITER(lkp)                                              \
        !           111: do {                                                                   \
        !           112:        if ((lkp)->lk_waitcount)                                {       \
        !           113:                /* XXX Cast away volatile. */                           \
        !           114:                wakeup((void *)(lkp));                                  \
        !           115:        }                                                               \
        !           116: } while (/*CONSTCOND*/0)
        !           117:
        !           118: #if defined(LOCKDEBUG) /* { */
        !           119: #if defined(MULTIPROCESSOR) /* { */
        !           120: struct simplelock spinlock_list_slock = SIMPLELOCK_INITIALIZER;
        !           121:
        !           122: #define        SPINLOCK_LIST_LOCK()                                            \
        !           123:        __cpu_simple_lock(&spinlock_list_slock.lock_data)
        !           124:
        !           125: #define        SPINLOCK_LIST_UNLOCK()                                          \
        !           126:        __cpu_simple_unlock(&spinlock_list_slock.lock_data)
        !           127: #else
        !           128: #define        SPINLOCK_LIST_LOCK()    /* nothing */
        !           129:
        !           130: #define        SPINLOCK_LIST_UNLOCK()  /* nothing */
        !           131: #endif /* MULTIPROCESSOR */ /* } */
        !           132:
        !           133: TAILQ_HEAD(, lock) spinlock_list =
        !           134:     TAILQ_HEAD_INITIALIZER(spinlock_list);
        !           135: #endif /* LOCKDEBUG */ /* } */
        !           136:
        !           137: #define        HAVEIT(lkp)                                                     \
        !           138: do {                                                                   \
        !           139: } while (/*CONSTCOND*/0)
        !           140:
        !           141: #define        DONTHAVEIT(lkp)                                                 \
        !           142: do {                                                                   \
        !           143: } while (/*CONSTCOND*/0)
        !           144:
        !           145: #if defined(LOCKDEBUG)
        !           146: /*
        !           147:  * Lock debug printing routine; can be configured to print to console
        !           148:  * or log to syslog.
        !           149:  */
        !           150: void
        !           151: lock_printf(const char *fmt, ...)
        !           152: {
        !           153:        char b[150];
        !           154:        va_list ap;
        !           155:
        !           156:        va_start(ap, fmt);
        !           157:        if (lock_debug_syslog)
        !           158:                vlog(LOG_DEBUG, fmt, ap);
        !           159:        else {
        !           160:                vsnprintf(b, sizeof(b), fmt, ap);
        !           161:                printf_nolog("%s", b);
        !           162:        }
        !           163:        va_end(ap);
        !           164: }
        !           165: #endif /* LOCKDEBUG */
        !           166:
        !           167: /*
        !           168:  * Initialize a lock; required before use.
        !           169:  */
        !           170: void
        !           171: lockinit(struct lock *lkp, int prio, char *wmesg, int timo, int flags)
        !           172: {
        !           173:
        !           174:        bzero(lkp, sizeof(struct lock));
        !           175:        lkp->lk_flags = flags & LK_EXTFLG_MASK;
        !           176:        lkp->lk_lockholder = LK_NOPROC;
        !           177:        lkp->lk_prio = prio;
        !           178:        lkp->lk_timo = timo;
        !           179:        lkp->lk_wmesg = wmesg;  /* just a name for spin locks */
        !           180: #if defined(LOCKDEBUG)
        !           181:        lkp->lk_lock_file = NULL;
        !           182:        lkp->lk_unlock_file = NULL;
        !           183: #endif
        !           184: }
        !           185:
        !           186: /*
        !           187:  * Determine the status of a lock.
        !           188:  */
        !           189: int
        !           190: lockstatus(struct lock *lkp)
        !           191: {
        !           192:        int lock_type = 0;
        !           193:
        !           194:        if (lkp->lk_exclusivecount != 0)
        !           195:                lock_type = LK_EXCLUSIVE;
        !           196:        else if (lkp->lk_sharecount != 0)
        !           197:                lock_type = LK_SHARED;
        !           198:        return (lock_type);
        !           199: }
        !           200:
        !           201: /*
        !           202:  * Set, change, or release a lock.
        !           203:  *
        !           204:  * Shared requests increment the shared count. Exclusive requests set the
        !           205:  * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
        !           206:  * accepted shared locks and shared-to-exclusive upgrades to go away.
        !           207:  */
        !           208: int
        !           209: lockmgr(__volatile struct lock *lkp, u_int flags, struct simplelock *interlkp)
        !           210: {
        !           211:        int error;
        !           212:        pid_t pid;
        !           213:        int extflags;
        !           214:        cpuid_t cpu_id;
        !           215:        struct proc *p = curproc;
        !           216:
        !           217:        error = 0;
        !           218:        extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
        !           219:
        !           220: #ifdef DIAGNOSTIC
        !           221:        if (p == NULL)
        !           222:                panic("lockmgr: process context required");
        !           223: #endif
        !           224:        /* Process context required. */
        !           225:        pid = p->p_pid;
        !           226:        cpu_id = CPU_NUMBER();
        !           227:
        !           228:        /*
        !           229:         * Once a lock has drained, the LK_DRAINING flag is set and an
        !           230:         * exclusive lock is returned. The only valid operation thereafter
        !           231:         * is a single release of that exclusive lock. This final release
        !           232:         * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any
        !           233:         * further requests of any sort will result in a panic. The bits
        !           234:         * selected for these two flags are chosen so that they will be set
        !           235:         * in memory that is freed (freed memory is filled with 0xdeadbeef).
        !           236:         */
        !           237:        if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) {
        !           238: #ifdef DIAGNOSTIC
        !           239:                if (lkp->lk_flags & LK_DRAINED)
        !           240:                        panic("lockmgr: using decommissioned lock");
        !           241:                if ((flags & LK_TYPE_MASK) != LK_RELEASE ||
        !           242:                    WEHOLDIT(lkp, pid, cpu_id) == 0)
        !           243:                        panic("lockmgr: non-release on draining lock: %d",
        !           244:                            flags & LK_TYPE_MASK);
        !           245: #endif /* DIAGNOSTIC */
        !           246:                lkp->lk_flags &= ~LK_DRAINING;
        !           247:                lkp->lk_flags |= LK_DRAINED;
        !           248:        }
        !           249:
        !           250:        /*
        !           251:         * Check if the caller is asking us to be schizophrenic.
        !           252:         */
        !           253:        if ((lkp->lk_flags & (LK_CANRECURSE|LK_RECURSEFAIL)) ==
        !           254:            (LK_CANRECURSE|LK_RECURSEFAIL))
        !           255:                panic("lockmgr: make up your mind");
        !           256:
        !           257:        switch (flags & LK_TYPE_MASK) {
        !           258:
        !           259:        case LK_SHARED:
        !           260:                if (WEHOLDIT(lkp, pid, cpu_id) == 0) {
        !           261:                        /*
        !           262:                         * If just polling, check to see if we will block.
        !           263:                         */
        !           264:                        if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
        !           265:                            (LK_HAVE_EXCL | LK_WANT_EXCL))) {
        !           266:                                error = EBUSY;
        !           267:                                break;
        !           268:                        }
        !           269:                        /*
        !           270:                         * Wait for exclusive locks and upgrades to clear.
        !           271:                         */
        !           272:                        ACQUIRE(lkp, error, extflags, 0, lkp->lk_flags &
        !           273:                            (LK_HAVE_EXCL | LK_WANT_EXCL));
        !           274:                        if (error)
        !           275:                                break;
        !           276:                        lkp->lk_sharecount++;
        !           277:                        break;
        !           278:                }
        !           279:                /*
        !           280:                 * We hold an exclusive lock, so downgrade it to shared.
        !           281:                 * An alternative would be to fail with EDEADLK.
        !           282:                 */
        !           283:                lkp->lk_sharecount++;
        !           284:
        !           285:                if (WEHOLDIT(lkp, pid, cpu_id) == 0 ||
        !           286:                    lkp->lk_exclusivecount == 0)
        !           287:                        panic("lockmgr: not holding exclusive lock");
        !           288:                lkp->lk_sharecount += lkp->lk_exclusivecount;
        !           289:                lkp->lk_exclusivecount = 0;
        !           290:                lkp->lk_flags &= ~LK_HAVE_EXCL;
        !           291:                SETHOLDER(lkp, LK_NOPROC, LK_NOCPU);
        !           292: #if defined(LOCKDEBUG)
        !           293:                lkp->lk_unlock_file = file;
        !           294:                lkp->lk_unlock_line = line;
        !           295: #endif
        !           296:                DONTHAVEIT(lkp);
        !           297:                WAKEUP_WAITER(lkp);
        !           298:                break;
        !           299:
        !           300:        case LK_EXCLUSIVE:
        !           301:                if (WEHOLDIT(lkp, pid, cpu_id)) {
        !           302:                        /*
        !           303:                         * Recursive lock.
        !           304:                         */
        !           305:                        if ((extflags & LK_CANRECURSE) == 0) {
        !           306:                                if (extflags & LK_RECURSEFAIL) {
        !           307:                                        error = EDEADLK;
        !           308:                                        break;
        !           309:                                } else
        !           310:                                        panic("lockmgr: locking against myself");
        !           311:                        }
        !           312:                        lkp->lk_exclusivecount++;
        !           313:                        break;
        !           314:                }
        !           315:                /*
        !           316:                 * If we are just polling, check to see if we will sleep.
        !           317:                 */
        !           318:                if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
        !           319:                     (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
        !           320:                     lkp->lk_sharecount != 0)) {
        !           321:                        error = EBUSY;
        !           322:                        break;
        !           323:                }
        !           324:                /*
        !           325:                 * Try to acquire the want_exclusive flag.
        !           326:                 */
        !           327:                ACQUIRE(lkp, error, extflags, 0, lkp->lk_flags &
        !           328:                    (LK_HAVE_EXCL | LK_WANT_EXCL));
        !           329:                if (error)
        !           330:                        break;
        !           331:                lkp->lk_flags |= LK_WANT_EXCL;
        !           332:                /*
        !           333:                 * Wait for shared locks and upgrades to finish.
        !           334:                 */
        !           335:                ACQUIRE(lkp, error, extflags, 0, lkp->lk_sharecount != 0);
        !           336:                lkp->lk_flags &= ~LK_WANT_EXCL;
        !           337:                if (error)
        !           338:                        break;
        !           339:                lkp->lk_flags |= LK_HAVE_EXCL;
        !           340:                SETHOLDER(lkp, pid, cpu_id);
        !           341: #if defined(LOCKDEBUG)
        !           342:                lkp->lk_lock_file = file;
        !           343:                lkp->lk_lock_line = line;
        !           344: #endif
        !           345:                HAVEIT(lkp);
        !           346:                if (lkp->lk_exclusivecount != 0)
        !           347:                        panic("lockmgr: non-zero exclusive count");
        !           348:                lkp->lk_exclusivecount = 1;
        !           349:                break;
        !           350:
        !           351:        case LK_RELEASE:
        !           352:                if (lkp->lk_exclusivecount != 0) {
        !           353:                        if (WEHOLDIT(lkp, pid, cpu_id) == 0) {
        !           354:                                panic("lockmgr: pid %d, not exclusive lock "
        !           355:                                    "holder %d unlocking",
        !           356:                                    pid, lkp->lk_lockholder);
        !           357:                        }
        !           358:                        lkp->lk_exclusivecount--;
        !           359:                        if (lkp->lk_exclusivecount == 0) {
        !           360:                                lkp->lk_flags &= ~LK_HAVE_EXCL;
        !           361:                                SETHOLDER(lkp, LK_NOPROC, LK_NOCPU);
        !           362: #if defined(LOCKDEBUG)
        !           363:                                lkp->lk_unlock_file = file;
        !           364:                                lkp->lk_unlock_line = line;
        !           365: #endif
        !           366:                                DONTHAVEIT(lkp);
        !           367:                        }
        !           368:                } else if (lkp->lk_sharecount != 0) {
        !           369:                        lkp->lk_sharecount--;
        !           370:                }
        !           371: #ifdef DIAGNOSTIC
        !           372:                else
        !           373:                        panic("lockmgr: release of unlocked lock!");
        !           374: #endif
        !           375:                WAKEUP_WAITER(lkp);
        !           376:                break;
        !           377:
        !           378:        case LK_DRAIN:
        !           379:                /*
        !           380:                 * Check that we do not already hold the lock, as it can
        !           381:                 * never drain if we do. Unfortunately, we have no way to
        !           382:                 * check for holding a shared lock, but at least we can
        !           383:                 * check for an exclusive one.
        !           384:                 */
        !           385:                if (WEHOLDIT(lkp, pid, cpu_id))
        !           386:                        panic("lockmgr: draining against myself");
        !           387:                /*
        !           388:                 * If we are just polling, check to see if we will sleep.
        !           389:                 */
        !           390:                if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
        !           391:                     (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
        !           392:                     lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0)) {
        !           393:                        error = EBUSY;
        !           394:                        break;
        !           395:                }
        !           396:                ACQUIRE(lkp, error, extflags, 1,
        !           397:                    ((lkp->lk_flags &
        !           398:                     (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
        !           399:                     lkp->lk_sharecount != 0 ||
        !           400:                     lkp->lk_waitcount != 0));
        !           401:                if (error)
        !           402:                        break;
        !           403:                lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
        !           404:                SETHOLDER(lkp, pid, cpu_id);
        !           405: #if defined(LOCKDEBUG)
        !           406:                lkp->lk_lock_file = file;
        !           407:                lkp->lk_lock_line = line;
        !           408: #endif
        !           409:                HAVEIT(lkp);
        !           410:                lkp->lk_exclusivecount = 1;
        !           411:                break;
        !           412:
        !           413:        default:
        !           414:                panic("lockmgr: unknown locktype request %d",
        !           415:                    flags & LK_TYPE_MASK);
        !           416:                /* NOTREACHED */
        !           417:        }
        !           418:        if ((lkp->lk_flags & LK_WAITDRAIN) != 0 &&
        !           419:            ((lkp->lk_flags &
        !           420:            (LK_HAVE_EXCL | LK_WANT_EXCL)) == 0 &&
        !           421:            lkp->lk_sharecount == 0 && lkp->lk_waitcount == 0)) {
        !           422:                lkp->lk_flags &= ~LK_WAITDRAIN;
        !           423:                wakeup((void *)&lkp->lk_flags);
        !           424:        }
        !           425:        return (error);
        !           426: }
        !           427:
        !           428: #ifdef DIAGNOSTIC
        !           429: /*
        !           430:  * Print out information about state of a lock. Used by VOP_PRINT
        !           431:  * routines to display ststus about contained locks.
        !           432:  */
        !           433: void
        !           434: lockmgr_printinfo(__volatile struct lock *lkp)
        !           435: {
        !           436:
        !           437:        if (lkp->lk_sharecount)
        !           438:                printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
        !           439:                    lkp->lk_sharecount);
        !           440:        else if (lkp->lk_flags & LK_HAVE_EXCL) {
        !           441:                printf(" lock type %s: EXCL (count %d) by ",
        !           442:                    lkp->lk_wmesg, lkp->lk_exclusivecount);
        !           443:                printf("pid %d", lkp->lk_lockholder);
        !           444:        } else
        !           445:                printf(" not locked");
        !           446:        if (lkp->lk_waitcount > 0)
        !           447:                printf(" with %d pending", lkp->lk_waitcount);
        !           448: }
        !           449: #endif /* DIAGNOSTIC */
        !           450:
        !           451: #if defined(LOCKDEBUG)
        !           452: TAILQ_HEAD(, simplelock) simplelock_list =
        !           453:     TAILQ_HEAD_INITIALIZER(simplelock_list);
        !           454:
        !           455: #if defined(MULTIPROCESSOR) /* { */
        !           456: struct simplelock simplelock_list_slock = SIMPLELOCK_INITIALIZER;
        !           457:
        !           458: #define        SLOCK_LIST_LOCK()                                               \
        !           459:        __cpu_simple_lock(&simplelock_list_slock.lock_data)
        !           460:
        !           461: #define        SLOCK_LIST_UNLOCK()                                             \
        !           462:        __cpu_simple_unlock(&simplelock_list_slock.lock_data)
        !           463:
        !           464: #define        SLOCK_COUNT(x)                                                  \
        !           465:        curcpu()->ci_simple_locks += (x)
        !           466: #else
        !           467: u_long simple_locks;
        !           468:
        !           469: #define        SLOCK_LIST_LOCK()       /* nothing */
        !           470:
        !           471: #define        SLOCK_LIST_UNLOCK()     /* nothing */
        !           472:
        !           473: #define        SLOCK_COUNT(x)          simple_locks += (x)
        !           474: #endif /* MULTIPROCESSOR */ /* } */
        !           475:
        !           476: #ifdef MULTIPROCESSOR
        !           477: #define SLOCK_MP()             lock_printf("on cpu %ld\n",             \
        !           478:                                    (u_long) cpu_number())
        !           479: #else
        !           480: #define SLOCK_MP()             /* nothing */
        !           481: #endif
        !           482:
        !           483: #define        SLOCK_WHERE(str, alp, id, l)                                    \
        !           484: do {                                                                   \
        !           485:        lock_printf("\n");                                              \
        !           486:        lock_printf(str);                                               \
        !           487:        lock_printf("lock: %p, currently at: %s:%d\n", (alp), (id), (l)); \
        !           488:        SLOCK_MP();                                                     \
        !           489:        if ((alp)->lock_file != NULL)                                   \
        !           490:                lock_printf("last locked: %s:%d\n", (alp)->lock_file,   \
        !           491:                    (alp)->lock_line);                                  \
        !           492:        if ((alp)->unlock_file != NULL)                                 \
        !           493:                lock_printf("last unlocked: %s:%d\n", (alp)->unlock_file, \
        !           494:                    (alp)->unlock_line);                                \
        !           495:        SLOCK_TRACE()                                                   \
        !           496:        SLOCK_DEBUGGER();                                               \
        !           497: } while (/*CONSTCOND*/0)
        !           498:
        !           499: /*
        !           500:  * Simple lock functions so that the debugger can see from whence
        !           501:  * they are being called.
        !           502:  */
        !           503: void
        !           504: simple_lock_init(struct simplelock *lkp)
        !           505: {
        !           506:
        !           507: #if defined(MULTIPROCESSOR) /* { */
        !           508:        __cpu_simple_lock_init(&alp->lock_data);
        !           509: #else
        !           510:        alp->lock_data = __SIMPLELOCK_UNLOCKED;
        !           511: #endif /* } */
        !           512:        alp->lock_file = NULL;
        !           513:        alp->lock_line = 0;
        !           514:        alp->unlock_file = NULL;
        !           515:        alp->unlock_line = 0;
        !           516:        alp->lock_holder = LK_NOCPU;
        !           517: }
        !           518:
        !           519: void
        !           520: _simple_lock(__volatile struct simplelock *lkp, const char *id, int l)
        !           521: {
        !           522:        cpuid_t cpu_id = CPU_NUMBER();
        !           523:        int s;
        !           524:
        !           525:        s = spllock();
        !           526:
        !           527:        /*
        !           528:         * MULTIPROCESSOR case: This is `safe' since if it's not us, we
        !           529:         * don't take any action, and just fall into the normal spin case.
        !           530:         */
        !           531:        if (alp->lock_data == __SIMPLELOCK_LOCKED) {
        !           532: #if defined(MULTIPROCESSOR) /* { */
        !           533:                if (alp->lock_holder == cpu_id) {
        !           534:                        SLOCK_WHERE("simple_lock: locking against myself\n",
        !           535:                            alp, id, l);
        !           536:                        goto out;
        !           537:                }
        !           538: #else
        !           539:                SLOCK_WHERE("simple_lock: lock held\n", alp, id, l);
        !           540:                goto out;
        !           541: #endif /* MULTIPROCESSOR */ /* } */
        !           542:        }
        !           543:
        !           544: #if defined(MULTIPROCESSOR) /* { */
        !           545:        /* Acquire the lock before modifying any fields. */
        !           546:        splx(s);
        !           547:        __cpu_simple_lock(&alp->lock_data);
        !           548:        s = spllock();
        !           549: #else
        !           550:        alp->lock_data = __SIMPLELOCK_LOCKED;
        !           551: #endif /* } */
        !           552:
        !           553:        if (alp->lock_holder != LK_NOCPU) {
        !           554:                SLOCK_WHERE("simple_lock: uninitialized lock\n",
        !           555:                    alp, id, l);
        !           556:        }
        !           557:        alp->lock_file = id;
        !           558:        alp->lock_line = l;
        !           559:        alp->lock_holder = cpu_id;
        !           560:
        !           561:        SLOCK_LIST_LOCK();
        !           562:        /* XXX Cast away volatile */
        !           563:        TAILQ_INSERT_TAIL(&simplelock_list, (struct simplelock *)alp, list);
        !           564:        SLOCK_LIST_UNLOCK();
        !           565:
        !           566:        SLOCK_COUNT(1);
        !           567:
        !           568:  out:
        !           569:        splx(s);
        !           570: }
        !           571:
        !           572: int
        !           573: _simple_lock_held(__volatile struct simplelock *alp)
        !           574: {
        !           575:        cpuid_t cpu_id = CPU_NUMBER();
        !           576:        int s, locked = 0;
        !           577:
        !           578:        s = spllock();
        !           579:
        !           580: #if defined(MULTIPROCESSOR)
        !           581:        if (__cpu_simple_lock_try(&alp->lock_data) == 0)
        !           582:                locked = (alp->lock_holder == cpu_id);
        !           583:        else
        !           584:                __cpu_simple_unlock(&alp->lock_data);
        !           585: #else
        !           586:        if (alp->lock_data == __SIMPLELOCK_LOCKED) {
        !           587:                locked = 1;
        !           588:                KASSERT(alp->lock_holder == cpu_id);
        !           589:        }
        !           590: #endif
        !           591:
        !           592:        splx(s);
        !           593:
        !           594:        return (locked);
        !           595: }
        !           596:
        !           597: int
        !           598: _simple_lock_try(__volatile struct simplelock *lkp, const char *id, int l)
        !           599: {
        !           600:        cpuid_t cpu_id = CPU_NUMBER();
        !           601:        int s, rv = 0;
        !           602:
        !           603:        s = spllock();
        !           604:
        !           605:        /*
        !           606:         * MULTIPROCESSOR case: This is `safe' since if it's not us, we
        !           607:         * don't take any action.
        !           608:         */
        !           609: #if defined(MULTIPROCESSOR) /* { */
        !           610:        if ((rv = __cpu_simple_lock_try(&alp->lock_data)) == 0) {
        !           611:                if (alp->lock_holder == cpu_id)
        !           612:                        SLOCK_WHERE("simple_lock_try: locking against myself\n",
        !           613:                            alp, id, l);
        !           614:                goto out;
        !           615:        }
        !           616: #else
        !           617:        if (alp->lock_data == __SIMPLELOCK_LOCKED) {
        !           618:                SLOCK_WHERE("simple_lock_try: lock held\n", alp, id, l);
        !           619:                goto out;
        !           620:        }
        !           621:        alp->lock_data = __SIMPLELOCK_LOCKED;
        !           622: #endif /* MULTIPROCESSOR */ /* } */
        !           623:
        !           624:        /*
        !           625:         * At this point, we have acquired the lock.
        !           626:         */
        !           627:
        !           628:        rv = 1;
        !           629:
        !           630:        alp->lock_file = id;
        !           631:        alp->lock_line = l;
        !           632:        alp->lock_holder = cpu_id;
        !           633:
        !           634:        SLOCK_LIST_LOCK();
        !           635:        /* XXX Cast away volatile. */
        !           636:        TAILQ_INSERT_TAIL(&simplelock_list, (struct simplelock *)alp, list);
        !           637:        SLOCK_LIST_UNLOCK();
        !           638:
        !           639:        SLOCK_COUNT(1);
        !           640:
        !           641:  out:
        !           642:        splx(s);
        !           643:        return (rv);
        !           644: }
        !           645:
        !           646: void
        !           647: _simple_unlock(__volatile struct simplelock *lkp, const char *id, int l)
        !           648: {
        !           649:        int s;
        !           650:
        !           651:        s = spllock();
        !           652:
        !           653:        /*
        !           654:         * MULTIPROCESSOR case: This is `safe' because we think we hold
        !           655:         * the lock, and if we don't, we don't take any action.
        !           656:         */
        !           657:        if (alp->lock_data == __SIMPLELOCK_UNLOCKED) {
        !           658:                SLOCK_WHERE("simple_unlock: lock not held\n",
        !           659:                    alp, id, l);
        !           660:                goto out;
        !           661:        }
        !           662:
        !           663:        SLOCK_LIST_LOCK();
        !           664:        TAILQ_REMOVE(&simplelock_list, alp, list);
        !           665:        SLOCK_LIST_UNLOCK();
        !           666:
        !           667:        SLOCK_COUNT(-1);
        !           668:
        !           669:        alp->list.tqe_next = NULL;      /* sanity */
        !           670:        alp->list.tqe_prev = NULL;      /* sanity */
        !           671:
        !           672:        alp->unlock_file = id;
        !           673:        alp->unlock_line = l;
        !           674:
        !           675: #if defined(MULTIPROCESSOR) /* { */
        !           676:        alp->lock_holder = LK_NOCPU;
        !           677:        /* Now that we've modified all fields, release the lock. */
        !           678:        __cpu_simple_unlock(&alp->lock_data);
        !           679: #else
        !           680:        alp->lock_data = __SIMPLELOCK_UNLOCKED;
        !           681:        KASSERT(alp->lock_holder == CPU_NUMBER());
        !           682:        alp->lock_holder = LK_NOCPU;
        !           683: #endif /* } */
        !           684:
        !           685:  out:
        !           686:        splx(s);
        !           687: }
        !           688:
        !           689: void
        !           690: simple_lock_dump(void)
        !           691: {
        !           692:        struct simplelock *alp;
        !           693:        int s;
        !           694:
        !           695:        s = spllock();
        !           696:        SLOCK_LIST_LOCK();
        !           697:        lock_printf("all simple locks:\n");
        !           698:        TAILQ_FOREACH(alp, &simplelock_list, list) {
        !           699:                lock_printf("%p CPU %lu %s:%d\n", alp, alp->lock_holder,
        !           700:                    alp->lock_file, alp->lock_line);
        !           701:        }
        !           702:        SLOCK_LIST_UNLOCK();
        !           703:        splx(s);
        !           704: }
        !           705:
        !           706: void
        !           707: simple_lock_freecheck(void *start, void *end)
        !           708: {
        !           709:        struct simplelock *alp;
        !           710:        int s;
        !           711:
        !           712:        s = spllock();
        !           713:        SLOCK_LIST_LOCK();
        !           714:        TAILQ_FOREACH(alp, &simplelock_list, list) {
        !           715:                if ((void *)alp >= start && (void *)alp < end) {
        !           716:                        lock_printf("freeing simple_lock %p CPU %lu %s:%d\n",
        !           717:                            alp, alp->lock_holder, alp->lock_file,
        !           718:                            alp->lock_line);
        !           719:                        SLOCK_DEBUGGER();
        !           720:                }
        !           721:        }
        !           722:        SLOCK_LIST_UNLOCK();
        !           723:        splx(s);
        !           724:  }
        !           725:
        !           726: /*
        !           727:  * We must be holding exactly one lock: the sched_lock.
        !           728:  */
        !           729:
        !           730: #ifdef notyet
        !           731: void
        !           732: simple_lock_switchcheck(void)
        !           733: {
        !           734:
        !           735:        simple_lock_only_held(&sched_lock, "switching");
        !           736: }
        !           737: #endif
        !           738:
        !           739: void
        !           740: simple_lock_only_held(volatile struct simplelock *lp, const char *where)
        !           741: {
        !           742:        struct simplelock *alp;
        !           743:        cpuid_t cpu_id = CPU_NUMBER();
        !           744:        int s;
        !           745:
        !           746:        if (lp) {
        !           747:                LOCK_ASSERT(simple_lock_held(lp));
        !           748:        }
        !           749:        s = spllock();
        !           750:        SLOCK_LIST_LOCK();
        !           751:        TAILQ_FOREACH(alp, &simplelock_list, list) {
        !           752:                if (alp == lp)
        !           753:                        continue;
        !           754:                if (alp->lock_holder == cpu_id)
        !           755:                        break;
        !           756:        }
        !           757:        SLOCK_LIST_UNLOCK();
        !           758:        splx(s);
        !           759:
        !           760:        if (alp != NULL) {
        !           761:                lock_printf("\n%s with held simple_lock %p "
        !           762:                    "CPU %lu %s:%d\n",
        !           763:                    where, alp, alp->lock_holder, alp->lock_file,
        !           764:                    alp->lock_line);
        !           765:                SLOCK_TRACE();
        !           766:                SLOCK_DEBUGGER();
        !           767:        }
        !           768: }
        !           769: #endif /* LOCKDEBUG */
        !           770:
        !           771: #if defined(MULTIPROCESSOR)
        !           772: /*
        !           773:  * Functions for manipulating the kernel_lock.  We put them here
        !           774:  * so that they show up in profiles.
        !           775:  */
        !           776:
        !           777: struct __mp_lock kernel_lock;
        !           778:
        !           779: void
        !           780: _kernel_lock_init(void)
        !           781: {
        !           782:        __mp_lock_init(&kernel_lock);
        !           783: }
        !           784:
        !           785: /*
        !           786:  * Acquire/release the kernel lock.  Intended for use in the scheduler
        !           787:  * and the lower half of the kernel.
        !           788:  */
        !           789:
        !           790: void
        !           791: _kernel_lock(void)
        !           792: {
        !           793:        SCHED_ASSERT_UNLOCKED();
        !           794:        __mp_lock(&kernel_lock);
        !           795: }
        !           796:
        !           797: void
        !           798: _kernel_unlock(void)
        !           799: {
        !           800:        __mp_unlock(&kernel_lock);
        !           801: }
        !           802:
        !           803: /*
        !           804:  * Acquire/release the kernel_lock on behalf of a process.  Intended for
        !           805:  * use in the top half of the kernel.
        !           806:  */
        !           807: void
        !           808: _kernel_proc_lock(struct proc *p)
        !           809: {
        !           810:        SCHED_ASSERT_UNLOCKED();
        !           811:        __mp_lock(&kernel_lock);
        !           812:        atomic_setbits_int(&p->p_flag, P_BIGLOCK);
        !           813: }
        !           814:
        !           815: void
        !           816: _kernel_proc_unlock(struct proc *p)
        !           817: {
        !           818:        atomic_clearbits_int(&p->p_flag, P_BIGLOCK);
        !           819:        __mp_unlock(&kernel_lock);
        !           820: }
        !           821:
        !           822: #ifdef MP_LOCKDEBUG
        !           823: /* CPU-dependent timing, needs this to be settable from ddb. */
        !           824: int __mp_lock_spinout = 200000000;
        !           825: #endif
        !           826:
        !           827: #endif /* MULTIPROCESSOR */

CVSweb