|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 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: /* ! 23: * Copyright (C) 1998 Apple Computer ! 24: * All Rights Reserved ! 25: */ ! 26: /* ! 27: * @OSF_COPYRIGHT@ ! 28: */ ! 29: /* ! 30: * Mach Operating System ! 31: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University ! 32: * All Rights Reserved. ! 33: * ! 34: * Permission to use, copy, modify and distribute this software and its ! 35: * documentation is hereby granted, provided that both the copyright ! 36: * notice and this permission notice appear in all copies of the ! 37: * software, derivative works or modified versions, and any portions ! 38: * thereof, and that both notices appear in supporting documentation. ! 39: * ! 40: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 41: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 42: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 43: * ! 44: * Carnegie Mellon requests users of this software to return to ! 45: * ! 46: * Software Distribution Coordinator or [email protected] ! 47: * School of Computer Science ! 48: * Carnegie Mellon University ! 49: * Pittsburgh PA 15213-3890 ! 50: * ! 51: * any improvements or extensions that they make and grant Carnegie Mellon ! 52: * the rights to redistribute these changes. ! 53: */ ! 54: /* ! 55: * File: kern/lock.h ! 56: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 57: * Date: 1985 ! 58: * ! 59: * Higher Level Locking primitives definitions ! 60: */ ! 61: ! 62: #ifndef _KERN_LOCK_H_ ! 63: #define _KERN_LOCK_H_ ! 64: ! 65: /* ! 66: * Configuration variables: ! 67: * ! 68: * ! 69: * MACH_LDEBUG: record pc and thread of callers, turn on ! 70: * all lock debugging. ! 71: * ! 72: * ! 73: * ETAP: The Event Trace Analysis Package (ETAP) monitors ! 74: * and records micro-kernel lock behavior and general ! 75: * kernel events. ETAP supports two levels of ! 76: * tracing for locks: ! 77: * - cumulative (ETAP_LOCK_ACCUMULATE) ! 78: * - monitored (ETAP_LOCK_MONITOR) ! 79: * ! 80: * Note: If either level of tracing is configured then ! 81: * ETAP_LOCK_TRACE is automatically defined to ! 82: * equal one. ! 83: * ! 84: * Several macros are added throughout the lock code to ! 85: * allow for convenient configuration. ! 86: */ ! 87: ! 88: #include <kern/simple_lock.h> ! 89: #include <machine/lock.h> ! 90: #include <mach/etap_events.h> ! 91: #include <mach/etap.h> ! 92: ! 93: /* ! 94: * The Mach lock package exports the following high-level ! 95: * lock abstractions: ! 96: * ! 97: * Lock Type Properties ! 98: * mutex blocking mutual exclusion lock, intended for ! 99: * SMP synchronization (vanishes on a uniprocessor); ! 100: * supports debugging, statistics, and pre-emption ! 101: * lock blocking synchronization permitting multiple ! 102: * simultaneous readers or a single writer; supports ! 103: * debugging and statistics but not pre-emption ! 104: * ! 105: * In general, mutex locks are preferred over all others, as the ! 106: * mutex supports pre-emption and relinquishes the processor ! 107: * upon contention. ! 108: * ! 109: */ ! 110: ! 111: /* ! 112: * A simple mutex lock. ! 113: * Do not change the order of the fields in this structure without ! 114: * changing the machine-dependent assembler routines which depend ! 115: * on them. ! 116: */ ! 117: #ifdef MACH_KERNEL_PRIVATE ! 118: #include <mach_ldebug.h> ! 119: #include <kern/etap_options.h> ! 120: #include <kern/etap_pool.h> ! 121: ! 122: typedef struct { ! 123: hw_lock_data_t interlock; ! 124: hw_lock_data_t locked; ! 125: short waiters; ! 126: #if MACH_LDEBUG ! 127: int type; ! 128: #define MUTEX_TAG 0x4d4d ! 129: vm_offset_t pc; ! 130: vm_offset_t thread; ! 131: #endif /* MACH_LDEBUG */ ! 132: #if ETAP_LOCK_TRACE ! 133: union { /* Must be overlaid on the event_tablep */ ! 134: struct event_table_chain event_table_chain; ! 135: struct { ! 136: event_table_t event_tablep; /* ptr to event table entry */ ! 137: etap_time_t start_hold_time; /* Time of last acquistion */ ! 138: } s; ! 139: } u; ! 140: #endif /* ETAP_LOCK_TRACE */ ! 141: #if ETAP_LOCK_ACCUMULATE ! 142: cbuff_entry_t cbuff_entry; /* cumulative buffer entry */ ! 143: #endif /* ETAP_LOCK_ACCUMULATE */ ! 144: #if ETAP_LOCK_MONITOR ! 145: vm_offset_t start_pc; /* pc where lock operation began */ ! 146: vm_offset_t end_pc; /* pc where lock operation ended */ ! 147: #endif /* ETAP_LOCK_MONITOR */ ! 148: } mutex_t; ! 149: ! 150: #define decl_mutex_data(class,name) class mutex_t name; ! 151: #if MACH_LDEBUG ! 152: #define mutex_held(m) (hw_lock_held(&((m)->locked)) && \ ! 153: ((m)->thread == (int)current_thread())) ! 154: #else /* MACH_LDEBUG */ ! 155: #define mutex_held(m) hw_lock_held(&((m)->locked)) ! 156: #endif /* MACH_LDEBUG */ ! 157: ! 158: #else /* MACH_KERNEL_PRIVATE */ ! 159: ! 160: typedef struct __mutex__ mutex_t; ! 161: extern boolean_t mutex_held(mutex_t*); ! 162: ! 163: #endif /* !MACH_KERNEL_PRIVATE */ ! 164: ! 165: extern mutex_t *mutex_alloc (etap_event_t); ! 166: extern void mutex_free (mutex_t*); ! 167: ! 168: extern void mutex_init (mutex_t*, etap_event_t); ! 169: extern void _mutex_lock (mutex_t*); ! 170: extern void mutex_unlock (mutex_t*); ! 171: extern boolean_t _mutex_try (mutex_t*); ! 172: ! 173: extern void mutex_lock_wait (mutex_t*); ! 174: extern void mutex_unlock_wakeup (mutex_t*); ! 175: extern void mutex_pause (void); ! 176: extern void interlock_unlock (hw_lock_t); ! 177: ! 178: /* ! 179: * The general lock structure. Provides for multiple readers, ! 180: * upgrading from read to write, and sleeping until the lock ! 181: * can be gained. ! 182: * ! 183: * On some architectures, assembly language code in the 'inline' ! 184: * program fiddles the lock structures. It must be changed in ! 185: * concert with the structure layout. ! 186: * ! 187: * Only the "interlock" field is used for hardware exclusion; ! 188: * other fields are modified with normal instructions after ! 189: * acquiring the interlock bit. ! 190: */ ! 191: #ifdef MACH_KERNEL_PRIVATE ! 192: typedef struct { ! 193: decl_simple_lock_data(,interlock) /* "hardware" interlock field */ ! 194: volatile unsigned int ! 195: read_count:16, /* No. of accepted readers */ ! 196: want_upgrade:1, /* Read-to-write upgrade waiting */ ! 197: want_write:1, /* Writer is waiting, or ! 198: locked for write */ ! 199: waiting:1, /* Someone is sleeping on lock */ ! 200: can_sleep:1; /* Can attempts to lock go to sleep? */ ! 201: #if ETAP_LOCK_TRACE ! 202: union { /* Must be overlaid on the event_tablep */ ! 203: struct event_table_chain event_table_chain; ! 204: struct { ! 205: event_table_t event_tablep; /* ptr to event table entry */ ! 206: start_data_node_t start_list; /* linked list of start times ! 207: and pcs */ ! 208: } s; ! 209: } u; ! 210: #endif /* ETAP_LOCK_TRACE */ ! 211: #if ETAP_LOCK_ACCUMULATE ! 212: cbuff_entry_t cbuff_write; /* write cumulative buffer entry */ ! 213: cbuff_entry_t cbuff_read; /* read cumulative buffer entry */ ! 214: #endif /* ETAP_LOCK_ACCUMULATE */ ! 215: } lock_t; ! 216: ! 217: /* Sleep locks must work even if no multiprocessing */ ! 218: ! 219: /* ! 220: * Complex lock operations ! 221: */ ! 222: ! 223: #if ETAP ! 224: /* ! 225: * Locks have a pointer into an event_table entry that names the ! 226: * corresponding lock event and controls whether it is being traced. ! 227: * Initially this pointer is into a read-only table event_table_init[]. ! 228: * Once dynamic allocation becomes possible a modifiable copy of the table ! 229: * is allocated and pointers are set to within this copy. The pointers ! 230: * that were already in place at that point need to be switched to point ! 231: * into the copy. To do this we overlay the event_table_chain structure ! 232: * onto sufficiently-big elements of the various lock structures so we ! 233: * can sweep down this list switching the pointers. The assumption is ! 234: * that we will not want to enable tracing before this is done (which is ! 235: * after all during kernel bootstrap, before any user tasks are launched). ! 236: * ! 237: * This is admittedly rather ugly but so were the alternatives: ! 238: * - record the event_table pointers in a statically-allocated array ! 239: * (dynamic allocation not yet being available) -- but there were ! 240: * over 8000 of them; ! 241: * - add a new link field to each lock structure; ! 242: * - change pointers to array indices -- this adds quite a bit of ! 243: * arithmetic to every lock operation that might be traced. ! 244: */ ! 245: #define lock_event_table(lockp) ((lockp)->u.s.event_tablep) ! 246: #define lock_start_hold_time(lockp) ((lockp)->u.s.start_hold_time) ! 247: #endif /* ETAP_LOCK_TRACE */ ! 248: ! 249: extern void lock_init (lock_t*, ! 250: boolean_t, ! 251: etap_event_t, ! 252: etap_event_t); ! 253: ! 254: #else /* MACH_KERNEL_PRIVATE */ ! 255: ! 256: typedef struct __lock__ lock_t; ! 257: extern lock_t *lock_alloc(boolean_t, etap_event_t, etap_event_t); ! 258: void lock_free(lock_t *); ! 259: ! 260: #endif /* !MACH_KERNEL_PRIVATE */ ! 261: ! 262: extern void lock_write (lock_t*); ! 263: extern void lock_read (lock_t*); ! 264: extern void lock_done (lock_t*); ! 265: extern void lock_write_to_read (lock_t*); ! 266: ! 267: #define lock_read_done(l) lock_done(l) ! 268: #define lock_write_done(l) lock_done(l) ! 269: ! 270: extern boolean_t lock_read_to_write (lock_t*); /* vm_map is only user */ ! 271: extern unsigned int LockTimeOut; /* Standard lock timeout value */ ! 272: ! 273: #endif /* _KERN_LOCK_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.