00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef LUMIERA_MUTEX_H
00023 #define LUMIERA_MUTEX_H
00024
00025 #include "lib/error.h"
00026 #include "lib/sectionlock.h"
00027 #include "lib/lockerror.h"
00028
00029 #include <pthread.h>
00030 #include <time.h>
00031 #include <nobug.h>
00032
00041 #define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \
00042 for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
00043 lumiera_lock_section_ = { \
00044 mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \
00045 NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \
00046 ({ \
00047 if (lumiera_lock_section_.lock) \
00048 lumiera_lock_section_.lock = \
00049 lumiera_mutex_lock (mtx, &NOBUG_FLAG(nobugflag), \
00050 &lumiera_lock_section_.rh, NOBUG_CONTEXT); \
00051 lumiera_lock_section_.lock; \
00052 }); \
00053 ({ \
00054 LUMIERA_MUTEX_SECTION_UNLOCK; \
00055 }))
00056
00057
00065 #define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \
00066 for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \
00067 NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \
00068 mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \
00069 NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \
00070 ({ \
00071 if (lumiera_lock_section_.lock) \
00072 { \
00073 REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \
00074 lumiera_lock_section_.lock = \
00075 lumiera_mutex_lock (mtx, &NOBUG_FLAG(nobugflag), \
00076 &lumiera_lock_section_.rh, NOBUG_CONTEXT); \
00077 LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \
00078 } \
00079 lumiera_lock_section_.lock; \
00080 }); \
00081 ({ \
00082 LUMIERA_MUTEX_SECTION_UNLOCK; \
00083 }))
00084
00085
00086 #define LUMIERA_MUTEX_SECTION_UNLOCK \
00087 LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_)
00088
00089
00094 struct lumiera_mutex_struct
00095 {
00096 pthread_mutex_t mutex;
00097 RESOURCE_HANDLE (rh);
00098 };
00099 typedef struct lumiera_mutex_struct lumiera_mutex;
00100 typedef lumiera_mutex* LumieraMutex;
00101
00102
00111 LumieraMutex
00112 lumiera_mutex_init (LumieraMutex self,
00113 const char* purpose,
00114 struct nobug_flag* flag,
00115 const struct nobug_context ctx);
00116
00123 LumieraMutex
00124 lumiera_mutex_destroy (LumieraMutex self,
00125 struct nobug_flag* flag,
00126 const struct nobug_context ctx);
00127
00128
00137 static inline LumieraMutex
00138 lumiera_mutex_lock (LumieraMutex self,
00139 struct nobug_flag* flag,
00140 struct nobug_resource_user** handle,
00141 const struct nobug_context ctx)
00142 {
00143 if (self)
00144 {
00145 NOBUG_RESOURCE_WAIT_CTX (NOBUG_FLAG_RAW(flag), self->rh, "acquire mutex", *handle, ctx)
00146 {
00147 if (pthread_mutex_lock (&self->mutex))
00148 LUMIERA_DIE (LOCK_ACQUIRE);
00149
00150 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle, ctx) ;
00151 }
00152 }
00153
00154 return self;
00155 }
00156
00157
00165 static inline LumieraMutex
00166 lumiera_mutex_trylock (LumieraMutex self,
00167 struct nobug_flag* flag,
00168 struct nobug_resource_user** handle,
00169 const struct nobug_context ctx)
00170 {
00171 if (self)
00172 {
00173 NOBUG_RESOURCE_TRY_CTX (NOBUG_FLAG_RAW(flag), self->rh, "try acquire mutex", *handle, ctx)
00174 {
00175 int err = pthread_mutex_trylock (&self->mutex);
00176
00177 if (!err)
00178 {
00179 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle, ctx) ;
00180 }
00181 else
00182 {
00183 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx) ;
00184 lumiera_lockerror_set (err, flag, ctx);
00185 self = NULL;
00186 }
00187 }
00188 }
00189
00190 return self;
00191 }
00192
00201 static inline LumieraMutex
00202 lumiera_mutex_timedlock (LumieraMutex self,
00203 const struct timespec* timeout,
00204 struct nobug_flag* flag,
00205 struct nobug_resource_user** handle,
00206 const struct nobug_context ctx)
00207 {
00208 if (self)
00209 {
00210 NOBUG_RESOURCE_TRY_CTX (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire mutex", *handle, ctx)
00211 {
00212 int err = pthread_mutex_timedlock (&self->mutex, timeout);
00213
00214 if (!err)
00215 {
00216 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle, ctx) ;
00217 }
00218 else
00219 {
00220 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx) ;
00221 lumiera_lockerror_set (err, flag, ctx);
00222 self = NULL;
00223 }
00224 }
00225 }
00226
00227 return self;
00228 }
00229
00230
00238 static inline void
00239 lumiera_mutex_unlock (LumieraMutex self,
00240 struct nobug_flag* flag,
00241 struct nobug_resource_user** handle,
00242 const struct nobug_context ctx)
00243 {
00244 NOBUG_REQUIRE_CTX (self, ctx);
00245
00246 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx)
00247 {
00248 if (pthread_mutex_unlock (&self->mutex))
00249 LUMIERA_DIE (LOCK_RELEASE);
00250 }
00251 }
00252
00253
00254 #endif
00255
00256
00257
00258
00259
00260
00261