Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
mutex.h
Go to the documentation of this file.
1/*
2 mutex.h - mutual exclusion locking
3
4 Copyright (C)
5 2008, 2009, Christian Thaeter <ct@pipapo.org>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11*/
12
13#ifndef LUMIERA_MUTEX_H
14#define LUMIERA_MUTEX_H
15
16#include "lib/error.h"
17#include "lib/sectionlock.h"
18#include "lib/lockerror.h"
19
20#include <pthread.h>
21#include <time.h>
22#include <nobug.h>
23
32#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \
33 for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
34 lumiera_lock_section_ = { \
35 mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \
36 NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \
37 ({ \
38 if (lumiera_lock_section_.lock) \
39 lumiera_lock_section_.lock = \
40 lumiera_mutex_lock (mtx, &NOBUG_FLAG(nobugflag), \
41 &lumiera_lock_section_.rh, NOBUG_CONTEXT); \
42 lumiera_lock_section_.lock; \
43 }); \
44 ({ \
45 LUMIERA_MUTEX_SECTION_UNLOCK; \
46 }))
47
48
56#define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \
57 for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \
58 NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \
59 mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \
60 NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \
61 ({ \
62 if (lumiera_lock_section_.lock) \
63 { \
64 REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \
65 lumiera_lock_section_.lock = \
66 lumiera_mutex_lock (mtx, &NOBUG_FLAG(nobugflag), \
67 &lumiera_lock_section_.rh, NOBUG_CONTEXT); \
68 LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \
69 } \
70 lumiera_lock_section_.lock; \
71 }); \
72 ({ \
73 LUMIERA_MUTEX_SECTION_UNLOCK; \
74 }))
75
76
77#define LUMIERA_MUTEX_SECTION_UNLOCK \
78 LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_)
79
80
86{
87 pthread_mutex_t mutex;
89};
90typedef struct lumiera_mutex_struct lumiera_mutex;
91typedef lumiera_mutex* LumieraMutex;
92
93
104 const char* purpose,
105 struct nobug_flag* flag,
106 const struct nobug_context ctx);
107
116 struct nobug_flag* flag,
117 const struct nobug_context ctx);
118
119
128static inline LumieraMutex
130 struct nobug_flag* flag,
131 struct nobug_resource_user** handle,
132 const struct nobug_context ctx)
133{
134 if (self)
135 {
136 NOBUG_RESOURCE_WAIT_CTX (NOBUG_FLAG_RAW(flag), self->rh, "acquire mutex", *handle, ctx)
137 {
138 if (pthread_mutex_lock (&self->mutex))
139 LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */
140
141 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle, ctx) /*{}*/;
142 }
143 }
144
145 return self;
146}
147
148
156static inline LumieraMutex
158 struct nobug_flag* flag,
159 struct nobug_resource_user** handle,
160 const struct nobug_context ctx)
161{
162 if (self)
163 {
164 NOBUG_RESOURCE_TRY_CTX (NOBUG_FLAG_RAW(flag), self->rh, "try acquire mutex", *handle, ctx)
165 {
166 int err = pthread_mutex_trylock (&self->mutex);
167
168 if (!err)
169 {
170 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle, ctx) /*{}*/;
171 }
172 else
173 {
174 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx) /*{}*/;
175 lumiera_lockerror_set (err, flag, ctx);
176 self = NULL;
177 }
178 }
179 }
180
181 return self;
182}
183
192static inline LumieraMutex
194 const struct timespec* timeout,
195 struct nobug_flag* flag,
196 struct nobug_resource_user** handle,
197 const struct nobug_context ctx)
198{
199 if (self)
200 {
201 NOBUG_RESOURCE_TRY_CTX (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire mutex", *handle, ctx)
202 {
203 int err = pthread_mutex_timedlock (&self->mutex, timeout);
204
205 if (!err)
206 {
207 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle, ctx) /*{}*/;
208 }
209 else
210 {
211 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx) /*{}*/;
212 lumiera_lockerror_set (err, flag, ctx);
213 self = NULL;
214 }
215 }
216 }
217
218 return self;
219}
220
221
229static inline void
231 struct nobug_flag* flag,
232 struct nobug_resource_user** handle,
233 const struct nobug_context ctx)
234{
235 NOBUG_REQUIRE_CTX (self, ctx);
236
237 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx)
238 {
239 if (pthread_mutex_unlock (&self->mutex))
240 LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */
241 }
242}
243
244
245#endif
246/*
247// Local Variables:
248// mode: C
249// c-file-style: "gnu"
250// indent-tabs-mode: nil
251// End:
252*/
Lumiera error handling (C interface).
#define LUMIERA_DIE(err)
Abort unconditionally with a 'Fatal Error!' message.
Definition error.h:54
return NULL
Definition llist.h:586
void lumiera_lockerror_set(int err, struct nobug_flag *flag, const struct nobug_context ctx)
Translate pthread error code into lumiera error.
Definition lockerror.c:40
definitions and declarations for error-handling on low-level locking
static void lumiera_mutex_unlock(LumieraMutex self, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
unlock a mutex variable Never fails
Definition mutex.h:230
static LumieraMutex lumiera_mutex_trylock(LumieraMutex self, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Try to lock a mutex variable.
Definition mutex.h:157
static LumieraMutex lumiera_mutex_lock(LumieraMutex self, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Lock a mutex variable Never fails.
Definition mutex.h:129
LumieraMutex lumiera_mutex_destroy(LumieraMutex self, struct nobug_flag *flag, const struct nobug_context ctx)
Destroy a mutex variable.
Definition mutex.c:39
lumiera_mutex * LumieraMutex
Definition mutex.h:91
static LumieraMutex lumiera_mutex_timedlock(LumieraMutex self, const struct timespec *timeout, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Try to lock a mutex variable with a timeout.
Definition mutex.h:193
LumieraMutex lumiera_mutex_init(LumieraMutex self, const char *purpose, struct nobug_flag *flag, const struct nobug_context ctx)
Initialise a mutex variable This initialises a 'fast' default mutex which must not be locked recursiv...
Definition mutex.c:21
Mutex state handle for locked code sections.
pthread_mutex_t mutex
Definition mutex.h:87