|
|
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: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved. ! 25: * ! 26: * NXConditionLock.m. Lock object with exported condition variable, ! 27: * kernel version. ! 28: * ! 29: * HISTORY ! 30: * 01-Aug-91 Doug Mitchell at NeXT ! 31: * Created. ! 32: */ ! 33: ! 34: #define KERNEL 1 ! 35: #define KERNEL_PRIVATE 1 ! 36: #define ARCH_PRIVATE 1 ! 37: #undef MACH_USER_API ! 38: ! 39: #import <machkit/NXLock.h> ! 40: #import <kern/sched_prim.h> ! 41: #import <kernserv/lock.h> ! 42: ! 43: /* ! 44: * _priv instance variable points to one of these. ! 45: */ ! 46: struct _priv { ! 47: simple_lock_t spin_lock; ! 48: lock_t sleep_lock; ! 49: int conditionVar; ! 50: }; ! 51: ! 52: @implementation NXConditionLock ! 53: ! 54: - init ! 55: { ! 56: return [self initWith:0]; ! 57: } ! 58: ! 59: - initWith : (int)condition ! 60: { ! 61: struct _priv *p = _priv; ! 62: ! 63: [super init]; ! 64: ! 65: if (p == 0) { ! 66: p = (struct _priv *)kalloc(sizeof (struct _priv)); ! 67: p->spin_lock = simple_lock_alloc(); ! 68: p->sleep_lock = lock_alloc(); ! 69: ! 70: _priv = p; ! 71: } ! 72: ! 73: simple_lock_init(p->spin_lock); ! 74: lock_init(p->sleep_lock, TRUE); ! 75: p->conditionVar = condition; ! 76: ! 77: return self; ! 78: } ! 79: ! 80: - (int) condition ! 81: { ! 82: struct _priv *p = _priv; ! 83: ! 84: return (p->conditionVar); ! 85: } ! 86: ! 87: - free ! 88: { ! 89: struct _priv *p = _priv; ! 90: ! 91: if (p) { ! 92: lock_free(p->sleep_lock); ! 93: simple_lock_free(p->spin_lock); ! 94: kfree(p, sizeof (struct _priv)); ! 95: } ! 96: ! 97: return [super free]; ! 98: } ! 99: ! 100: - lock ! 101: { ! 102: struct _priv *p = _priv; ! 103: ! 104: lock_write(p->sleep_lock); ! 105: ! 106: return self; ! 107: } ! 108: ! 109: - unlock ! 110: { ! 111: struct _priv *p = _priv; ! 112: ! 113: thread_wakeup_one(&p->conditionVar); ! 114: lock_done(p->sleep_lock); ! 115: ! 116: return self; ! 117: } ! 118: ! 119: - lockWhen : (int)condition ! 120: { ! 121: struct _priv *p = _priv; ! 122: ! 123: /* ! 124: * First acquire ownership of the entire object. ! 125: */ ! 126: lock_write(p->sleep_lock); ! 127: while (condition != p->conditionVar) { ! 128: ! 129: /* ! 130: * Need to hold a simple_lock when we call thread_sleep(). ! 131: * Both _spin_lock and sleep_lock must be held to ! 132: * change _conditionVar. ! 133: */ ! 134: simple_lock(p->spin_lock); ! 135: lock_done(p->sleep_lock); ! 136: ! 137: /* ! 138: * this is the critical section on a multi in which ! 139: * another thread could hold _sleep_lock, but they ! 140: * can't change _conditionVar. Holding _spin_lock here ! 141: * (until after assert_wait() is called from ! 142: * thread_sleep()) ensures that we'll be notified ! 143: * of changes in _conditionVar. ! 144: */ ! 145: thread_sleep((void *)&p->conditionVar, p->spin_lock, FALSE); ! 146: lock_write(p->sleep_lock); ! 147: } ! 148: ! 149: return self; ! 150: } ! 151: ! 152: - unlockWith : (int)condition ! 153: { ! 154: struct _priv *p = _priv; ! 155: ! 156: /* ! 157: * _sleep_lock held, but not _spin_lock. ! 158: */ ! 159: simple_lock(p->spin_lock); ! 160: p->conditionVar = condition; ! 161: simple_unlock(p->spin_lock); ! 162: thread_wakeup_one(&p->conditionVar); ! 163: lock_done(p->sleep_lock); ! 164: ! 165: return self; ! 166: } ! 167: ! 168: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.