Annotation of XNU/iokit/Kernel/IOConditionLock.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* Copyright (c) 1997 Apple Computer, Inc.  All rights reserved.
                     23:  * Copyright (c) 1994-1996 NeXT Software, Inc.  All rights reserved. 
                     24:  *
                     25:  * AppleIOPSSafeCondLock.m. Lock object with exported condition variable, 
                     26:  *     kernel version.
                     27:  *
                     28:  * HISTORY
                     29:  * 1997-11-
                     30:  * 01-Aug-91    Doug Mitchell at NeXT
                     31:  *      Created. 
                     32:  */
                     33: 
                     34: #include <IOKit/IOConditionLock.h>
                     35: 
                     36: #define super OSObject
                     37: OSDefineMetaClassAndStructors(IOConditionLock, OSObject)
                     38: 
                     39: bool IOConditionLock::initWithCondition(int inCondition, bool inIntr = true)
                     40: {
                     41:     if (!super::init())
                     42:         return false;
                     43: 
                     44:     cond_interlock = IOLockAlloc();
                     45:     sleep_interlock = IOLockAlloc();
                     46: 
                     47:     condition = inCondition;
                     48:     want_lock    = false;
                     49:     waiting      = false;
                     50:     interruptible = (inIntr) ? THREAD_INTERRUPTIBLE : THREAD_UNINT;
                     51: 
                     52:     return cond_interlock && sleep_interlock;
                     53: }
                     54: 
                     55: IOConditionLock *IOConditionLock::withCondition(int condition, bool intr = true)
                     56: {
                     57:     IOConditionLock *me = new IOConditionLock;
                     58: 
                     59:     if (me && !me->initWithCondition(condition, intr)) {
                     60:         me->free();
                     61:         return 0;
                     62:     }
                     63: 
                     64:     return me;
                     65: }
                     66: void IOConditionLock::free()
                     67: {
                     68:     if (cond_interlock)
                     69:         IOLockFree(cond_interlock);
                     70:     if (sleep_interlock)
                     71:         IOLockFree(sleep_interlock);
                     72:     super::free();
                     73: }
                     74: 
                     75: bool IOConditionLock::getInterruptible() const
                     76: {
                     77:     return interruptible;
                     78: }
                     79: 
                     80: int IOConditionLock:: getCondition() const
                     81: {
                     82:     return condition;
                     83: }
                     84: 
                     85: int IOConditionLock:: setCondition(int inCondition)
                     86: {
                     87:     int old = condition;
                     88: 
                     89:     condition = inCondition;
                     90:     thread_wakeup_one((void *) &condition);
                     91: 
                     92:     return old;
                     93: }
                     94: 
                     95: void IOConditionLock::unlock()
                     96: {
                     97:     IOTakeLock(sleep_interlock);
                     98: 
                     99:     thread_wakeup_one((void *) &condition);
                    100: 
                    101:     want_lock = false;
                    102:     if (waiting) {
                    103:        waiting = false;
                    104:        thread_wakeup(this);    // Wakeup everybody
                    105:     }
                    106: 
                    107:     IOUnlock(sleep_interlock);
                    108: }
                    109: 
                    110: void IOConditionLock::unlockWith(int inCondition)
                    111: {
                    112:     IOTakeLock(sleep_interlock);
                    113:     IOTakeLock(cond_interlock);
                    114:     
                    115:     condition = inCondition;
                    116: 
                    117:     IOUnlock(cond_interlock);
                    118:     IOUnlock(sleep_interlock);
                    119: 
                    120:     unlock();
                    121: }
                    122: 
                    123: bool IOConditionLock::tryLock()
                    124: {
                    125:     bool result;
                    126: 
                    127:     IOTakeLock(sleep_interlock);
                    128: 
                    129:     result = !want_lock;
                    130:     if (result)
                    131:        want_lock = true;
                    132: 
                    133:     IOUnlock(sleep_interlock);
                    134: 
                    135:     return result;
                    136: }
                    137: 
                    138: int IOConditionLock::lock()
                    139: {
                    140:     int thread_res = THREAD_AWAKENED;
                    141: 
                    142:     IOTakeLock(sleep_interlock);
                    143:     
                    144:     /* Try to acquire the want_lock bit. */
                    145:     while (want_lock && thread_res == THREAD_AWAKENED)
                    146:     {
                    147:        waiting = true;
                    148: 
                    149:         assert_wait((void *) this, interruptible);     /* assert event */
                    150:        IOUnlock(sleep_interlock);                      /* release the lock */
                    151:        thread_block((void (*)(void)) 0);               /* block ourselves */
                    152: 
                    153:         IOTakeLock(sleep_interlock);
                    154:        thread_res = thread_wait_result();
                    155:     }
                    156:     if (thread_res == THREAD_AWAKENED)
                    157:        want_lock = true;
                    158:     
                    159:     IOUnlock(sleep_interlock);
                    160: 
                    161:     return thread_res;
                    162: }
                    163: 
                    164: int IOConditionLock::lockWhen(int inCondition)
                    165: {
                    166:     int thread_res;
                    167:     
                    168:     do
                    169:     {
                    170:        /* First get the actual lock */
                    171:        thread_res = lock();
                    172:        if (thread_res != THREAD_AWAKENED)
                    173:            break;      // Failed to acquire lock
                    174: 
                    175:        if (inCondition == condition)
                    176:            break;      // Hold lock and condition is expected value
                    177: 
                    178:        /*
                    179:         * Need to hold a IOTakeLock when we call thread_sleep().
                    180:         * Both _cond_interlock and want_lock must be held to 
                    181:         * change _condition.
                    182:         */
                    183:        IOTakeLock(cond_interlock);
                    184:         unlock();      // Release lock and sleep
                    185:        
                    186:        /*
                    187:         * this is the critical section on a multi in which
                    188:         * another thread could hold _sleep_interlock, but they 
                    189:         * can't change _condition. Holding _cond_interlock here
                    190:         * (until after assert_wait() is called from 
                    191:         * thread_sleep()) ensures that we'll be notified
                    192:         * of changes in _condition.
                    193:         */
                    194:         assert_wait((void *) &condition, interruptible); /* assert event */
                    195:        IOUnlock(cond_interlock);                       /* release the lock */
                    196:        thread_block((void (*)(void)) 0);               /* block ourselves */
                    197: 
                    198:        thread_res = thread_wait_result();
                    199:     } while (thread_res == THREAD_AWAKENED);
                    200:     
                    201:     return thread_res;
                    202: }

unix.superglobalmegacorp.com

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