1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "system.h" 25 #include <string.h> 26 #include <osl/diagnose.h> 27 #include <osl/thread.h> 28 #include <osl/nlsupport.h> 29 #ifndef _RTL_TEXTENC_H_ 30 #include <rtl/textenc.h> 31 #endif 32 33 #if defined LINUX 34 #include <sys/prctl.h> 35 #endif 36 37 /**************************************************************************** 38 * @@@ TODO @@@ 39 * 40 * (1) 'osl_thread_priority_init_Impl()' 41 * - insane assumption that initializing caller is main thread 42 * - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?) 43 * - POSIX doesn't require defined prio's for SCHED_OTHER (!) 44 * - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?) 45 * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()' 46 * - cannot reliably be applied to 'alien' threads; 47 * - memory leak for 'alien' thread 'HashEntry's; 48 * - use 'PTHREAD_VALUE(pthread_t)' as identifier instead (?) 49 * - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar 50 * (3) 'oslSigAlarmHandler()' (#71232#) 51 * - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates 52 * the process. So we initialize our signal handling module and do 53 * register a SIGALRM Handler which catches and ignores it] 54 * - should this still happen, 'signal.c' needs to be fixed instead. 55 * 56 ****************************************************************************/ 57 58 /*****************************************************************************/ 59 /* Internal data structures and functions */ 60 /*****************************************************************************/ 61 62 #define THREADIMPL_FLAGS_TERMINATE 0x00001 63 #define THREADIMPL_FLAGS_STARTUP 0x00002 64 #define THREADIMPL_FLAGS_SUSPENDED 0x00004 65 #define THREADIMPL_FLAGS_ACTIVE 0x00008 66 #define THREADIMPL_FLAGS_ATTACHED 0x00010 67 #define THREADIMPL_FLAGS_DESTROYED 0x00020 68 69 typedef struct osl_thread_impl_st 70 { 71 pthread_t m_hThread; 72 sal_uInt16 m_Ident; /* @@@ see TODO @@@ */ 73 short m_Flags; 74 oslWorkerFunction m_WorkerFunction; 75 void* m_pData; 76 pthread_mutex_t m_Lock; 77 pthread_cond_t m_Cond; 78 } Thread_Impl; 79 80 struct osl_thread_priority_st 81 { 82 int m_Highest; 83 int m_Above_Normal; 84 int m_Normal; 85 int m_Below_Normal; 86 int m_Lowest; 87 }; 88 89 #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 } 90 static void osl_thread_priority_init_Impl (void); 91 92 struct osl_thread_textencoding_st 93 { 94 pthread_key_t m_key; /* key to store thread local text encoding */ 95 rtl_TextEncoding m_default; /* the default text encoding */ 96 }; 97 98 #define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW } 99 static void osl_thread_textencoding_init_Impl (void); 100 101 struct osl_thread_global_st 102 { 103 pthread_once_t m_once; 104 struct osl_thread_priority_st m_priority; 105 struct osl_thread_textencoding_st m_textencoding; 106 }; 107 108 static struct osl_thread_global_st g_thread = 109 { 110 PTHREAD_ONCE_INIT, 111 OSL_THREAD_PRIORITY_INITIALIZER, 112 OSL_THREAD_TEXTENCODING_INITIALIZER 113 }; 114 115 static void osl_thread_init_Impl (void); 116 117 static Thread_Impl* osl_thread_construct_Impl (void); 118 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl); 119 120 static void* osl_thread_start_Impl (void * pData); 121 static void osl_thread_cleanup_Impl (void * pData); 122 123 static oslThread osl_thread_create_Impl ( 124 oslWorkerFunction pWorker, void * pThreadData, short nFlags); 125 126 static void osl_thread_join_cleanup_Impl (void * opaque); 127 static void osl_thread_wait_cleanup_Impl (void * opaque); 128 129 /* @@@ see TODO @@@ */ 130 static sal_uInt16 insertThreadId (pthread_t hThread); 131 static sal_uInt16 lookupThreadId (pthread_t hThread); 132 static void removeThreadId (pthread_t hThread); 133 134 /*****************************************************************************/ 135 /* osl_thread_init_Impl */ 136 /*****************************************************************************/ 137 static void osl_thread_init_Impl (void) 138 { 139 osl_thread_priority_init_Impl(); 140 osl_thread_textencoding_init_Impl(); 141 } 142 143 /*****************************************************************************/ 144 /* osl_thread_join_cleanup_Impl */ 145 /*****************************************************************************/ 146 static void osl_thread_join_cleanup_Impl (void * opaque) 147 { 148 pthread_t hThread = (pthread_t)(opaque); 149 pthread_detach (hThread); 150 } 151 152 /*****************************************************************************/ 153 /* osl_thread_wait_cleanup_Impl */ 154 /*****************************************************************************/ 155 static void osl_thread_wait_cleanup_Impl (void * opaque) 156 { 157 pthread_mutex_t * pMutex = (pthread_mutex_t*)(opaque); 158 pthread_mutex_unlock (pMutex); 159 } 160 161 /*****************************************************************************/ 162 /* osl_thread_construct_Impl */ 163 /*****************************************************************************/ 164 Thread_Impl* osl_thread_construct_Impl (void) 165 { 166 Thread_Impl* pImpl = malloc (sizeof(Thread_Impl)); 167 if (pImpl) 168 { 169 memset (pImpl, 0, sizeof(Thread_Impl)); 170 171 pthread_mutex_init (&(pImpl->m_Lock), PTHREAD_MUTEXATTR_DEFAULT); 172 pthread_cond_init (&(pImpl->m_Cond), PTHREAD_CONDATTR_DEFAULT); 173 } 174 return (pImpl); 175 } 176 177 /*****************************************************************************/ 178 /* osl_thread_destruct_Impl */ 179 /*****************************************************************************/ 180 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl) 181 { 182 OSL_ASSERT(ppImpl); 183 if (*ppImpl) 184 { 185 pthread_cond_destroy (&((*ppImpl)->m_Cond)); 186 pthread_mutex_destroy (&((*ppImpl)->m_Lock)); 187 188 free (*ppImpl); 189 (*ppImpl) = NULL; 190 } 191 } 192 193 /*****************************************************************************/ 194 /* osl_thread_cleanup_Impl */ 195 /*****************************************************************************/ 196 static void osl_thread_cleanup_Impl (void* pData) 197 { 198 pthread_t thread; 199 int attached; 200 int destroyed; 201 Thread_Impl* pImpl= (Thread_Impl*)pData; 202 203 pthread_mutex_lock (&(pImpl->m_Lock)); 204 205 thread = pImpl->m_hThread; 206 attached = (pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) != 0; 207 destroyed = (pImpl->m_Flags & THREADIMPL_FLAGS_DESTROYED) != 0; 208 pImpl->m_Flags &= ~(THREADIMPL_FLAGS_ACTIVE | THREADIMPL_FLAGS_ATTACHED); 209 210 pthread_mutex_unlock (&(pImpl->m_Lock)); 211 212 /* release oslThreadIdentifier @@@ see TODO @@@ */ 213 removeThreadId (thread); 214 215 if (attached) 216 { 217 pthread_detach (thread); 218 } 219 220 if (destroyed) 221 { 222 osl_thread_destruct_Impl (&pImpl); 223 } 224 } 225 226 /*****************************************************************************/ 227 /* osl_thread_start_Impl */ 228 /*****************************************************************************/ 229 static void* osl_thread_start_Impl (void* pData) 230 { 231 int terminate; 232 Thread_Impl* pImpl= (Thread_Impl*)pData; 233 234 OSL_ASSERT(pImpl); 235 236 pthread_mutex_lock (&(pImpl->m_Lock)); 237 238 /* install cleanup handler */ 239 pthread_cleanup_push (osl_thread_cleanup_Impl, pData); 240 241 /* request oslThreadIdentifier @@@ see TODO @@@ */ 242 pImpl->m_Ident = insertThreadId (pImpl->m_hThread); 243 244 /* signal change from STARTUP to ACTIVE state */ 245 pImpl->m_Flags &= ~THREADIMPL_FLAGS_STARTUP; 246 pImpl->m_Flags |= THREADIMPL_FLAGS_ACTIVE; 247 pthread_cond_signal (&(pImpl->m_Cond)); 248 249 /* Check if thread is started in SUSPENDED state */ 250 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 251 { 252 /* wait until SUSPENDED flag is cleared */ 253 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 254 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 255 pthread_cleanup_pop (0); 256 } 257 258 /* check for SUSPENDED to TERMINATE state change */ 259 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0); 260 261 pthread_mutex_unlock (&(pImpl->m_Lock)); 262 263 if (!terminate) 264 { 265 /* call worker function */ 266 pImpl->m_WorkerFunction(pImpl->m_pData); 267 } 268 269 /* call cleanup handler and leave */ 270 pthread_cleanup_pop (1); 271 return (0); 272 } 273 274 /*****************************************************************************/ 275 /* osl_thread_create_Impl */ 276 /*****************************************************************************/ 277 static oslThread osl_thread_create_Impl ( 278 oslWorkerFunction pWorker, 279 void* pThreadData, 280 short nFlags) 281 { 282 Thread_Impl* pImpl; 283 int nRet=0; 284 285 pImpl = osl_thread_construct_Impl(); 286 if (!pImpl) 287 return (0); /* ENOMEM */ 288 289 pImpl->m_WorkerFunction = pWorker; 290 pImpl->m_pData = pThreadData; 291 pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP; 292 293 pthread_mutex_lock (&(pImpl->m_Lock)); 294 295 if ((nRet = pthread_create ( 296 &(pImpl->m_hThread), 297 PTHREAD_ATTR_DEFAULT, 298 osl_thread_start_Impl, 299 (void*)(pImpl))) != 0) 300 { 301 OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n", 302 nRet, strerror(nRet)); 303 304 pthread_mutex_unlock (&(pImpl->m_Lock)); 305 osl_thread_destruct_Impl (&pImpl); 306 307 return (0); 308 } 309 310 /* wait for change from STARTUP to ACTIVE state */ 311 while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP) 312 { 313 /* wait until STARTUP flag is cleared */ 314 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 315 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 316 pthread_cleanup_pop (0); 317 } 318 319 pthread_mutex_unlock (&(pImpl->m_Lock)); 320 321 return ((oslThread)(pImpl)); 322 } 323 324 /*****************************************************************************/ 325 /* osl_createThread */ 326 /*****************************************************************************/ 327 oslThread osl_createThread ( 328 oslWorkerFunction pWorker, 329 void * pThreadData) 330 { 331 return osl_thread_create_Impl ( 332 pWorker, 333 pThreadData, 334 THREADIMPL_FLAGS_ATTACHED); 335 } 336 337 /*****************************************************************************/ 338 /* osl_createSuspendedThread */ 339 /*****************************************************************************/ 340 oslThread osl_createSuspendedThread ( 341 oslWorkerFunction pWorker, 342 void * pThreadData) 343 { 344 return osl_thread_create_Impl ( 345 pWorker, 346 pThreadData, 347 THREADIMPL_FLAGS_ATTACHED | 348 THREADIMPL_FLAGS_SUSPENDED ); 349 } 350 351 /*****************************************************************************/ 352 /* osl_destroyThread */ 353 /*****************************************************************************/ 354 void SAL_CALL osl_destroyThread(oslThread Thread) 355 { 356 if (Thread != NULL) { 357 Thread_Impl * impl = (Thread_Impl *) Thread; 358 int active; 359 pthread_mutex_lock(&impl->m_Lock); 360 active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0; 361 impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED; 362 pthread_mutex_unlock(&impl->m_Lock); 363 if (!active) { 364 osl_thread_destruct_Impl(&impl); 365 } 366 } 367 } 368 369 /*****************************************************************************/ 370 /* osl_resumeThread */ 371 /*****************************************************************************/ 372 void SAL_CALL osl_resumeThread(oslThread Thread) 373 { 374 Thread_Impl* pImpl= (Thread_Impl*)Thread; 375 376 OSL_ASSERT(pImpl); 377 if (!pImpl) 378 return; /* EINVAL */ 379 380 pthread_mutex_lock (&(pImpl->m_Lock)); 381 382 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 383 { 384 /* clear SUSPENDED flag */ 385 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED; 386 pthread_cond_signal (&(pImpl->m_Cond)); 387 } 388 389 pthread_mutex_unlock (&(pImpl->m_Lock)); 390 } 391 392 /*****************************************************************************/ 393 /* osl_suspendThread */ 394 /*****************************************************************************/ 395 void SAL_CALL osl_suspendThread(oslThread Thread) 396 { 397 Thread_Impl* pImpl= (Thread_Impl*)Thread; 398 399 OSL_ASSERT(pImpl); 400 if (!pImpl) 401 return; /* EINVAL */ 402 403 pthread_mutex_lock (&(pImpl->m_Lock)); 404 405 pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED; 406 407 if (pthread_equal (pthread_self(), pImpl->m_hThread)) 408 { 409 /* self suspend */ 410 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 411 { 412 /* wait until SUSPENDED flag is cleared */ 413 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 414 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 415 pthread_cleanup_pop (0); 416 } 417 } 418 419 pthread_mutex_unlock (&(pImpl->m_Lock)); 420 } 421 422 /*****************************************************************************/ 423 /* osl_isThreadRunning */ 424 /*****************************************************************************/ 425 sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread) 426 { 427 sal_Bool active; 428 Thread_Impl* pImpl= (Thread_Impl*)Thread; 429 430 if (!pImpl) 431 return sal_False; 432 433 pthread_mutex_lock (&(pImpl->m_Lock)); 434 active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0); 435 pthread_mutex_unlock (&(pImpl->m_Lock)); 436 437 return (active); 438 } 439 440 /*****************************************************************************/ 441 /* osl_joinWithThread */ 442 /*****************************************************************************/ 443 void SAL_CALL osl_joinWithThread(oslThread Thread) 444 { 445 pthread_t thread; 446 int attached; 447 Thread_Impl* pImpl= (Thread_Impl*)Thread; 448 449 if (!pImpl) 450 return; 451 452 pthread_mutex_lock (&(pImpl->m_Lock)); 453 454 if (pthread_equal (pthread_self(), pImpl->m_hThread)) 455 { 456 /* self join */ 457 pthread_mutex_unlock (&(pImpl->m_Lock)); 458 return; /* EDEADLK */ 459 } 460 461 thread = pImpl->m_hThread; 462 attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0); 463 pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED; 464 465 pthread_mutex_unlock (&(pImpl->m_Lock)); 466 467 if (attached) 468 { 469 /* install cleanup handler to ensure consistent flags and state */ 470 pthread_cleanup_push ( 471 osl_thread_join_cleanup_Impl, (void*)thread); 472 473 /* join */ 474 pthread_join (thread, NULL); 475 476 /* remove cleanup handler */ 477 pthread_cleanup_pop (0); 478 } 479 } 480 481 /*****************************************************************************/ 482 /* osl_terminateThread */ 483 /*****************************************************************************/ 484 void SAL_CALL osl_terminateThread(oslThread Thread) 485 { 486 Thread_Impl* pImpl= (Thread_Impl*)Thread; 487 488 OSL_ASSERT(pImpl); 489 if (!pImpl) 490 return; /* EINVAL */ 491 492 pthread_mutex_lock (&(pImpl->m_Lock)); 493 494 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 495 { 496 /* clear SUSPENDED flag */ 497 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED; 498 pthread_cond_signal (&(pImpl->m_Cond)); 499 } 500 501 pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE; 502 503 pthread_mutex_unlock (&(pImpl->m_Lock)); 504 } 505 506 /*****************************************************************************/ 507 /* osl_scheduleThread */ 508 /*****************************************************************************/ 509 sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread) 510 { 511 int terminate; 512 Thread_Impl* pImpl= (Thread_Impl*)Thread; 513 514 OSL_ASSERT(pImpl); 515 if (!pImpl) 516 return sal_False; /* EINVAL */ 517 518 OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread)); 519 if (!(pthread_equal (pthread_self(), pImpl->m_hThread))) 520 return sal_False; /* EINVAL */ 521 522 pthread_testcancel(); 523 pthread_mutex_lock (&(pImpl->m_Lock)); 524 525 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 526 { 527 /* wait until SUSPENDED flag is cleared */ 528 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 529 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 530 pthread_cleanup_pop (0); 531 } 532 533 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0); 534 535 pthread_mutex_unlock(&(pImpl->m_Lock)); 536 pthread_testcancel(); 537 538 return (terminate == 0); 539 } 540 541 /*****************************************************************************/ 542 /* osl_waitThread */ 543 /*****************************************************************************/ 544 void SAL_CALL osl_waitThread(const TimeValue* pDelay) 545 { 546 if (pDelay) 547 { 548 struct timespec delay; 549 550 SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec); 551 552 SLEEP_TIMESPEC(delay); 553 } 554 } 555 556 /*****************************************************************************/ 557 /* osl_yieldThread */ 558 /* 559 Note that POSIX scheduling _really_ requires threads to call this 560 functions, since a thread only reschedules to other thread, when 561 it blocks (sleep, blocking I/O) OR calls sched_yield(). 562 */ 563 /*****************************************************************************/ 564 void SAL_CALL osl_yieldThread() 565 { 566 sched_yield(); 567 } 568 569 void SAL_CALL osl_setThreadName(char const * name) { 570 #if defined LINUX 571 if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) { 572 OSL_TRACE( 573 "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX, 574 errno); 575 } 576 #else 577 (void) name; 578 #endif 579 } 580 581 /*****************************************************************************/ 582 /* osl_getThreadIdentifier @@@ see TODO @@@ */ 583 /*****************************************************************************/ 584 585 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize) 586 587 typedef struct _HashEntry 588 { 589 pthread_t Handle; 590 sal_uInt16 Ident; 591 struct _HashEntry *Next; 592 } HashEntry; 593 594 static HashEntry* HashTable[31]; 595 static int HashSize = sizeof(HashTable) / sizeof(HashTable[0]); 596 597 static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER; 598 599 static sal_uInt16 LastIdent = 0; 600 601 static sal_uInt16 lookupThreadId (pthread_t hThread) 602 { 603 HashEntry *pEntry; 604 605 pthread_mutex_lock(&HashLock); 606 607 pEntry = HashTable[HASHID(hThread)]; 608 while (pEntry != NULL) 609 { 610 if (pthread_equal(pEntry->Handle, hThread)) 611 { 612 pthread_mutex_unlock(&HashLock); 613 return (pEntry->Ident); 614 } 615 pEntry = pEntry->Next; 616 } 617 618 pthread_mutex_unlock(&HashLock); 619 620 return (0); 621 } 622 623 static sal_uInt16 insertThreadId (pthread_t hThread) 624 { 625 HashEntry *pEntry, *pInsert = NULL; 626 627 pthread_mutex_lock(&HashLock); 628 629 pEntry = HashTable[HASHID(hThread)]; 630 631 while (pEntry != NULL) 632 { 633 if (pthread_equal(pEntry->Handle, hThread)) 634 break; 635 636 pInsert = pEntry; 637 pEntry = pEntry->Next; 638 } 639 640 if (pEntry == NULL) 641 { 642 pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1); 643 644 pEntry->Handle = hThread; 645 646 ++ LastIdent; 647 648 if ( LastIdent == 0 ) 649 LastIdent = 1; 650 651 pEntry->Ident = LastIdent; 652 653 if (pInsert) 654 pInsert->Next = pEntry; 655 else 656 HashTable[HASHID(hThread)] = pEntry; 657 } 658 659 pthread_mutex_unlock(&HashLock); 660 661 return (pEntry->Ident); 662 } 663 664 static void removeThreadId (pthread_t hThread) 665 { 666 HashEntry *pEntry, *pRemove = NULL; 667 668 pthread_mutex_lock(&HashLock); 669 670 pEntry = HashTable[HASHID(hThread)]; 671 while (pEntry != NULL) 672 { 673 if (pthread_equal(pEntry->Handle, hThread)) 674 break; 675 676 pRemove = pEntry; 677 pEntry = pEntry->Next; 678 } 679 680 if (pEntry != NULL) 681 { 682 if (pRemove) 683 pRemove->Next = pEntry->Next; 684 else 685 HashTable[HASHID(hThread)] = pEntry->Next; 686 687 free(pEntry); 688 } 689 690 pthread_mutex_unlock(&HashLock); 691 } 692 693 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread) 694 { 695 Thread_Impl* pImpl= (Thread_Impl*)Thread; 696 sal_uInt16 Ident; 697 698 if (pImpl) 699 Ident = pImpl->m_Ident; 700 else 701 { 702 /* current thread */ 703 pthread_t current = pthread_self(); 704 705 Ident = lookupThreadId (current); 706 if (Ident == 0) 707 /* @@@ see TODO: alien pthread_self() @@@ */ 708 Ident = insertThreadId (current); 709 } 710 711 return ((oslThreadIdentifier)(Ident)); 712 } 713 714 /***************************************************************************** 715 @@@ see TODO @@@ 716 osl_thread_priority_init_Impl 717 718 set the base-priority of the main-thread to 719 oslThreadPriorityNormal (64) since 0 (lowest) is 720 the system default. This behaviour collides with 721 our enum-priority definition (highest..normal..lowest). 722 A normaluser will expect the main-thread of an app. 723 to have the "normal" priority. 724 725 *****************************************************************************/ 726 static void osl_thread_priority_init_Impl (void) 727 { 728 #ifndef NO_PTHREAD_PRIORITY 729 struct sched_param param; 730 int policy=0; 731 int nRet=0; 732 733 /* @@@ see TODO: calling thread may not be main thread @@@ */ 734 735 if ((nRet = pthread_getschedparam(pthread_self(), &policy, ¶m)) != 0) 736 { 737 OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet)); 738 return; 739 } 740 741 #if defined (SOLARIS) 742 if ( policy >= _SCHED_NEXT) 743 { 744 /* mfe: pthread_getschedparam on Solaris has a possible Bug */ 745 /* one gets 959917873 as the policy */ 746 /* so set the policy to a default one */ 747 policy=SCHED_OTHER; 748 } 749 #endif /* SOLARIS */ 750 751 if ((nRet = sched_get_priority_min(policy) ) != -1) 752 { 753 OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet); 754 g_thread.m_priority.m_Lowest=nRet; 755 } 756 #if OSL_DEBUG_LEVEL > 1 757 else 758 { 759 fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno)); 760 } 761 #endif /* OSL_DEBUG_LEVEL */ 762 763 if ((nRet = sched_get_priority_max(policy) ) != -1) 764 { 765 OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet); 766 g_thread.m_priority.m_Highest=nRet; 767 } 768 #if OSL_DEBUG_LEVEL > 1 769 else 770 { 771 fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno)); 772 } 773 #endif /* OSL_DEBUG_LEVEL */ 774 775 g_thread.m_priority.m_Normal = 776 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2; 777 g_thread.m_priority.m_Below_Normal = 778 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2; 779 g_thread.m_priority.m_Above_Normal = 780 (g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2; 781 782 /* @@@ set prio of calling (not main) thread (?) @@@ */ 783 784 param.sched_priority= g_thread.m_priority.m_Normal; 785 786 if ((nRet = pthread_setschedparam(pthread_self(), policy, ¶m)) != 0) 787 { 788 OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet)); 789 OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority); 790 } 791 792 #endif /* NO_PTHREAD_PRIORITY */ 793 } 794 795 /*****************************************************************************/ 796 /* osl_setThreadPriority */ 797 /* 798 Impl-Notes: contrary to solaris-docu, which claims 799 valid priority-levels from 0 .. INT_MAX, only the 800 range 0..127 is accepted. (0 lowest, 127 highest) 801 */ 802 /*****************************************************************************/ 803 void SAL_CALL osl_setThreadPriority ( 804 oslThread Thread, 805 oslThreadPriority Priority) 806 { 807 #ifndef NO_PTHREAD_PRIORITY 808 809 struct sched_param Param; 810 int policy; 811 int nRet; 812 813 #endif /* NO_PTHREAD_PRIORITY */ 814 815 Thread_Impl* pImpl= (Thread_Impl*)Thread; 816 817 OSL_ASSERT(pImpl); 818 if (!pImpl) 819 return; /* EINVAL */ 820 821 #ifdef NO_PTHREAD_PRIORITY 822 (void) Priority; /* unused */ 823 #else /* NO_PTHREAD_PRIORITY */ 824 825 if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0) 826 return; /* ESRCH */ 827 828 #if defined (SOLARIS) 829 if ( policy >= _SCHED_NEXT) 830 { 831 /* mfe: pthread_getschedparam on Solaris has a possible Bug */ 832 /* one gets 959917873 as the policy */ 833 /* so set the policy to a default one */ 834 policy=SCHED_OTHER; 835 } 836 #endif /* SOLARIS */ 837 838 pthread_once (&(g_thread.m_once), osl_thread_init_Impl); 839 840 switch(Priority) 841 { 842 case osl_Thread_PriorityHighest: 843 Param.sched_priority= g_thread.m_priority.m_Highest; 844 break; 845 846 case osl_Thread_PriorityAboveNormal: 847 Param.sched_priority= g_thread.m_priority.m_Above_Normal; 848 break; 849 850 case osl_Thread_PriorityNormal: 851 Param.sched_priority= g_thread.m_priority.m_Normal; 852 break; 853 854 case osl_Thread_PriorityBelowNormal: 855 Param.sched_priority= g_thread.m_priority.m_Below_Normal; 856 break; 857 858 case osl_Thread_PriorityLowest: 859 Param.sched_priority= g_thread.m_priority.m_Lowest; 860 break; 861 862 case osl_Thread_PriorityUnknown: 863 OSL_ASSERT(sal_False); /* only fools try this...*/ 864 865 /* let release-version behave friendly */ 866 return; 867 868 default: 869 /* enum expanded, but forgotten here...*/ 870 OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n"); 871 872 /* let release-version behave friendly */ 873 return; 874 } 875 876 if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0) 877 { 878 OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet)); 879 } 880 881 #endif /* NO_PTHREAD_PRIORITY */ 882 } 883 884 /*****************************************************************************/ 885 /* osl_getThreadPriority */ 886 /*****************************************************************************/ 887 oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread) 888 { 889 #ifndef NO_PTHREAD_PRIORITY 890 891 struct sched_param Param; 892 int Policy; 893 894 #endif /* NO_PTHREAD_PRIORITY */ 895 896 oslThreadPriority Priority = osl_Thread_PriorityNormal; 897 Thread_Impl* pImpl= (Thread_Impl*)Thread; 898 899 OSL_ASSERT(pImpl); 900 if (!pImpl) 901 return osl_Thread_PriorityUnknown; /* EINVAL */ 902 903 #ifndef NO_PTHREAD_PRIORITY 904 905 if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0) 906 return osl_Thread_PriorityUnknown; /* ESRCH */ 907 908 pthread_once (&(g_thread.m_once), osl_thread_init_Impl); 909 910 /* map pthread priority to enum */ 911 if (Param.sched_priority==g_thread.m_priority.m_Highest) 912 { 913 /* 127 - highest */ 914 Priority= osl_Thread_PriorityHighest; 915 } 916 else if (Param.sched_priority > g_thread.m_priority.m_Normal) 917 { 918 /* 65..126 - above normal */ 919 Priority= osl_Thread_PriorityAboveNormal; 920 } 921 else if (Param.sched_priority == g_thread.m_priority.m_Normal) 922 { 923 /* normal */ 924 Priority= osl_Thread_PriorityNormal; 925 } 926 else if (Param.sched_priority > g_thread.m_priority.m_Lowest) 927 { 928 /* 63..1 -below normal */ 929 Priority= osl_Thread_PriorityBelowNormal; 930 } 931 else if (Param.sched_priority == g_thread.m_priority.m_Lowest) 932 { 933 /* 0 - lowest */ 934 Priority= osl_Thread_PriorityLowest; 935 } 936 else 937 { 938 /* unknown */ 939 Priority= osl_Thread_PriorityUnknown; 940 } 941 942 #endif /* NO_PTHREAD_PRIORITY */ 943 944 return Priority; 945 } 946 947 /*****************************************************************************/ 948 /* osl_createThreadKey */ 949 /*****************************************************************************/ 950 oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback ) 951 { 952 pthread_key_t key; 953 954 if (pthread_key_create(&key, pCallback) != 0) 955 key = 0; 956 957 return ((oslThreadKey)key); 958 } 959 960 /*****************************************************************************/ 961 /* osl_destroyThreadKey */ 962 /*****************************************************************************/ 963 void SAL_CALL osl_destroyThreadKey(oslThreadKey Key) 964 { 965 pthread_key_delete((pthread_key_t)Key); 966 } 967 968 /*****************************************************************************/ 969 /* osl_getThreadKeyData */ 970 /*****************************************************************************/ 971 void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key) 972 { 973 return (pthread_getspecific((pthread_key_t)Key)); 974 } 975 976 /*****************************************************************************/ 977 /* osl_setThreadKeyData */ 978 /*****************************************************************************/ 979 sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData) 980 { 981 return (pthread_setspecific((pthread_key_t)Key, pData) == 0); 982 } 983 984 /*****************************************************************************/ 985 /* Thread Local Text Encoding */ 986 /*****************************************************************************/ 987 static void osl_thread_textencoding_init_Impl (void) 988 { 989 rtl_TextEncoding defaultEncoding; 990 const char * pszEncoding; 991 992 /* create thread specific data key */ 993 pthread_key_create (&(g_thread.m_textencoding.m_key), NULL); 994 995 /* determine default text encoding */ 996 pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING"); 997 if (pszEncoding) 998 defaultEncoding = atoi(pszEncoding); 999 else 1000 defaultEncoding = osl_getTextEncodingFromLocale(NULL); 1001 1002 OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW); 1003 1004 /* 1005 Tools string functions call abort() on an unknown encoding so ASCII 1006 is a meaningful fallback regardless wether the assertion makes sense. 1007 */ 1008 1009 if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding ) 1010 defaultEncoding = RTL_TEXTENCODING_ASCII_US; 1011 1012 g_thread.m_textencoding.m_default = defaultEncoding; 1013 } 1014 1015 /*****************************************************************************/ 1016 /* osl_getThreadTextEncoding */ 1017 /*****************************************************************************/ 1018 rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding() 1019 { 1020 rtl_TextEncoding threadEncoding; 1021 1022 pthread_once (&(g_thread.m_once), osl_thread_init_Impl); 1023 1024 /* check for thread specific encoding, use default if not set */ 1025 threadEncoding = SAL_INT_CAST( 1026 rtl_TextEncoding, 1027 (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key)); 1028 if (0 == threadEncoding) 1029 threadEncoding = g_thread.m_textencoding.m_default; 1030 1031 return threadEncoding; 1032 } 1033 1034 /*****************************************************************************/ 1035 /* osl_setThreadTextEncoding */ 1036 /*****************************************************************************/ 1037 rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding) 1038 { 1039 rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding(); 1040 1041 /* save encoding in thread local storage */ 1042 pthread_setspecific ( 1043 g_thread.m_textencoding.m_key, 1044 (void*) SAL_INT_CAST(sal_uIntPtr, Encoding)); 1045 1046 return oldThreadEncoding; 1047 } 1048