1 /*
2 * Threading primitives for CUPS.
3 *
4 * Copyright © 2009-2018 by Apple Inc.
5 *
6 * Licensed under Apache License v2.0. See the file "LICENSE" for more
7 * information.
8 */
9
10 /*
11 * Include necessary headers...
12 */
13
14 #include "cups-private.h"
15 #include "thread-private.h"
16
17
18 #if defined(HAVE_PTHREAD_H)
19 /*
20 * '_cupsCondBroadcast()' - Wake up waiting threads.
21 */
22
23 void
_cupsCondBroadcast(_cups_cond_t * cond)24 _cupsCondBroadcast(_cups_cond_t *cond) /* I - Condition */
25 {
26 pthread_cond_broadcast(cond);
27 }
28
29
30 /*
31 * '_cupsCondInit()' - Initialize a condition variable.
32 */
33
34 void
_cupsCondInit(_cups_cond_t * cond)35 _cupsCondInit(_cups_cond_t *cond) /* I - Condition */
36 {
37 pthread_cond_init(cond, NULL);
38 }
39
40
41 /*
42 * '_cupsCondWait()' - Wait for a condition with optional timeout.
43 */
44
45 void
_cupsCondWait(_cups_cond_t * cond,_cups_mutex_t * mutex,double timeout)46 _cupsCondWait(_cups_cond_t *cond, /* I - Condition */
47 _cups_mutex_t *mutex, /* I - Mutex */
48 double timeout) /* I - Timeout in seconds (0 or negative for none) */
49 {
50 if (timeout > 0.0)
51 {
52 struct timespec abstime; /* Timeout */
53
54 clock_gettime(CLOCK_REALTIME, &abstime);
55
56 abstime.tv_sec += (long)timeout;
57 abstime.tv_nsec += (long)(1000000000 * (timeout - (long)timeout));
58
59 while (abstime.tv_nsec >= 1000000000)
60 {
61 abstime.tv_nsec -= 1000000000;
62 abstime.tv_sec ++;
63 };
64
65 pthread_cond_timedwait(cond, mutex, &abstime);
66 }
67 else
68 pthread_cond_wait(cond, mutex);
69 }
70
71
72 /*
73 * '_cupsMutexInit()' - Initialize a mutex.
74 */
75
76 void
_cupsMutexInit(_cups_mutex_t * mutex)77 _cupsMutexInit(_cups_mutex_t *mutex) /* I - Mutex */
78 {
79 pthread_mutex_init(mutex, NULL);
80 }
81
82
83 /*
84 * '_cupsMutexLock()' - Lock a mutex.
85 */
86
87 void
_cupsMutexLock(_cups_mutex_t * mutex)88 _cupsMutexLock(_cups_mutex_t *mutex) /* I - Mutex */
89 {
90 pthread_mutex_lock(mutex);
91 }
92
93
94 /*
95 * '_cupsMutexUnlock()' - Unlock a mutex.
96 */
97
98 void
_cupsMutexUnlock(_cups_mutex_t * mutex)99 _cupsMutexUnlock(_cups_mutex_t *mutex) /* I - Mutex */
100 {
101 pthread_mutex_unlock(mutex);
102 }
103
104
105 /*
106 * '_cupsRWInit()' - Initialize a reader/writer lock.
107 */
108
109 void
_cupsRWInit(_cups_rwlock_t * rwlock)110 _cupsRWInit(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
111 {
112 pthread_rwlock_init(rwlock, NULL);
113 }
114
115
116 /*
117 * '_cupsRWLockRead()' - Acquire a reader/writer lock for reading.
118 */
119
120 void
_cupsRWLockRead(_cups_rwlock_t * rwlock)121 _cupsRWLockRead(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
122 {
123 pthread_rwlock_rdlock(rwlock);
124 }
125
126
127 /*
128 * '_cupsRWLockWrite()' - Acquire a reader/writer lock for writing.
129 */
130
131 void
_cupsRWLockWrite(_cups_rwlock_t * rwlock)132 _cupsRWLockWrite(_cups_rwlock_t *rwlock)/* I - Reader/writer lock */
133 {
134 pthread_rwlock_wrlock(rwlock);
135 }
136
137
138 /*
139 * '_cupsRWUnlock()' - Release a reader/writer lock.
140 */
141
142 void
_cupsRWUnlock(_cups_rwlock_t * rwlock)143 _cupsRWUnlock(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
144 {
145 pthread_rwlock_unlock(rwlock);
146 }
147
148
149 /*
150 * '_cupsThreadCancel()' - Cancel (kill) a thread.
151 */
152
153 void
_cupsThreadCancel(_cups_thread_t thread)154 _cupsThreadCancel(_cups_thread_t thread)/* I - Thread ID */
155 {
156 pthread_cancel(thread);
157 }
158
159
160 /*
161 * '_cupsThreadCreate()' - Create a thread.
162 */
163
164 _cups_thread_t /* O - Thread ID */
_cupsThreadCreate(_cups_thread_func_t func,void * arg)165 _cupsThreadCreate(
166 _cups_thread_func_t func, /* I - Entry point */
167 void *arg) /* I - Entry point context */
168 {
169 pthread_t thread;
170
171 if (pthread_create(&thread, NULL, (void *(*)(void *))func, arg))
172 return (0);
173 else
174 return (thread);
175 }
176
177
178 /*
179 * '_cupsThreadDetach()' - Tell the OS that the thread is running independently.
180 */
181
182 void
_cupsThreadDetach(_cups_thread_t thread)183 _cupsThreadDetach(_cups_thread_t thread)/* I - Thread ID */
184 {
185 pthread_detach(thread);
186 }
187
188
189 /*
190 * '_cupsThreadWait()' - Wait for a thread to exit.
191 */
192
193 void * /* O - Return value */
_cupsThreadWait(_cups_thread_t thread)194 _cupsThreadWait(_cups_thread_t thread) /* I - Thread ID */
195 {
196 void *ret; /* Return value */
197
198
199 if (pthread_join(thread, &ret))
200 return (NULL);
201 else
202 return (ret);
203 }
204
205
206 #elif defined(_WIN32)
207 # include <process.h>
208
209
210 /*
211 * '_cupsCondBroadcast()' - Wake up waiting threads.
212 */
213
214 void
_cupsCondBroadcast(_cups_cond_t * cond)215 _cupsCondBroadcast(_cups_cond_t *cond) /* I - Condition */
216 {
217 // TODO: Implement me
218 }
219
220
221 /*
222 * '_cupsCondInit()' - Initialize a condition variable.
223 */
224
225 void
_cupsCondInit(_cups_cond_t * cond)226 _cupsCondInit(_cups_cond_t *cond) /* I - Condition */
227 {
228 // TODO: Implement me
229 }
230
231
232 /*
233 * '_cupsCondWait()' - Wait for a condition with optional timeout.
234 */
235
236 void
_cupsCondWait(_cups_cond_t * cond,_cups_mutex_t * mutex,double timeout)237 _cupsCondWait(_cups_cond_t *cond, /* I - Condition */
238 _cups_mutex_t *mutex, /* I - Mutex */
239 double timeout) /* I - Timeout in seconds (0 or negative for none) */
240 {
241 // TODO: Implement me
242 }
243
244
245 /*
246 * '_cupsMutexInit()' - Initialize a mutex.
247 */
248
249 void
_cupsMutexInit(_cups_mutex_t * mutex)250 _cupsMutexInit(_cups_mutex_t *mutex) /* I - Mutex */
251 {
252 InitializeCriticalSection(&mutex->m_criticalSection);
253 mutex->m_init = 1;
254 }
255
256
257 /*
258 * '_cupsMutexLock()' - Lock a mutex.
259 */
260
261 void
_cupsMutexLock(_cups_mutex_t * mutex)262 _cupsMutexLock(_cups_mutex_t *mutex) /* I - Mutex */
263 {
264 if (!mutex->m_init)
265 {
266 _cupsGlobalLock();
267
268 if (!mutex->m_init)
269 {
270 InitializeCriticalSection(&mutex->m_criticalSection);
271 mutex->m_init = 1;
272 }
273
274 _cupsGlobalUnlock();
275 }
276
277 EnterCriticalSection(&mutex->m_criticalSection);
278 }
279
280
281 /*
282 * '_cupsMutexUnlock()' - Unlock a mutex.
283 */
284
285 void
_cupsMutexUnlock(_cups_mutex_t * mutex)286 _cupsMutexUnlock(_cups_mutex_t *mutex) /* I - Mutex */
287 {
288 LeaveCriticalSection(&mutex->m_criticalSection);
289 }
290
291
292 /*
293 * '_cupsRWInit()' - Initialize a reader/writer lock.
294 */
295
296 void
_cupsRWInit(_cups_rwlock_t * rwlock)297 _cupsRWInit(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
298 {
299 _cupsMutexInit((_cups_mutex_t *)rwlock);
300 }
301
302
303 /*
304 * '_cupsRWLockRead()' - Acquire a reader/writer lock for reading.
305 */
306
307 void
_cupsRWLockRead(_cups_rwlock_t * rwlock)308 _cupsRWLockRead(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
309 {
310 _cupsMutexLock((_cups_mutex_t *)rwlock);
311 }
312
313
314 /*
315 * '_cupsRWLockWrite()' - Acquire a reader/writer lock for writing.
316 */
317
318 void
_cupsRWLockWrite(_cups_rwlock_t * rwlock)319 _cupsRWLockWrite(_cups_rwlock_t *rwlock)/* I - Reader/writer lock */
320 {
321 _cupsMutexLock((_cups_mutex_t *)rwlock);
322 }
323
324
325 /*
326 * '_cupsRWUnlock()' - Release a reader/writer lock.
327 */
328
329 void
_cupsRWUnlock(_cups_rwlock_t * rwlock)330 _cupsRWUnlock(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
331 {
332 _cupsMutexUnlock((_cups_mutex_t *)rwlock);
333 }
334
335
336 /*
337 * '_cupsThreadCancel()' - Cancel (kill) a thread.
338 */
339
340 void
_cupsThreadCancel(_cups_thread_t thread)341 _cupsThreadCancel(_cups_thread_t thread)/* I - Thread ID */
342 {
343 // TODO: Implement me
344 }
345
346
347 /*
348 * '_cupsThreadCreate()' - Create a thread.
349 */
350
351 _cups_thread_t /* O - Thread ID */
_cupsThreadCreate(_cups_thread_func_t func,void * arg)352 _cupsThreadCreate(
353 _cups_thread_func_t func, /* I - Entry point */
354 void *arg) /* I - Entry point context */
355 {
356 return (_beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL));
357 }
358
359
360 /*
361 * '_cupsThreadDetach()' - Tell the OS that the thread is running independently.
362 */
363
364 void
_cupsThreadDetach(_cups_thread_t thread)365 _cupsThreadDetach(_cups_thread_t thread)/* I - Thread ID */
366 {
367 // TODO: Implement me
368 (void)thread;
369 }
370
371
372 /*
373 * '_cupsThreadWait()' - Wait for a thread to exit.
374 */
375
376 void * /* O - Return value */
_cupsThreadWait(_cups_thread_t thread)377 _cupsThreadWait(_cups_thread_t thread) /* I - Thread ID */
378 {
379 // TODO: Implement me
380 (void)thread;
381
382 return (NULL);
383 }
384
385
386 #else /* No threading */
387 /*
388 * '_cupsCondBroadcast()' - Wake up waiting threads.
389 */
390
391 void
_cupsCondBroadcast(_cups_cond_t * cond)392 _cupsCondBroadcast(_cups_cond_t *cond) /* I - Condition */
393 {
394 // TODO: Implement me
395 }
396
397
398 /*
399 * '_cupsCondInit()' - Initialize a condition variable.
400 */
401
402 void
_cupsCondInit(_cups_cond_t * cond)403 _cupsCondInit(_cups_cond_t *cond) /* I - Condition */
404 {
405 // TODO: Implement me
406 }
407
408
409 /*
410 * '_cupsCondWait()' - Wait for a condition with optional timeout.
411 */
412
413 void
_cupsCondWait(_cups_cond_t * cond,_cups_mutex_t * mutex,double timeout)414 _cupsCondWait(_cups_cond_t *cond, /* I - Condition */
415 _cups_mutex_t *mutex, /* I - Mutex */
416 double timeout) /* I - Timeout in seconds (0 or negative for none) */
417 {
418 // TODO: Implement me
419 }
420
421
422 /*
423 * '_cupsMutexInit()' - Initialize a mutex.
424 */
425
426 void
_cupsMutexInit(_cups_mutex_t * mutex)427 _cupsMutexInit(_cups_mutex_t *mutex) /* I - Mutex */
428 {
429 (void)mutex;
430 }
431
432
433 /*
434 * '_cupsMutexLock()' - Lock a mutex.
435 */
436
437 void
_cupsMutexLock(_cups_mutex_t * mutex)438 _cupsMutexLock(_cups_mutex_t *mutex) /* I - Mutex */
439 {
440 (void)mutex;
441 }
442
443
444 /*
445 * '_cupsMutexUnlock()' - Unlock a mutex.
446 */
447
448 void
_cupsMutexUnlock(_cups_mutex_t * mutex)449 _cupsMutexUnlock(_cups_mutex_t *mutex) /* I - Mutex */
450 {
451 (void)mutex;
452 }
453
454
455 /*
456 * '_cupsRWInit()' - Initialize a reader/writer lock.
457 */
458
459 void
_cupsRWInit(_cups_rwlock_t * rwlock)460 _cupsRWInit(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
461 {
462 (void)rwlock;
463 }
464
465
466 /*
467 * '_cupsRWLockRead()' - Acquire a reader/writer lock for reading.
468 */
469
470 void
_cupsRWLockRead(_cups_rwlock_t * rwlock)471 _cupsRWLockRead(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
472 {
473 (void)rwlock;
474 }
475
476
477 /*
478 * '_cupsRWLockWrite()' - Acquire a reader/writer lock for writing.
479 */
480
481 void
_cupsRWLockWrite(_cups_rwlock_t * rwlock)482 _cupsRWLockWrite(_cups_rwlock_t *rwlock)/* I - Reader/writer lock */
483 {
484 (void)rwlock;
485 }
486
487
488 /*
489 * '_cupsRWUnlock()' - Release a reader/writer lock.
490 */
491
492 void
_cupsRWUnlock(_cups_rwlock_t * rwlock)493 _cupsRWUnlock(_cups_rwlock_t *rwlock) /* I - Reader/writer lock */
494 {
495 (void)rwlock;
496 }
497
498
499 /*
500 * '_cupsThreadCancel()' - Cancel (kill) a thread.
501 */
502
503 void
_cupsThreadCancel(_cups_thread_t thread)504 _cupsThreadCancel(_cups_thread_t thread)/* I - Thread ID */
505 {
506 (void)thread;
507 }
508
509
510 /*
511 * '_cupsThreadCreate()' - Create a thread.
512 */
513
514 _cups_thread_t /* O - Thread ID */
_cupsThreadCreate(_cups_thread_func_t func,void * arg)515 _cupsThreadCreate(
516 _cups_thread_func_t func, /* I - Entry point */
517 void *arg) /* I - Entry point context */
518 {
519 fputs("DEBUG: CUPS was compiled without threading support, no thread created.\n", stderr);
520
521 (void)func;
522 (void)arg;
523
524 return (0);
525 }
526
527
528 /*
529 * '_cupsThreadDetach()' - Tell the OS that the thread is running independently.
530 */
531
532 void
_cupsThreadDetach(_cups_thread_t thread)533 _cupsThreadDetach(_cups_thread_t thread)/* I - Thread ID */
534 {
535 (void)thread;
536 }
537
538
539 /*
540 * '_cupsThreadWait()' - Wait for a thread to exit.
541 */
542
543 void * /* O - Return value */
_cupsThreadWait(_cups_thread_t thread)544 _cupsThreadWait(_cups_thread_t thread) /* I - Thread ID */
545 {
546 (void)thread;
547
548 return (NULL);
549 }
550
551 #endif /* HAVE_PTHREAD_H */
552