Annotation of kernel/kern/lock.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1993-1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  *     File:   kern/lock.c
                     52:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     53:  *     Date:   1985
                     54:  *
                     55:  *     Locking primitives implementation
                     56:  */
                     57: 
                     58: #include <cpus.h>
                     59: 
                     60: #include <kern/lock.h>
                     61: #include <kern/thread.h>
                     62: #include <kern/sched_prim.h>
                     63: 
                     64: 
                     65: #if (DIAGNOSTIC && defined(__ppc__))
                     66: void
                     67: simple_lock(
                     68:     simple_lock_t       slock)
                     69: {
                     70:        real_simple_lock(slock); /* inline in mach/{ppc,i386}/simple_lock.h */
                     71:        slock->lock_data[1] = (int)(current_thread());
                     72: }
                     73: #endif /* DIAGNOSTIC */
                     74: 
                     75: #if    NCPUS > 1
                     76: 
                     77: /*
                     78:  *     Module:         lock
                     79:  *     Function:
                     80:  *             Provide reader/writer sychronization.
                     81:  *     Implementation:
                     82:  *             Simple interlock on a bit.  Readers first interlock,
                     83:  *             increment the reader count, then let go.  Writers hold
                     84:  *             the interlock (thus preventing further readers), and
                     85:  *             wait for already-accepted readers to go away.
                     86:  */
                     87: 
                     88: /*
                     89:  *     The simple-lock routines are the primitives out of which
                     90:  *     the lock package is built.  The implementation is left
                     91:  *     to the machine-dependent code.
                     92:  */
                     93: 
                     94: #ifdef notdef
                     95: /*
                     96:  *     A sample implementation of simple locks.
                     97:  *     assumes:
                     98:  *             boolean_t test_and_set(boolean_t *)
                     99:  *                     indivisibly sets the boolean to TRUE
                    100:  *                     and returns its old value
                    101:  *             and that setting a boolean to FALSE is indivisible.
                    102:  */
                    103: /*
                    104:  *     simple_lock_init initializes a simple lock.  A simple lock
                    105:  *     may only be used for exclusive locks.
                    106:  */
                    107: 
                    108: void simple_lock_init(simple_lock_t l)
                    109: {
                    110:        *(boolean_t *)l = FALSE;
                    111: }
                    112: 
                    113: void simple_lock(simple_lock_t l)
                    114: {
                    115:        while (test_and_set((boolean_t *)l))
                    116:                continue;
                    117: }
                    118: 
                    119: void simple_unlock(simple_lock_t l)
                    120: {
                    121:        *(boolean_t *)l = FALSE;
                    122: }
                    123: 
                    124: boolean_t simple_lock_try(simple_lock_t l)
                    125: {
                    126:        return (!test_and_set((boolean_t *)l));
                    127: }
                    128: #endif /* notdef */
                    129: #endif /* NCPUS > 1 */
                    130: 
                    131: #if    NCPUS > 1
                    132: int lock_wait_time = 100;
                    133: #else  /* NCPUS > 1 */
                    134: 
                    135:        /*
                    136:         *      It is silly to spin on a uni-processor as if we
                    137:         *      thought something magical would happen to the
                    138:         *      want_write bit while we are executing.
                    139:         */
                    140: int lock_wait_time = 0;
                    141: #endif /* NCPUS > 1 */
                    142: 
                    143: simple_lock_t simple_lock_alloc(void)
                    144: {
                    145: #if    MACH_SLOCKS
                    146:        return (simple_lock_t)kalloc(sizeof(simple_lock_data_t));
                    147: #else  MACH_SLOCKS
                    148:        return 0;
                    149: #endif MACH_SLOCKS
                    150: }
                    151: 
                    152: void simple_lock_free(
                    153:        simple_lock_t l)
                    154: {
                    155: #if    MACH_SLOCKS
                    156:        kfree(l, sizeof(*l));
                    157: #endif MACH_SLOCKS
                    158: }
                    159: 
                    160: /*
                    161:  *     Routine:        lock_alloc
                    162:  *     Function:
                    163:  *             Allocate a lock_t data structure.  Used by loadable
                    164:  *             servers that can't allocate a lock statically.
                    165:  */
                    166: lock_t lock_alloc(void)
                    167: {
                    168:        return (lock_t)kalloc(sizeof(lock_data_t));
                    169: }
                    170: 
                    171: /*
                    172:  *     Routine:        lock_free
                    173:  *     Function:
                    174:  *             Free a lock allocated by lock_alloc()
                    175:  */
                    176: void lock_free(
                    177:        lock_t  l)
                    178: {
                    179:        kfree(l, sizeof(lock_data_t));
                    180: }
                    181: 
                    182: /*
                    183:  *     Routine:        lock_init
                    184:  *     Function:
                    185:  *             Initialize a lock; required before use.
                    186:  *             Note that clients declare the "struct lock"
                    187:  *             variables and then initialize them, rather
                    188:  *             than getting a new one from this module.
                    189:  */
                    190: void lock_init(
                    191:        lock_t          l,
                    192:        boolean_t       can_sleep)
                    193: {
                    194:        bzero((char *)l, sizeof(lock_data_t));
                    195:        simple_lock_init(&l->interlock);
                    196:        l->want_write = FALSE;
                    197:        l->want_upgrade = FALSE;
                    198:        l->read_count = 0;
                    199:        l->can_sleep = can_sleep;
                    200:        l->thread = (struct thread *)-1;        /* XXX */
                    201:        l->recursion_depth = 0;
                    202: }
                    203: 
                    204: void lock_sleepable(
                    205:        lock_t          l,
                    206:        boolean_t       can_sleep)
                    207: {
                    208:        simple_lock(&l->interlock);
                    209:        l->can_sleep = can_sleep;
                    210:        simple_unlock(&l->interlock);
                    211: }
                    212: 
                    213: 
                    214: /*
                    215:  *     Sleep locks.  These use the same data structure and algorithm
                    216:  *     as the spin locks, but the process sleeps while it is waiting
                    217:  *     for the lock.  These work on uniprocessor systems.
                    218:  */
                    219: 
                    220: void lock_write(
                    221:        register lock_t l)
                    222: {
                    223:        register int    i;
                    224: 
                    225:        simple_lock(&l->interlock);
                    226: 
                    227:        if (l->thread == current_thread()) {
                    228:                /*
                    229:                 *      Recursive lock.
                    230:                 */
                    231:                l->recursion_depth++;
                    232:                simple_unlock(&l->interlock);
                    233:                return;
                    234:        }
                    235: 
                    236:        /*
                    237:         *      Try to acquire the want_write bit.
                    238:         */
                    239:        while (l->want_write) {
                    240:                if ((i = lock_wait_time) > 0) {
                    241:                        simple_unlock(&l->interlock);
                    242:                        while (--i > 0 && l->want_write)
                    243:                                continue;
                    244:                        simple_lock(&l->interlock);
                    245:                }
                    246: 
                    247:                if (l->can_sleep && l->want_write) {
                    248:                        l->waiting = TRUE;
                    249:                        thread_sleep(l,
                    250:                                simple_lock_addr(l->interlock), FALSE);
                    251:                        simple_lock(&l->interlock);
                    252:                }
                    253:        }
                    254:        l->want_write = TRUE;
                    255: 
                    256:        /* Wait for readers (and upgrades) to finish */
                    257: 
                    258:        while ((l->read_count != 0) || l->want_upgrade) {
                    259:                if ((i = lock_wait_time) > 0) {
                    260:                        simple_unlock(&l->interlock);
                    261:                        while (--i > 0 && (l->read_count != 0 ||
                    262:                                        l->want_upgrade))
                    263:                                continue;
                    264:                        simple_lock(&l->interlock);
                    265:                }
                    266: 
                    267:                if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) {
                    268:                        l->waiting = TRUE;
                    269:                        thread_sleep(l,
                    270:                                simple_lock_addr(l->interlock), FALSE);
                    271:                        simple_lock(&l->interlock);
                    272:                }
                    273:        }
                    274:        simple_unlock(&l->interlock);
                    275: }
                    276: 
                    277: void lock_done(
                    278:        register lock_t l)
                    279: {
                    280:        simple_lock(&l->interlock);
                    281: 
                    282:        if (l->read_count != 0)
                    283:                l->read_count--;
                    284:        else
                    285:        if (l->recursion_depth != 0)
                    286:                l->recursion_depth--;
                    287:        else
                    288:        if (l->want_upgrade)
                    289:                l->want_upgrade = FALSE;
                    290:        else
                    291:                l->want_write = FALSE;
                    292: 
                    293:        /*
                    294:         *      There is no reason to wakeup a waiting thread
                    295:         *      if the read-count is non-zero.  Consider:
                    296:         *              we must be dropping a read lock
                    297:         *              threads are waiting only if one wants a write lock
                    298:         *              if there are still readers, they can't proceed
                    299:         */
                    300: 
                    301:        if (l->waiting && (l->read_count == 0)) {
                    302:                l->waiting = FALSE;
                    303:                thread_wakeup(l);
                    304:        }
                    305: 
                    306:        simple_unlock(&l->interlock);
                    307: }
                    308: 
                    309: void lock_read(
                    310:        register lock_t l)
                    311: {
                    312:        register int    i;
                    313: 
                    314:        simple_lock(&l->interlock);
                    315: 
                    316:        if (l->thread == current_thread()) {
                    317:                /*
                    318:                 *      Recursive lock.
                    319:                 */
                    320:                l->read_count++;
                    321:                simple_unlock(&l->interlock);
                    322:                return;
                    323:        }
                    324: 
                    325:        while (l->want_write || l->want_upgrade) {
                    326:                if ((i = lock_wait_time) > 0) {
                    327:                        simple_unlock(&l->interlock);
                    328:                        while (--i > 0 && (l->want_write || l->want_upgrade))
                    329:                                continue;
                    330:                        simple_lock(&l->interlock);
                    331:                }
                    332: 
                    333:                if (l->can_sleep && (l->want_write || l->want_upgrade)) {
                    334:                        l->waiting = TRUE;
                    335:                        thread_sleep(l,
                    336:                                simple_lock_addr(l->interlock), FALSE);
                    337:                        simple_lock(&l->interlock);
                    338:                }
                    339:        }
                    340: 
                    341:        l->read_count++;
                    342:        simple_unlock(&l->interlock);
                    343: }
                    344: 
                    345: /*
                    346:  *     Routine:        lock_read_to_write
                    347:  *     Function:
                    348:  *             Improves a read-only lock to one with
                    349:  *             write permission.  If another reader has
                    350:  *             already requested an upgrade to a write lock,
                    351:  *             no lock is held upon return.
                    352:  *
                    353:  *             Returns TRUE if the upgrade *failed*.
                    354:  */
                    355: boolean_t lock_read_to_write(
                    356:        register lock_t l)
                    357: {
                    358:        register int    i;
                    359: 
                    360:        simple_lock(&l->interlock);
                    361: 
                    362:        l->read_count--;
                    363: 
                    364:        if (l->thread == current_thread()) {
                    365:                /*
                    366:                 *      Recursive lock.
                    367:                 */
                    368:                l->recursion_depth++;
                    369:                simple_unlock(&l->interlock);
                    370:                return(FALSE);
                    371:        }
                    372: 
                    373:        if (l->want_upgrade) {
                    374:                /*
                    375:                 *      Someone else has requested upgrade.
                    376:                 *      Since we've released a read lock, wake
                    377:                 *      him up.
                    378:                 */
                    379:                if (l->waiting && (l->read_count == 0)) {
                    380:                        l->waiting = FALSE;
                    381:                        thread_wakeup(l);
                    382:                }
                    383: 
                    384:                simple_unlock(&l->interlock);
                    385:                return TRUE;
                    386:        }
                    387: 
                    388:        l->want_upgrade = TRUE;
                    389: 
                    390:        while (l->read_count != 0) {
                    391:                if ((i = lock_wait_time) > 0) {
                    392:                        simple_unlock(&l->interlock);
                    393:                        while (--i > 0 && l->read_count != 0)
                    394:                                continue;
                    395:                        simple_lock(&l->interlock);
                    396:                }
                    397: 
                    398:                if (l->can_sleep && l->read_count != 0) {
                    399:                        l->waiting = TRUE;
                    400:                        thread_sleep(l,
                    401:                                simple_lock_addr(l->interlock), FALSE);
                    402:                        simple_lock(&l->interlock);
                    403:                }
                    404:        }
                    405: 
                    406:        simple_unlock(&l->interlock);
                    407:        return FALSE;
                    408: }
                    409: 
                    410: void lock_write_to_read(
                    411:        register lock_t l)
                    412: {
                    413:        simple_lock(&l->interlock);
                    414: 
                    415:        l->read_count++;
                    416:        if (l->recursion_depth != 0)
                    417:                l->recursion_depth--;
                    418:        else
                    419:        if (l->want_upgrade)
                    420:                l->want_upgrade = FALSE;
                    421:        else
                    422:                l->want_write = FALSE;
                    423: 
                    424:        if (l->waiting) {
                    425:                l->waiting = FALSE;
                    426:                thread_wakeup(l);
                    427:        }
                    428: 
                    429:        simple_unlock(&l->interlock);
                    430: }
                    431: 
                    432: 
                    433: /*
                    434:  *     Routine:        lock_try_write
                    435:  *     Function:
                    436:  *             Tries to get a write lock.
                    437:  *
                    438:  *             Returns FALSE if the lock is not held on return.
                    439:  */
                    440: 
                    441: boolean_t lock_try_write(
                    442:        register lock_t l)
                    443: {
                    444:        simple_lock(&l->interlock);
                    445: 
                    446:        if (l->thread == current_thread()) {
                    447:                /*
                    448:                 *      Recursive lock
                    449:                 */
                    450:                l->recursion_depth++;
                    451:                simple_unlock(&l->interlock);
                    452:                return TRUE;
                    453:        }
                    454: 
                    455:        if (l->want_write || l->want_upgrade || l->read_count) {
                    456:                /*
                    457:                 *      Can't get lock.
                    458:                 */
                    459:                simple_unlock(&l->interlock);
                    460:                return FALSE;
                    461:        }
                    462: 
                    463:        /*
                    464:         *      Have lock.
                    465:         */
                    466: 
                    467:        l->want_write = TRUE;
                    468:        simple_unlock(&l->interlock);
                    469:        return TRUE;
                    470: }
                    471: 
                    472: /*
                    473:  *     Routine:        lock_try_read
                    474:  *     Function:
                    475:  *             Tries to get a read lock.
                    476:  *
                    477:  *             Returns FALSE if the lock is not held on return.
                    478:  */
                    479: 
                    480: boolean_t lock_try_read(
                    481:        register lock_t l)
                    482: {
                    483:        simple_lock(&l->interlock);
                    484: 
                    485:        if (l->thread == current_thread()) {
                    486:                /*
                    487:                 *      Recursive lock
                    488:                 */
                    489:                l->read_count++;
                    490:                simple_unlock(&l->interlock);
                    491:                return TRUE;
                    492:        }
                    493: 
                    494:        if (l->want_write || l->want_upgrade) {
                    495:                simple_unlock(&l->interlock);
                    496:                return FALSE;
                    497:        }
                    498: 
                    499:        l->read_count++;
                    500:        simple_unlock(&l->interlock);
                    501:        return TRUE;
                    502: }
                    503: 
                    504: /*
                    505:  *     Routine:        lock_try_read_to_write
                    506:  *     Function:
                    507:  *             Improves a read-only lock to one with
                    508:  *             write permission.  If another reader has
                    509:  *             already requested an upgrade to a write lock,
                    510:  *             the read lock is still held upon return.
                    511:  *
                    512:  *             Returns FALSE if the upgrade *failed*.
                    513:  */
                    514: boolean_t lock_try_read_to_write(
                    515:        register lock_t l)
                    516: {
                    517:        simple_lock(&l->interlock);
                    518: 
                    519:        if (l->thread == current_thread()) {
                    520:                /*
                    521:                 *      Recursive lock
                    522:                 */
                    523:                l->read_count--;
                    524:                l->recursion_depth++;
                    525:                simple_unlock(&l->interlock);
                    526:                return TRUE;
                    527:        }
                    528: 
                    529:        if (l->want_upgrade) {
                    530:                simple_unlock(&l->interlock);
                    531:                return FALSE;
                    532:        }
                    533:        l->want_upgrade = TRUE;
                    534:        l->read_count--;
                    535: 
                    536:        while (l->read_count != 0) {
                    537:                l->waiting = TRUE;
                    538:                thread_sleep(l,
                    539:                        simple_lock_addr(l->interlock), FALSE);
                    540:                simple_lock(&l->interlock);
                    541:        }
                    542: 
                    543:        simple_unlock(&l->interlock);
                    544:        return TRUE;
                    545: }
                    546: 
                    547: /*
                    548:  *     Allow a process that has a lock for write to acquire it
                    549:  *     recursively (for read, write, or update).
                    550:  */
                    551: void lock_set_recursive(
                    552:        lock_t          l)
                    553: {
                    554:        simple_lock(&l->interlock);
                    555:        if (!l->want_write) {
                    556:                panic("lock_set_recursive: don't have write lock");
                    557:        }
                    558:        l->thread = current_thread();
                    559:        simple_unlock(&l->interlock);
                    560: }
                    561: 
                    562: /*
                    563:  *     Prevent a lock from being re-acquired.
                    564:  */
                    565: void lock_clear_recursive(
                    566:        lock_t          l)
                    567: {
                    568:        simple_lock(&l->interlock);
                    569:        if (l->thread != current_thread()) {
                    570:                panic("lock_clear_recursive: wrong thread");
                    571:        }
                    572:        if (l->recursion_depth == 0)
                    573:                l->thread = (struct thread *)-1;        /* XXX */
                    574:        simple_unlock(&l->interlock);
                    575: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.