solidc
Robust collection of general-purpose cross-platform C libraries and data structures designed for rapid and safe development in C
Loading...
Searching...
No Matches
lock.c
1#ifndef _GNU_SOURCE
2#define _GNU_SOURCE
3#endif
4
5#include "../include/lock.h"
6
7#include <errno.h> // for errno constants
8#include <stdio.h> // for fprintf, stderr
9#include <stdlib.h> // for NULL
10#include <string.h> // for strerror
11#include <time.h> // for clock_gettime, timespec
12
13#ifdef _WIN32
14
15int lock_init(Lock* lock) {
16 if (lock == NULL) {
17 return -1;
18 }
19 InitializeCriticalSection(lock);
20 return 0;
21}
22
23int lock_acquire(Lock* lock) {
24 if (lock == NULL) {
25 return -1;
26 }
27
28 EnterCriticalSection(lock);
29 return 0;
30}
31
32int lock_release(Lock* lock) {
33 if (lock == NULL) {
34 return -1;
35 }
36
37 LeaveCriticalSection(lock);
38 return 0;
39}
40
41int lock_free(Lock* lock) {
42 if (lock == NULL) {
43 return 0;
44 }
45
46 DeleteCriticalSection(lock);
47 return 0;
48}
49
50int lock_try_acquire(Lock* lock) {
51 if (lock == NULL) {
52 return -1;
53 }
54
55 if (TryEnterCriticalSection(lock)) {
56 return 0;
57 }
58 return -1;
59}
60
61int lock_wait(Lock* lock, Condition* condition, int timeout_ms) {
62 if (lock == NULL || condition == NULL) {
63 return -1;
64 }
65
66 DWORD timeout = (timeout_ms < 0) ? INFINITE : (DWORD)timeout_ms;
67 if (SleepConditionVariableCS(condition, lock, timeout)) {
68 return 0;
69 }
70 return -1;
71}
72
73int cond_init(Condition* condition) {
74 if (condition == NULL) {
75 return -1;
76 }
77
78 InitializeConditionVariable(condition);
79 return 0;
80}
81
82int cond_signal(Condition* condition) {
83 if (condition == NULL) {
84 return -1;
85 }
86
87 WakeConditionVariable(condition);
88 return 0;
89}
90
91int cond_broadcast(Condition* condition) {
92 if (condition == NULL) {
93 return -1;
94 }
95
96 WakeAllConditionVariable(condition);
97 return 0;
98}
99
100int cond_wait(Condition* condition, Lock* lock) {
101 if (condition == NULL || lock == NULL) {
102 return -1;
103 }
104
105 if (SleepConditionVariableCS(condition, lock, INFINITE)) {
106 return 0;
107 }
108 return -1;
109}
110
111int cond_wait_timeout(Condition* condition, Lock* lock, int timeout_ms) {
112 if (condition == NULL || lock == NULL) {
113 return -1;
114 }
115
116 DWORD timeout = (timeout_ms < 0) ? INFINITE : (DWORD)timeout_ms;
117 if (SleepConditionVariableCS(condition, lock, timeout)) {
118 return 0;
119 }
120
121 return -1;
122}
123
124int cond_free(Condition* condition) {
125 // Windows condition variables don't require explicit cleanup
126 (void)condition;
127 return 0;
128}
129
130#else // POSIX implementation
131
132int lock_init(Lock* lock) {
133 if (lock == NULL) {
134 return -1;
135 }
136
137 int ret = pthread_mutex_init(lock, NULL);
138 if (ret != 0) {
139 fprintf(stderr, "pthread_mutex_init failed: %s\n", strerror(ret));
140 return -1;
141 }
142 return 0;
143}
144
145int lock_acquire(Lock* lock) {
146 if (lock == NULL) {
147 return -1;
148 }
149
150 int ret = pthread_mutex_lock(lock);
151 if (ret != 0) {
152 switch (ret) {
153 case EDEADLK:
154 fprintf(stderr, "Deadlock detected in pthread_mutex_lock\n");
155 return -1;
156 case EINVAL:
157 fprintf(stderr, "Invalid mutex in pthread_mutex_lock\n");
158 return -1;
159 default:
160 fprintf(stderr, "pthread_mutex_lock failed: %s\n", strerror(ret));
161 return -1;
162 }
163 }
164
165 return 0;
166}
167
168int lock_release(Lock* lock) {
169 if (lock == NULL) {
170 return -1;
171 }
172
173 int ret = pthread_mutex_unlock(lock);
174 if (ret != 0) {
175 fprintf(stderr, "pthread_mutex_unlock failed: %s\n", strerror(ret));
176 return -1;
177 }
178
179 return 0;
180}
181
182int lock_free(Lock* lock) {
183 if (lock == NULL) {
184 return 0; // NULL is valid for cleanup functions
185 }
186
187 int ret = pthread_mutex_destroy(lock);
188 if (ret != 0) {
189 fprintf(stderr, "pthread_mutex_destroy failed: %s\n", strerror(ret));
190 return -1;
191 }
192
193 return 0;
194}
195
197 if (lock == NULL) {
198 return -1;
199 }
200
201 int ret = pthread_mutex_trylock(lock);
202 switch (ret) {
203 case 0:
204 return 0;
205 case EBUSY:
206 return -1;
207 case EINVAL:
208 fprintf(stderr, "Invalid mutex in pthread_mutex_trylock\n");
209 return -1;
210 default:
211 fprintf(stderr, "pthread_mutex_trylock failed: %s\n", strerror(ret));
212 return -1;
213 }
214}
215
216int lock_wait(Lock* lock, Condition* condition, int timeout_ms) {
217 return cond_wait_timeout(condition, lock, timeout_ms);
218}
219
220int cond_init(Condition* condition) {
221 if (condition == NULL) {
222 return -1;
223 }
224
225 int ret = pthread_cond_init(condition, NULL);
226 if (ret != 0) {
227 fprintf(stderr, "pthread_cond_init failed: %s\n", strerror(ret));
228 return -1;
229 }
230
231 return 0;
232}
233
234int cond_signal(Condition* condition) {
235 if (condition == NULL) {
236 return -1;
237 }
238
239 int ret = pthread_cond_signal(condition);
240 if (ret != 0) {
241 fprintf(stderr, "pthread_cond_signal failed: %s\n", strerror(ret));
242 return -1;
243 }
244
245 return 0;
246}
247
248int cond_broadcast(Condition* condition) {
249 if (condition == NULL) {
250 return -1;
251 }
252
253 int ret = pthread_cond_broadcast(condition);
254 if (ret != 0) {
255 fprintf(stderr, "pthread_cond_broadcast failed: %s\n", strerror(ret));
256 return -1;
257 }
258
259 return 0;
260}
261
262int cond_wait(Condition* condition, Lock* lock) {
263 if (condition == NULL || lock == NULL) {
264 return -1;
265 }
266
267 int ret = pthread_cond_wait(condition, lock);
268 if (ret != 0) {
269 fprintf(stderr, "pthread_cond_wait failed: %s\n", strerror(ret));
270 return -1;
271 }
272 return 0;
273}
274
275int cond_wait_timeout(Condition* condition, Lock* lock, int timeout_ms) {
276 if (condition == NULL || lock == NULL) {
277 return -1;
278 }
279
280 if (timeout_ms < 0) {
281 // Negative timeout means wait indefinitely
282 return cond_wait(condition, lock);
283 }
284
285 struct timespec ts;
286 if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
287 fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
288 return -1;
289 }
290
291 // Add timeout to current time
292 ts.tv_sec += timeout_ms / 1000;
293 ts.tv_nsec += (timeout_ms % 1000) * 1000000L;
294
295 // Handle nanosecond overflow
296 if (ts.tv_nsec >= 1000000000L) {
297 ts.tv_sec++;
298 ts.tv_nsec -= 1000000000L;
299 }
300
301 int ret = pthread_cond_timedwait(condition, lock, &ts);
302 switch (ret) {
303 case 0:
304 return 0;
305 case ETIMEDOUT:
306 return -1;
307 case EINVAL:
308 fprintf(stderr, "Invalid parameters in pthread_cond_timedwait\n");
309 return -1;
310 default:
311 fprintf(stderr, "pthread_cond_timedwait failed: %s\n", strerror(ret));
312 return -1;
313 }
314}
315
316int cond_free(Condition* condition) {
317 if (condition == NULL) {
318 return 0; // NULL is valid for cleanup functions
319 }
320
321 int ret = pthread_cond_destroy(condition);
322 if (ret != 0) {
323 fprintf(stderr, "pthread_cond_destroy failed: %s\n", strerror(ret));
324 return -1;
325 }
326
327 return 0;
328}
329
330#endif
pthread_mutex_t Lock
Definition lock.h:32
int lock_init(Lock *lock)
Definition lock.c:132
int cond_wait(Condition *condition, Lock *lock)
Definition lock.c:262
int cond_free(Condition *condition)
Definition lock.c:316
int cond_init(Condition *condition)
Definition lock.c:220
int lock_acquire(Lock *lock)
Definition lock.c:145
int cond_wait_timeout(Condition *condition, Lock *lock, int timeout_ms)
Definition lock.c:275
int lock_release(Lock *lock)
Definition lock.c:168
int cond_signal(Condition *condition)
Definition lock.c:234
int lock_try_acquire(Lock *lock)
Definition lock.c:196
int cond_broadcast(Condition *condition)
Definition lock.c:248
int lock_free(Lock *lock)
Definition lock.c:182
pthread_cond_t Condition
Definition lock.h:34
int lock_wait(Lock *lock, Condition *condition, int timeout_ms)
Definition lock.c:216