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