Annotation of XNU/osfmk/kern/lock.h, revision 1.1.1.1

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_ */

unix.superglobalmegacorp.com

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