Lumiera  0.pre.03
»edit your freedom«
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;
88  RESOURCE_HANDLE (rh);
89 };
90 typedef struct lumiera_mutex_struct lumiera_mutex;
91 typedef lumiera_mutex* LumieraMutex;
92 
93 
102 LumieraMutex
103 lumiera_mutex_init (LumieraMutex self,
104  const char* purpose,
105  struct nobug_flag* flag,
106  const struct nobug_context ctx);
107 
114 LumieraMutex
115 lumiera_mutex_destroy (LumieraMutex self,
116  struct nobug_flag* flag,
117  const struct nobug_context ctx);
118 
119 
128 static inline LumieraMutex
129 lumiera_mutex_lock (LumieraMutex self,
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 
156 static inline LumieraMutex
157 lumiera_mutex_trylock (LumieraMutex self,
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 
192 static inline LumieraMutex
193 lumiera_mutex_timedlock (LumieraMutex self,
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 
229 static inline void
230 lumiera_mutex_unlock (LumieraMutex self,
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 */
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 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
Common functions for handling of time values.
definitions and declarations for error-handling on low-level locking
Lumiera error handling (C interface).
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
#define LUMIERA_DIE(err)
Abort unconditionally with a &#39;Fatal Error!&#39; message.
Definition: error.h:54
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 &#39;fast&#39; default mutex which must not be locked recursiv...
Definition: mutex.c:21
LumieraMutex lumiera_mutex_destroy(LumieraMutex self, struct nobug_flag *flag, const struct nobug_context ctx)
Destroy a mutex variable.
Definition: mutex.c:39
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
Mutex state handle for locked code sections.