| 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 | \f |
| 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 | \f |
| 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 | \f |
| 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 |