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