Return an rc from the passwd and group functions.
[pwmd.git] / src / mutex.h
blob7d2d30529d3ebd94d81bcf9c3519357bc8f9bacf
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifndef MUTEX_H
21 #define MUTEX_H
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #ifdef HAVE_SYS_TIME_H
28 #include <sys/time.h>
29 #endif
31 #ifdef HAVE_TIME_H
32 #include <time.h>
33 #endif
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
37 #else
38 #include <sys/types.h>
39 #include <unistd.h>
40 #endif
42 #ifdef HAVE_SYS_FILE_H
43 #include <sys/file.h>
44 #endif
46 #ifdef HAVE_FCNTL_H
47 #include <fcntl.h>
48 #endif
50 #include <pthread.h>
51 #include <assert.h>
52 #include <errno.h>
53 #include "rcfile.h"
55 #define INIT_TIMESPEC(t, ts) do { \
56 long s = (t*100000000)/1000000000; \
57 long l = (t*100000000)%1000000000; \
58 clock_gettime(CLOCK_REALTIME, &ts); \
59 ts.tv_sec += s; \
60 if (ts.tv_nsec + l >= 1000000000) { \
61 ts.tv_sec++; \
62 ts.tv_nsec = 0; \
63 } \
64 else \
65 ts.tv_nsec += l; \
66 } while (0)
68 #ifdef MUTEX_DEBUG
69 #define MUTEX_LOCK_DEBUG(m) do { \
70 log_write("%s(%i): %s(): LOCK %p", __FILE__, __LINE__, \
71 __FUNCTION__, m); \
72 } while (0)
74 #define MUTEX_UNLOCK_DEBUG(m) do { \
75 log_write("%s(%i): %s(): UNLOCK %p", __FILE__, __LINE__, \
76 __FUNCTION__, m); \
77 } while (0)
78 #else
79 #define MUTEX_LOCK_DEBUG(m)
80 #define MUTEX_UNLOCK_DEBUG(m)
81 #endif
83 #define MUTEX_LOCK(m) do { \
84 MUTEX_LOCK_DEBUG(m); \
85 pthread_mutex_lock(m); \
86 } while (0)
88 #define MUTEX_UNLOCK(m) do { \
89 MUTEX_UNLOCK_DEBUG(m); \
90 pthread_mutex_unlock(m); \
91 } while (0)
93 #define TIMED_LOCK_DURATION 100000
94 #ifdef HAVE_FLOCK
95 #define TRY_FLOCK(ctx, fd, type, rc) do { \
96 long ka = (long)config_get_integer ("global", "keepalive_interval"); \
97 int to = config_get_integer ("global", "lock_timeout"); \
98 for (long elapsed = 0; ; elapsed++) { \
99 struct timeval tv = { 0, TIMED_LOCK_DURATION }; \
100 int n = flock (fd, type|LOCK_NB); \
101 if (n == -1 && errno == EWOULDBLOCK) \
103 if (to == -1 || elapsed >= to) { \
104 rc = GPG_ERR_LOCKED; \
105 break; \
107 select (0, NULL, NULL, NULL, &tv); \
108 if (ctx && ka && elapsed && !((elapsed+1*10) % (ka*10))) { \
109 rc = send_status (ctx, STATUS_KEEPALIVE, NULL); \
110 if (rc) \
111 break; \
114 else if (n == -1) \
115 rc = gpg_error_from_errno (errno); \
116 else \
117 break; \
119 } while (0)
120 #else
121 #define TRY_FLOCK(ctx, fd, type, rc) do { \
122 rc = 0; \
123 } while (0)
124 #endif
126 #define MUTEX_TIMED_LOCK(ctx, m, timeout, rc) do { \
127 long ka = (long)config_get_integer ("global", "keepalive_interval"); \
128 for (long elapsed = 0; ; elapsed++) { \
129 struct timeval tv = { 0, TIMED_LOCK_DURATION }; \
130 if (pthread_mutex_trylock(m) == EBUSY) { \
131 if (timeout == -1 || elapsed >= timeout) { \
132 rc = GPG_ERR_LOCKED; \
133 break; \
135 select (0, NULL, NULL, NULL, &tv); \
136 if (ctx && ka && elapsed && !((elapsed+1*10) % (ka*10))) { \
137 rc = send_status (ctx, STATUS_KEEPALIVE, NULL); \
138 if (rc) \
139 break; \
142 else { \
143 MUTEX_LOCK_DEBUG(m); \
144 break; \
147 } while (0)
149 #define MUTEX_TRYLOCK(ctx, m, rc, t) do { \
150 int n; \
151 rc = 0; \
152 if ((n = pthread_mutex_trylock(m)) == EBUSY) { \
153 if (t != -1) { \
154 if (ctx) \
155 rc = send_status(ctx, STATUS_LOCKED, NULL); \
156 if (!rc && t != 0) { \
157 MUTEX_TIMED_LOCK(ctx, m, t, rc); \
159 else if (!rc) { \
160 MUTEX_LOCK_DEBUG(m); \
163 else \
164 rc = GPG_ERR_LOCKED; \
166 else if (n) \
167 rc = gpg_error_from_errno(n); \
168 else \
169 MUTEX_LOCK_DEBUG(m); \
170 } while (0)
172 #endif