|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1993-1987 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: kern/lock.h
28: * Author: Avadis Tevanian, Jr., Michael Wayne Young
29: * Date: 1985
30: *
31: * Locking primitives definitions
32: */
33:
34: #ifndef _KERN_LOCK_H_
35: #define _KERN_LOCK_H_
36:
37: #include <mach/boolean.h>
38: #include <mach/machine/vm_types.h>
39:
40: #if NCPUS > 1
41: #include <machine/lock.h>/*XXX*/
42: #endif
43:
44: #define MACH_SLOCKS ((NCPUS > 1) || MACH_LDEBUG)
45:
46: /*
47: * A simple spin lock.
48: */
49:
50: struct slock {
51: volatile natural_t lock_data; /* in general 1 bit is sufficient */
1.1.1.4 ! root 52: struct {} is_a_simple_lock;
1.1 root 53: };
54:
1.1.1.4 ! root 55: /*
! 56: * Used by macros to assert that the given argument is a simple
! 57: * lock.
! 58: */
! 59: #define simple_lock_assert(l) (void) &(l)->is_a_simple_lock
! 60:
1.1 root 61: typedef struct slock simple_lock_data_t;
62: typedef struct slock *simple_lock_t;
63:
64: #if MACH_SLOCKS
65: /*
66: * Use the locks.
67: */
68:
69: #define decl_simple_lock_data(class,name) \
70: class simple_lock_data_t name;
71:
1.1.1.4 ! root 72: #define simple_lock_addr(lock) (simple_lock_assert(&(lock)), \
! 73: &(lock))
1.1 root 74:
75: #if (NCPUS > 1)
76:
77: /*
78: * The single-CPU debugging routines are not valid
79: * on a multiprocessor.
80: */
1.1.1.4 ! root 81: #define simple_lock_taken(lock) (simple_lock_assert(lock), \
! 82: 1) /* always succeeds */
1.1 root 83: #define check_simple_locks()
1.1.1.4 ! root 84: #define check_simple_locks_enable()
! 85: #define check_simple_locks_disable()
1.1 root 86:
87: #else /* NCPUS > 1 */
88: /*
89: * Use our single-CPU locking test routines.
90: */
91:
92: extern void simple_lock_init(simple_lock_t);
1.1.1.4 ! root 93: extern void _simple_lock(simple_lock_t,
! 94: const char *, const char *);
1.1 root 95: extern void simple_unlock(simple_lock_t);
1.1.1.4 ! root 96: extern boolean_t _simple_lock_try(simple_lock_t,
! 97: const char *, const char *);
! 98:
! 99: /* We provide simple_lock and simple_lock_try so that we can save the
! 100: location. */
! 101: #define XSTR(x) #x
! 102: #define STR(x) XSTR(x)
! 103: #define LOCATION __FILE__ ":" STR(__LINE__)
! 104:
! 105: #define simple_lock(lock) _simple_lock((lock), #lock, LOCATION)
! 106: #define simple_lock_try(lock) _simple_lock_try((lock), #lock, LOCATION)
1.1 root 107:
108: #define simple_lock_pause()
1.1.1.4 ! root 109: #define simple_lock_taken(lock) (simple_lock_assert(lock), \
! 110: (lock)->lock_data)
1.1 root 111:
112: extern void check_simple_locks(void);
1.1.1.4 ! root 113: extern void check_simple_locks_enable(void);
! 114: extern void check_simple_locks_disable(void);
1.1 root 115:
116: #endif /* NCPUS > 1 */
117:
118: #else /* MACH_SLOCKS */
119: /*
120: * Do not allocate storage for locks if not needed.
121: */
1.1.1.4 ! root 122: struct simple_lock_data_empty { struct {} is_a_simple_lock; };
! 123: #define decl_simple_lock_data(class,name) \
1.1.1.3 root 124: class struct simple_lock_data_empty name;
1.1.1.4 ! root 125: #define simple_lock_addr(lock) (simple_lock_assert(&(lock)), \
! 126: (simple_lock_t)0)
1.1 root 127:
128: /*
129: * No multiprocessor locking is necessary.
130: */
1.1.1.4 ! root 131: #define simple_lock_init(l) simple_lock_assert(l)
! 132: #define simple_lock(l) simple_lock_assert(l)
! 133: #define simple_unlock(l) simple_lock_assert(l)
! 134: #define simple_lock_try(l) (simple_lock_assert(l), \
! 135: TRUE) /* always succeeds */
! 136: #define simple_lock_taken(l) (simple_lock_assert(l), \
! 137: 1) /* always succeeds */
1.1 root 138: #define check_simple_locks()
1.1.1.4 ! root 139: #define check_simple_locks_enable()
! 140: #define check_simple_locks_disable()
1.1 root 141: #define simple_lock_pause()
142:
143: #endif /* MACH_SLOCKS */
144:
145:
146: #define decl_mutex_data(class,name) decl_simple_lock_data(class,name)
147: #define mutex_try(l) simple_lock_try(l)
148: #define mutex_lock(l) simple_lock(l)
149: #define mutex_unlock(l) simple_unlock(l)
150: #define mutex_init(l) simple_lock_init(l)
151:
152:
153: /*
154: * The general lock structure. Provides for multiple readers,
155: * upgrading from read to write, and sleeping until the lock
156: * can be gained.
157: *
158: * On some architectures, assembly language code in the 'inline'
159: * program fiddles the lock structures. It must be changed in
160: * concert with the structure layout.
161: *
162: * Only the "interlock" field is used for hardware exclusion;
163: * other fields are modified with normal instructions after
164: * acquiring the interlock bit.
165: */
166: struct lock {
167: struct thread *thread; /* Thread that has lock, if
168: recursive locking allowed */
169: unsigned int read_count:16, /* Number of accepted readers */
170: /* boolean_t */ want_upgrade:1, /* Read-to-write upgrade waiting */
171: /* boolean_t */ want_write:1, /* Writer is waiting, or
172: locked for write */
173: /* boolean_t */ waiting:1, /* Someone is sleeping on lock */
174: /* boolean_t */ can_sleep:1, /* Can attempts to lock go to sleep? */
175: recursion_depth:12, /* Depth of recursion */
176: :0;
1.1.1.4 ! root 177: #if MACH_LDEBUG
! 178: struct thread *writer;
! 179: #endif /* MACH_LDEBUG */
1.1 root 180: decl_simple_lock_data(,interlock)
181: /* Hardware interlock field.
182: Last in the structure so that
183: field offsets are the same whether
184: or not it is present. */
185: };
186:
187: typedef struct lock lock_data_t;
188: typedef struct lock *lock_t;
189:
190: /* Sleep locks must work even if no multiprocessing */
191:
192: extern void lock_init(lock_t, boolean_t);
193: extern void lock_sleepable(lock_t, boolean_t);
194: extern void lock_write(lock_t);
195: extern void lock_read(lock_t);
196: extern void lock_done(lock_t);
197: extern boolean_t lock_read_to_write(lock_t);
198: extern void lock_write_to_read(lock_t);
199: extern boolean_t lock_try_write(lock_t);
200: extern boolean_t lock_try_read(lock_t);
201: extern boolean_t lock_try_read_to_write(lock_t);
202:
203: #define lock_read_done(l) lock_done(l)
204: #define lock_write_done(l) lock_done(l)
205:
206: extern void lock_set_recursive(lock_t);
207: extern void lock_clear_recursive(lock_t);
208:
1.1.1.4 ! root 209: /* Lock debugging support. */
! 210: #if ! MACH_LDEBUG
! 211: #define have_read_lock(l) 1
! 212: #define have_write_lock(l) 1
! 213: #else /* MACH_LDEBUG */
! 214: /* XXX: We don't keep track of readers, so this is an approximation. */
! 215: #define have_read_lock(l) ((l)->read_count > 0)
! 216: #define have_write_lock(l) ((l)->writer == current_thread())
! 217: #endif /* MACH_LDEBUG */
! 218: #define have_lock(l) (have_read_lock(l) || have_write_lock(l))
! 219:
1.1.1.2 root 220: void db_show_all_slocks(void);
221:
1.1 root 222: #endif /* _KERN_LOCK_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.