• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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