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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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