1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 *
31 */
32/*
33 * HISTORY
34 *
35 * Revision 1.1.1.1  1998/09/22 21:05:30  wsanchez
36 * Import of Mac OS X kernel (~semeria)
37 *
38 * Revision 1.1.1.1  1998/03/07 02:25:45  wsanchez
39 * Import of OSF Mach kernel (~mburg)
40 *
41 * Revision 1.1.4.1  1995/06/13  18:20:29  sjs
42 * 	Merged from flipc_shared.
43 * 	[95/06/07            sjs]
44 *
45 * Revision 1.1.2.3  1995/03/09  19:42:30  rwd
46 * 	Move yield function out of macro and prototype.
47 * 	[1995/03/09  19:36:25  rwd]
48 *
49 * Revision 1.1.2.2  1995/02/21  17:23:11  randys
50 * 	Re-indented code to four space indentation
51 * 	[1995/02/21  16:25:39  randys]
52 *
53 * Revision 1.1.2.1  1994/12/20  19:02:06  randys
54 * 	Moved definition of flipc_simple_lock to flipc_cb.h
55 * 	[1994/12/20  17:34:44  randys]
56 *
57 * 	Separated the lock macros out into machine dependent and independent files;
58 * 	this is the machine independent file.
59 * 	[1994/12/20  16:43:38  randys]
60 *
61 * $EndLog$
62 */
63
64/*
65 * mach/flipc_locks.h
66 *
67 * The machine independent part of the flipc_simple_locks definitions.
68 * Most of the locks definitions is in flipc_dep.h, but what isn't
69 * dependent on the platform being used is here.
70 */
71
72/*
73 * Note that the locks defined in this file and in flipc_dep.h are only
74 * for use by user level code.  The reason why this file is visible to
75 * the kernel is that the kernel section of flipc needs to initialize
76 * these locks.
77 */
78
79#ifndef _MACH_FLIPC_LOCKS_H_
80#define _MACH_FLIPC_LOCKS_H_
81
82/* Get the simple lock type.  */
83#include <mach/flipc_cb.h>
84
85/*
86 * Lock function prototypes.  This needs to be before any lock definitions
87 * that happen to be macros.
88 */
89
90/* Initializes lock.  Always a macro (so that kernel code can use it without
91   library assistance).  */
92void flipc_simple_lock_init(flipc_simple_lock *lock);
93
94/* Returns 1 if lock gained, 0 otherwise.  */
95int flipc_simple_lock_try(flipc_simple_lock *lock);
96
97/* Returns 1 if lock is locked, 0 otherwise.  */
98int flipc_simple_lock_locked(flipc_simple_lock *lock);
99
100/* Releases the lock.  */
101void flipc_simple_lock_release(flipc_simple_lock *lock);
102
103/* Take the lock.  */
104void flipc_simple_lock_acquire(flipc_simple_lock *lock);
105
106/* Take two locks.  Does not hold one while spinning on the
107   other.  */
108void flipc_simple_lock_acquire_2(flipc_simple_lock *lock1,
109			   flipc_simple_lock *lock2);
110
111/* Get the machine dependent stuff.  The things that need to be
112 * defined in a machine dependent fashion are:
113 *
114 *   flipc_simple_lock_init	(must be a macro)
115 *   flipc_simple_lock_try
116 *   flipc_simple_lock_locked
117 *   flipc_simple_lock_release
118 *
119 * These last three don't necessarily have to be macros, but if they
120 * aren't definitions must be included in the machine dependent
121 * part of the user level library code.
122 */
123#include <mach/machine/flipc_dep.h>
124
125/*
126 * Set at flipc initialization time to thread_yield argument to
127 * FLIPC_domain_init
128 */
129
130extern void (*flipc_simple_lock_yield_fn)(void);
131
132/*
133 * Machine independent definitions; defined in terms of above routines.
134 */
135
136/* Take the lock.  Assumes an external define saying how long to
137   spin, and an external function to call when we've spun too long.  */
138#define flipc_simple_lock_acquire(lock)		\
139do {						\
140  int __spin_count = 0;				\
141						\
142  while (flipc_simple_lock_locked(lock)		\
143	 || !flipc_simple_lock_try(lock))	\
144    if (++__spin_count > LOCK_SPIN_LIMIT) {	\
145      (*flipc_simple_lock_yield_fn)();		\
146      __spin_count = 0;				\
147    }						\
148} while (0)
149
150/* Take two locks.  Hold neither while spinning on the other.  */
151#define flipc_simple_lock_acquire_2(lock1, lock2)	\
152do {							\
153  int __spin_count = 0;					\
154							\
155  while (1) {						\
156    while (flipc_simple_lock_locked(lock1)		\
157	   || !flipc_simple_lock_try(lock1))		\
158      if (++__spin_count > LOCK_SPIN_LIMIT) {		\
159	(*flipc_simple_lock_yield_fn)();		\
160	__spin_count = 0;				\
161      }							\
162							\
163    if (flipc_simple_lock_try(lock2))			\
164      break;						\
165    flipc_simple_lock_release(lock1);			\
166							\
167    while (flipc_simple_lock_locked(lock2)		\
168	   || !flipc_simple_lock_try(lock2))		\
169      if (++__spin_count > LOCK_SPIN_LIMIT) {		\
170	(*flipc_simple_lock_yield_fn)();		\
171	__spin_count = 0;				\
172      }							\
173							\
174    if (flipc_simple_lock_try(lock1))			\
175      break;						\
176    flipc_simple_lock_release(lock2);			\
177  }							\
178} while (0)
179
180#endif	/* _MACH_FLIPC_LOCKS_H_ */
181