1 /*
2  * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
3  * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
4  * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
5  * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
6  * To anyone who acknowledges that this file is provided "AS IS" without
7  * any express or implied warranty: permission to use, copy, modify, and
8  * distribute this file for any purpose is hereby granted without fee,
9  * provided that the above copyright notices and this notice appears in
10  * all source code copies, and that none of the names listed above be used
11  * in advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission.  None of these organizations
13  * makes any representations about the suitability of this software for
14  * any purpose.
15  */
16 /*
17  *	Header file for mutex operations
18  */
19 
20 #ifndef CMA_MUTEX
21 #define CMA_MUTEX
22 
23 /*
24  *  INCLUDE FILES
25  */
26 
27 #include <cma.h>
28 #include <cma_attr.h>
29 #include <cma_defs.h>
30 #include <cma_semaphore_defs.h>
31 #include <cma_sequence.h>
32 #include <cma_tcb_defs.h>
33 #include <cma_stack.h>
34 
35 /*
36  * CONSTANTS AND MACROS
37  */
38 
39 /*
40  * TYPEDEFS
41  */
42 
43 typedef struct CMA__T_INT_MUTEX {
44     cma__t_object	header;		/* Common header (sequence, type) */
45     cma__t_int_attr	*attributes;	/* Back link */
46     cma__t_int_tcb	*owner;		/* Current owner (if any) */
47     cma_t_integer	nest_count;	/* Nesting level for recursive mutex */
48     cma__t_atomic_bit	*unlock;	/* Pointer used for unlock operation */
49     cma__t_atomic_bit	lock;		/* Set if currently locked */
50     struct CMA__T_INT_MUTEX *int_lock;	/* Internal protection for mutex */
51     cma__t_atomic_bit	event;		/* Clear when unlock requires action */
52     cma__t_atomic_bit	waiters;	/* Clear when threads are waiting */
53     cma__t_atomic_bit	bitbucket;	/* Fake bit to keep friendlies locked */
54     cma_t_mutex_kind	mutex_kind;	/* Kind of mutex */
55     cma__t_semaphore	semaphore;	/* Semaphore for low-level wait */
56     } cma__t_int_mutex;
57 
58 
59 /*
60  *  FUNCTIONAL DESCRIPTION:
61  *
62  *	Lock a mutex (internal)
63  *
64  *  FORMAL PARAMETERS:
65  *
66  *	mutex		Pointer to mutex object to lock
67  *
68  *  IMPLICIT INPUTS:
69  *
70  *	none
71  *
72  *  IMPLICIT OUTPUTS:
73  *
74  *	none
75  *
76  *  FUNCTION VALUE:
77  *
78  *	none
79  *
80  *  SIDE EFFECTS:
81  *
82  *	none
83  */
84 #ifdef NDEBUG
85 # define cma__int_lock(mutex) { \
86     if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \
87 	cma_t_status	res;\
88 	res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \
89 	if (res != cma_s_normal) cma__error (res); \
90 	} \
91     }
92 #else
93 # define cma__int_lock(mutex) { \
94     cma__t_int_tcb *__ltcb__; \
95     __ltcb__ = cma__get_self_tcb (); \
96     if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \
97 	cma_t_status	res;\
98 	res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \
99 	if (res != cma_s_normal) cma__error (res); \
100 	} \
101     ((cma__t_int_mutex *)mutex)->owner = __ltcb__; \
102     }
103 #endif
104 
105 /*
106  *  FUNCTIONAL DESCRIPTION:
107  *
108  *	Unlock a mutex (internal)
109  *
110  *  FORMAL PARAMETERS:
111  *
112  *	mutex		Pointer to mutex object to unlock
113  *
114  *  IMPLICIT INPUTS:
115  *
116  *	none
117  *
118  *  IMPLICIT OUTPUTS:
119  *
120  *	none
121  *
122  *  FUNCTION VALUE:
123  *
124  *	none
125  *
126  *  SIDE EFFECTS:
127  *
128  *	none
129  */
130 #ifdef NDEBUG
131 # define cma__int_unlock(mutex) { \
132     cma__unset (((cma__t_int_mutex *)mutex)->unlock); \
133     if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \
134 	cma_t_status	res;\
135 	res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \
136 	if (res != cma_s_normal) cma__error (res); \
137 	} \
138     }
139 #else
140 # define cma__int_unlock(mutex) { \
141     cma__t_int_tcb	*__utcb__; \
142     __utcb__ = cma__get_self_tcb (); \
143     if (((cma__t_int_mutex *)mutex)->mutex_kind == cma_c_mutex_fast) { \
144 	cma__assert_warn ( \
145 		(__utcb__ == ((cma__t_int_mutex *)mutex)->owner), \
146 		"attempt to release mutx owned by another thread"); \
147 	((cma__t_int_mutex *)mutex)->owner = (cma__t_int_tcb *)cma_c_null_ptr; \
148 	} \
149     cma__unset (((cma__t_int_mutex *)mutex)->unlock); \
150     if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \
151 	cma_t_status	res;\
152 	res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \
153 	if (res != cma_s_normal) cma__error (res); \
154 	} \
155     }
156 #endif
157 
158 /*
159  *  FUNCTIONAL DESCRIPTION:
160  *
161  *	cma__int_mutex_delete - Performs work for cma_mutex_delete
162  *
163  *  FORMAL PARAMETERS:
164  *
165  *	cma__t_mutex	    _mutex_	- Mutex to be deleted
166  *
167  *  IMPLICIT INPUTS:
168  *
169  *	none
170  *
171  *  IMPLICIT OUTPUTS:
172  *
173  *	none
174  *
175  *  FUNCTION VALUE:
176  *
177  *	none
178  *
179  *  SIDE EFFECTS:
180  *
181  *	none
182  */
183 #define cma__int_mutex_delete(_mutex_) { \
184     cma__t_int_mutex    *_int_mutex_; \
185     _int_mutex_ = cma__validate_null_mutex (_mutex_); \
186     if (_int_mutex_ == (cma__t_int_mutex *)cma_c_null_ptr) \
187         return; \
188     if (cma__int_mutex_locked (_int_mutex_)) \
189         cma__error (cma_s_in_use); \
190     cma__free_mutex (_int_mutex_); \
191     cma__clear_handle (_mutex_); \
192     }
193 
194 
195 /*
196  *  GLOBAL DATA
197  */
198 
199 extern cma__t_sequence	cma__g_mutex_seq;
200 extern cma__t_int_mutex	*cma__g_global_lock;
201 
202 /*
203  * INTERNAL INTERFACES
204  */
205 
206 extern void cma__destroy_mutex  (cma__t_int_mutex *);
207 
208 extern void cma__free_mutex  (cma__t_int_mutex *);
209 
210 extern void cma__free_mutex_nolock  (cma__t_int_mutex *);
211 
212 extern cma__t_int_mutex * cma__get_first_mutex  (cma__t_int_attr *);
213 
214 extern cma__t_int_mutex * cma__get_mutex  (cma__t_int_attr *);
215 
216 extern void cma__init_mutex  (void);
217 
218 extern cma_t_status cma__int_mutex_block  (cma__t_int_mutex *);
219 
220 extern cma_t_boolean cma__int_mutex_locked  (cma__t_int_mutex *);
221 
222 extern cma_t_boolean cma__int_try_lock  (cma__t_int_mutex *);
223 
224 extern cma_t_status cma__int_mutex_unblock  (cma__t_int_mutex *);
225 
226 extern cma_t_boolean cma__mutex_locked  (cma_t_mutex);
227 
228 extern void cma__reinit_mutex  (cma_t_integer);
229 
230 #endif
231