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