Annotation of XNU/osfmk/kern/lock.h, revision 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.