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
43typedef 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
199extern cma__t_sequence	cma__g_mutex_seq;
200extern cma__t_int_mutex	*cma__g_global_lock;
201
202/*
203 * INTERNAL INTERFACES
204 */
205
206extern void cma__destroy_mutex  (cma__t_int_mutex *);
207
208extern void cma__free_mutex  (cma__t_int_mutex *);
209
210extern void cma__free_mutex_nolock  (cma__t_int_mutex *);
211
212extern cma__t_int_mutex * cma__get_first_mutex  (cma__t_int_attr *);
213
214extern cma__t_int_mutex * cma__get_mutex  (cma__t_int_attr *);
215
216extern void cma__init_mutex  (void);
217
218extern cma_t_status cma__int_mutex_block  (cma__t_int_mutex *);
219
220extern cma_t_boolean cma__int_mutex_locked  (cma__t_int_mutex *);
221
222extern cma_t_boolean cma__int_try_lock  (cma__t_int_mutex *);
223
224extern cma_t_status cma__int_mutex_unblock  (cma__t_int_mutex *);
225
226extern cma_t_boolean cma__mutex_locked  (cma_t_mutex);
227
228extern void cma__reinit_mutex  (cma_t_integer);
229
230#endif
231