|
|
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 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: /*
56: */
57:
58: /*
59: * Machine-dependent simple locks for the i386.
60: */
61:
62: #ifndef _I386_LOCK_H_
63: #define _I386_LOCK_H_
64:
65: #include <kern/macro_help.h>
66: #include <kern/assert.h>
67: #include <i386/hw_lock_types.h>
68:
69: #ifdef MACH_KERNEL_PRIVATE
70:
71: #include <mach_rt.h>
72: #include <mach_ldebug.h>
73: #include <cpus.h>
74:
75:
76: #if defined(__GNUC__)
77:
78: /*
79: * General bit-lock routines.
80: */
81:
82: #define bit_lock(bit,l) \
83: __asm__ volatile(" jmp 1f \n \
84: 0: btl %0, %1 \n \
85: jb 0b \n \
86: 1: lock \n \
87: btsl %0,%1 \n \
88: jb 0b" : \
89: : \
90: "r" (bit), "m" (*(volatile int *)(l)) : \
91: "memory");
92:
93: #define bit_unlock(bit,l) \
94: __asm__ volatile(" lock \n \
95: btrl %0,%1" : \
96: : \
97: "r" (bit), "m" (*(volatile int *)(l)));
98:
99: /*
100: * Set or clear individual bits in a long word.
101: * The locked access is needed only to lock access
102: * to the word, not to individual bits.
103: */
104:
105: #define i_bit_set(bit,l) \
106: __asm__ volatile(" lock \n \
107: btsl %0,%1" : \
108: : \
109: "r" (bit), "m" (*(volatile int *)(l)));
110:
111: #define i_bit_clear(bit,l) \
112: __asm__ volatile(" lock \n \
113: btrl %0,%1" : \
114: : \
115: "r" (bit), "m" (*(volatile int *)(l)));
116:
117: extern __inline__ unsigned long i_bit_isset(unsigned int testbit, volatile unsigned long *word)
118: {
119: int bit;
120:
121: __asm__ volatile("btl %2,%1\n\tsbbl %0,%0" : "=r" (bit)
122: : "m" (word), "ir" (testbit));
123: return bit;
124: }
125:
126: extern __inline__ char xchgb(volatile char * cp, char new);
127:
128: extern __inline__ void atomic_incl(long * p, long delta);
129: extern __inline__ void atomic_incs(short * p, short delta);
130: extern __inline__ void atomic_incb(char * p, char delta);
131:
132: extern __inline__ void atomic_decl(long * p, long delta);
133: extern __inline__ void atomic_decs(short * p, short delta);
134: extern __inline__ void atomic_decb(char * p, char delta);
135:
136: extern __inline__ long atomic_getl(long * p);
137: extern __inline__ short atomic_gets(short * p);
138: extern __inline__ char atomic_getb(char * p);
139:
140: extern __inline__ void atomic_setl(long * p, long value);
141: extern __inline__ void atomic_sets(short * p, short value);
142: extern __inline__ void atomic_setb(char * p, char value);
143:
144: extern __inline__ char xchgb(volatile char * cp, char new)
145: {
146: register char old = new;
147:
148: __asm__ volatile (" xchgb %0,%2" :
149: "=q" (old) :
150: "0" (new), "m" (*(volatile char *)cp) : "memory");
151: return (old);
152: }
153:
154: extern __inline__ void atomic_incl(long * p, long delta)
155: {
156: #if NEED_ATOMIC
157: __asm__ volatile (" lock \n \
158: addl %0,%1" : \
159: : \
160: "r" (delta), "m" (*(volatile long *)p));
161: #else /* NEED_ATOMIC */
162: *p += delta;
163: #endif /* NEED_ATOMIC */
164: }
165:
166: extern __inline__ void atomic_incs(short * p, short delta)
167: {
168: #if NEED_ATOMIC
169: __asm__ volatile (" lock \n \
170: addw %0,%1" : \
171: : \
172: "q" (delta), "m" (*(volatile short *)p));
173: #else /* NEED_ATOMIC */
174: *p += delta;
175: #endif /* NEED_ATOMIC */
176: }
177:
178: extern __inline__ void atomic_incb(char * p, char delta)
179: {
180: #if NEED_ATOMIC
181: __asm__ volatile (" lock \n \
182: addb %0,%1" : \
183: : \
184: "q" (delta), "m" (*(volatile char *)p));
185: #else /* NEED_ATOMIC */
186: *p += delta;
187: #endif /* NEED_ATOMIC */
188: }
189:
190: extern __inline__ void atomic_decl(long * p, long delta)
191: {
192: #if NCPUS > 1
193: __asm__ volatile (" lock \n \
194: subl %0,%1" : \
195: : \
196: "r" (delta), "m" (*(volatile long *)p));
197: #else /* NCPUS > 1 */
198: *p -= delta;
199: #endif /* NCPUS > 1 */
200: }
201:
202: extern __inline__ void atomic_decs(short * p, short delta)
203: {
204: #if NEED_ATOMIC
205: __asm__ volatile (" lock \n \
206: subw %0,%1" : \
207: : \
208: "q" (delta), "m" (*(volatile short *)p));
209: #else /* NEED_ATOMIC */
210: *p -= delta;
211: #endif /* NEED_ATOMIC */
212: }
213:
214: extern __inline__ void atomic_decb(char * p, char delta)
215: {
216: #if NEED_ATOMIC
217: __asm__ volatile (" lock \n \
218: subb %0,%1" : \
219: : \
220: "q" (delta), "m" (*(volatile char *)p));
221: #else /* NEED_ATOMIC */
222: *p -= delta;
223: #endif /* NEED_ATOMIC */
224: }
225:
226: extern __inline__ long atomic_getl(long * p)
227: {
228: return (*p);
229: }
230:
231: extern __inline__ short atomic_gets(short * p)
232: {
233: return (*p);
234: }
235:
236: extern __inline__ char atomic_getb(char * p)
237: {
238: return (*p);
239: }
240:
241: extern __inline__ void atomic_setl(long * p, long value)
242: {
243: *p = value;
244: }
245:
246: extern __inline__ void atomic_sets(short * p, short value)
247: {
248: *p = value;
249: }
250:
251: extern __inline__ void atomic_setb(char * p, char value)
252: {
253: *p = value;
254: }
255:
256:
257: #else /* !defined(__GNUC__) */
258:
259: extern void i_bit_set(
260: int index,
261: void *addr);
262:
263: extern void i_bit_clear(
264: int index,
265: void *addr);
266:
267: extern void bit_lock(
268: int index,
269: void *addr);
270:
271: extern void bit_unlock(
272: int index,
273: void *addr);
274:
275: /*
276: * All other routines defined in __GNUC__ case lack
277: * definitions otherwise. - XXX
278: */
279:
280: #endif /* !defined(__GNUC__) */
281:
282:
283: #if !(USLOCK_DEBUG || USLOCK_STATS)
284: /*
285: * Take responsibility for production-quality usimple_locks.
286: * Let the portable lock package build simple_locks in terms
287: * of usimple_locks, which is done efficiently with macros.
288: * Currently, these aren't inlined although they probably
289: * should be. The portable lock package is used for the
290: * usimple_lock prototypes and data declarations.
291: *
292: * For non-production configurations, punt entirely to the
293: * portable lock package.
294: *
295: * N.B. I've left in the hooks for ETAP, so we can
296: * compare the performance of stats-gathering on top
297: * of "production" locks v. stats-gathering on top
298: * of portable, C-based locks.
299: */
300: #define USIMPLE_LOCK_CALLS
301: #endif /* !(USLOCK_DEBUG || USLOCK_STATS) */
302:
303:
304: #if MACH_RT || (NCPUS > 1) || MACH_LDEBUG
305: #if MACH_LDEBUG || !MACH_RT
306: #define mutex_try(m) (!(m)->interlock && _mutex_try(m))
307: #define mutex_lock(m) \
308: MACRO_BEGIN \
309: assert(assert_wait_possible()); \
310: _mutex_lock((m)); \
311: MACRO_END
312:
313: #else /* MACH_LDEBUG || !MACH_RT */
314: #define mutex_try(m) (!(m)->interlock && \
315: !xchgb ((volatile char *)&((m)->locked), 1))
316: #define mutex_lock(m) \
317: MACRO_BEGIN \
318: assert(assert_wait_possible()); \
319: _mutex_lock (m); \
320: MACRO_END
321:
322: #endif /* MACH_LDEBUG || !MACH_RT */
323: #else /* MACH_RT || (NCPUS > 1) || MACH_LDEBUG */
324: #define mutex_try _mutex_try
325: #define mutex_lock _mutex_lock
326: #endif /* MACH_RT || (NCPUS > 1) || MACH_LDEBUG */
327:
328: #else /* !MACH_KERNEL_PRIVATE */
329:
330: #define mutex_try _mutex_try
331: #define mutex_lock(m) \
332: MACRO_BEGIN \
333: assert(assert_wait_possible()); \
334: _mutex_lock((m)); \
335: MACRO_END
336:
337: #endif /* !MACH_KERNEL_PRIVATE */
338:
339: extern void kernel_preempt_check (void);
340:
341: #endif /* _I386_LOCK_H_ */
342:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.