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