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", nRet, strerror(nRet)); 302 303 pthread_mutex_unlock (&(pImpl->m_Lock)); 304 osl_thread_destruct_Impl (&pImpl); 305 306 return (0); 307 } 308 309 /* wait for change from STARTUP to ACTIVE state */ 310 while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP) 311 { 312 /* wait until STARTUP flag is cleared */ 313 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 314 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 315 pthread_cleanup_pop (0); 316 } 317 318 pthread_mutex_unlock (&(pImpl->m_Lock)); 319 320 return ((oslThread)(pImpl)); 321 } 322 323 /*****************************************************************************/ 324 /* osl_createThread */ 325 /*****************************************************************************/ 326 oslThread osl_createThread ( 327 oslWorkerFunction pWorker, 328 void * pThreadData) 329 { 330 return osl_thread_create_Impl ( 331 pWorker, 332 pThreadData, 333 THREADIMPL_FLAGS_ATTACHED); 334 } 335 336 /*****************************************************************************/ 337 /* osl_createSuspendedThread */ 338 /*****************************************************************************/ 339 oslThread osl_createSuspendedThread ( 340 oslWorkerFunction pWorker, 341 void * pThreadData) 342 { 343 return osl_thread_create_Impl ( 344 pWorker, 345 pThreadData, 346 THREADIMPL_FLAGS_ATTACHED | 347 THREADIMPL_FLAGS_SUSPENDED ); 348 } 349 350 /*****************************************************************************/ 351 /* osl_destroyThread */ 352 /*****************************************************************************/ 353 void SAL_CALL osl_destroyThread(oslThread Thread) 354 { 355 if (Thread != NULL) { 356 Thread_Impl * impl = (Thread_Impl *) Thread; 357 int active; 358 pthread_mutex_lock(&impl->m_Lock); 359 active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0; 360 impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED; 361 pthread_mutex_unlock(&impl->m_Lock); 362 if (!active) { 363 osl_thread_destruct_Impl(&impl); 364 } 365 } 366 } 367 368 /*****************************************************************************/ 369 /* osl_resumeThread */ 370 /*****************************************************************************/ 371 void SAL_CALL osl_resumeThread(oslThread Thread) 372 { 373 Thread_Impl* pImpl= (Thread_Impl*)Thread; 374 375 OSL_ASSERT(pImpl); 376 if (!pImpl) 377 return; /* EINVAL */ 378 379 pthread_mutex_lock (&(pImpl->m_Lock)); 380 381 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 382 { 383 /* clear SUSPENDED flag */ 384 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED; 385 pthread_cond_signal (&(pImpl->m_Cond)); 386 } 387 388 pthread_mutex_unlock (&(pImpl->m_Lock)); 389 } 390 391 /*****************************************************************************/ 392 /* osl_suspendThread */ 393 /*****************************************************************************/ 394 void SAL_CALL osl_suspendThread(oslThread Thread) 395 { 396 Thread_Impl* pImpl= (Thread_Impl*)Thread; 397 398 OSL_ASSERT(pImpl); 399 if (!pImpl) 400 return; /* EINVAL */ 401 402 pthread_mutex_lock (&(pImpl->m_Lock)); 403 404 pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED; 405 406 if (pthread_equal (pthread_self(), pImpl->m_hThread)) 407 { 408 /* self suspend */ 409 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 410 { 411 /* wait until SUSPENDED flag is cleared */ 412 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 413 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 414 pthread_cleanup_pop (0); 415 } 416 } 417 418 pthread_mutex_unlock (&(pImpl->m_Lock)); 419 } 420 421 /*****************************************************************************/ 422 /* osl_isThreadRunning */ 423 /*****************************************************************************/ 424 sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread) 425 { 426 sal_Bool active; 427 Thread_Impl* pImpl= (Thread_Impl*)Thread; 428 429 if (!pImpl) 430 return sal_False; 431 432 pthread_mutex_lock (&(pImpl->m_Lock)); 433 active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0); 434 pthread_mutex_unlock (&(pImpl->m_Lock)); 435 436 return (active); 437 } 438 439 /*****************************************************************************/ 440 /* osl_joinWithThread */ 441 /*****************************************************************************/ 442 void SAL_CALL osl_joinWithThread(oslThread Thread) 443 { 444 pthread_t thread; 445 int attached; 446 Thread_Impl* pImpl= (Thread_Impl*)Thread; 447 448 if (!pImpl) 449 return; 450 451 pthread_mutex_lock (&(pImpl->m_Lock)); 452 453 if (pthread_equal (pthread_self(), pImpl->m_hThread)) 454 { 455 /* self join */ 456 pthread_mutex_unlock (&(pImpl->m_Lock)); 457 return; /* EDEADLK */ 458 } 459 460 thread = pImpl->m_hThread; 461 attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0); 462 pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED; 463 464 pthread_mutex_unlock (&(pImpl->m_Lock)); 465 466 if (attached) 467 { 468 /* install cleanup handler to ensure consistent flags and state */ 469 pthread_cleanup_push ( 470 osl_thread_join_cleanup_Impl, (void*)thread); 471 472 /* join */ 473 pthread_join (thread, NULL); 474 475 /* remove cleanup handler */ 476 pthread_cleanup_pop (0); 477 } 478 } 479 480 /*****************************************************************************/ 481 /* osl_terminateThread */ 482 /*****************************************************************************/ 483 void SAL_CALL osl_terminateThread(oslThread Thread) 484 { 485 Thread_Impl* pImpl= (Thread_Impl*)Thread; 486 487 OSL_ASSERT(pImpl); 488 if (!pImpl) 489 return; /* EINVAL */ 490 491 pthread_mutex_lock (&(pImpl->m_Lock)); 492 493 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 494 { 495 /* clear SUSPENDED flag */ 496 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED; 497 pthread_cond_signal (&(pImpl->m_Cond)); 498 } 499 500 pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE; 501 502 pthread_mutex_unlock (&(pImpl->m_Lock)); 503 } 504 505 /*****************************************************************************/ 506 /* osl_scheduleThread */ 507 /*****************************************************************************/ 508 sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread) 509 { 510 int terminate; 511 Thread_Impl* pImpl= (Thread_Impl*)Thread; 512 513 OSL_ASSERT(pImpl); 514 if (!pImpl) 515 return sal_False; /* EINVAL */ 516 517 OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread)); 518 if (!(pthread_equal (pthread_self(), pImpl->m_hThread))) 519 return sal_False; /* EINVAL */ 520 521 pthread_testcancel(); 522 pthread_mutex_lock (&(pImpl->m_Lock)); 523 524 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED) 525 { 526 /* wait until SUSPENDED flag is cleared */ 527 pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock)); 528 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock)); 529 pthread_cleanup_pop (0); 530 } 531 532 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0); 533 534 pthread_mutex_unlock(&(pImpl->m_Lock)); 535 pthread_testcancel(); 536 537 return (terminate == 0); 538 } 539 540 /*****************************************************************************/ 541 /* osl_waitThread */ 542 /*****************************************************************************/ 543 void SAL_CALL osl_waitThread(const TimeValue* pDelay) 544 { 545 if (pDelay) 546 { 547 struct timespec delay; 548 549 SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec); 550 551 SLEEP_TIMESPEC(delay); 552 } 553 } 554 555 /*****************************************************************************/ 556 /* osl_yieldThread */ 557 /* 558 Note that POSIX scheduling _really_ requires threads to call this 559 functions, since a thread only reschedules to other thread, when 560 it blocks (sleep, blocking I/O) OR calls sched_yield(). 561 */ 562 /*****************************************************************************/ 563 void SAL_CALL osl_yieldThread() 564 { 565 sched_yield(); 566 } 567 568 void SAL_CALL osl_setThreadName(char const * name) { 569 #if defined LINUX 570 if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) { 571 OSL_TRACE( 572 "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX, 573 errno); 574 } 575 #else 576 (void) name; 577 #endif 578 } 579 580 /*****************************************************************************/ 581 /* osl_getThreadIdentifier @@@ see TODO @@@ */ 582 /*****************************************************************************/ 583 584 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize) 585 586 typedef struct _HashEntry 587 { 588 pthread_t Handle; 589 sal_uInt16 Ident; 590 struct _HashEntry *Next; 591 } HashEntry; 592 593 static HashEntry* HashTable[31]; 594 static int HashSize = sizeof(HashTable) / sizeof(HashTable[0]); 595 596 static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER; 597 598 static sal_uInt16 LastIdent = 0; 599 600 static sal_uInt16 lookupThreadId (pthread_t hThread) 601 { 602 HashEntry *pEntry; 603 604 pthread_mutex_lock(&HashLock); 605 606 pEntry = HashTable[HASHID(hThread)]; 607 while (pEntry != NULL) 608 { 609 if (pthread_equal(pEntry->Handle, hThread)) 610 { 611 pthread_mutex_unlock(&HashLock); 612 return (pEntry->Ident); 613 } 614 pEntry = pEntry->Next; 615 } 616 617 pthread_mutex_unlock(&HashLock); 618 619 return (0); 620 } 621 622 static sal_uInt16 insertThreadId (pthread_t hThread) 623 { 624 HashEntry *pEntry, *pInsert = NULL; 625 626 pthread_mutex_lock(&HashLock); 627 628 pEntry = HashTable[HASHID(hThread)]; 629 630 while (pEntry != NULL) 631 { 632 if (pthread_equal(pEntry->Handle, hThread)) 633 break; 634 635 pInsert = pEntry; 636 pEntry = pEntry->Next; 637 } 638 639 if (pEntry == NULL) 640 { 641 pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1); 642 643 pEntry->Handle = hThread; 644 645 ++ LastIdent; 646 647 if ( LastIdent == 0 ) 648 LastIdent = 1; 649 650 pEntry->Ident = LastIdent; 651 652 if (pInsert) 653 pInsert->Next = pEntry; 654 else 655 HashTable[HASHID(hThread)] = pEntry; 656 } 657 658 pthread_mutex_unlock(&HashLock); 659 660 return (pEntry->Ident); 661 } 662 663 static void removeThreadId (pthread_t hThread) 664 { 665 HashEntry *pEntry, *pRemove = NULL; 666 667 pthread_mutex_lock(&HashLock); 668 669 pEntry = HashTable[HASHID(hThread)]; 670 while (pEntry != NULL) 671 { 672 if (pthread_equal(pEntry->Handle, hThread)) 673 break; 674 675 pRemove = pEntry; 676 pEntry = pEntry->Next; 677 } 678 679 if (pEntry != NULL) 680 { 681 if (pRemove) 682 pRemove->Next = pEntry->Next; 683 else 684 HashTable[HASHID(hThread)] = pEntry->Next; 685 686 free(pEntry); 687 } 688 689 pthread_mutex_unlock(&HashLock); 690 } 691 692 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread) 693 { 694 Thread_Impl* pImpl= (Thread_Impl*)Thread; 695 sal_uInt16 Ident; 696 697 if (pImpl) 698 Ident = pImpl->m_Ident; 699 else 700 { 701 /* current thread */ 702 pthread_t current = pthread_self(); 703 704 Ident = lookupThreadId (current); 705 if (Ident == 0) 706 /* @@@ see TODO: alien pthread_self() @@@ */ 707 Ident = insertThreadId (current); 708 } 709 710 return ((oslThreadIdentifier)(Ident)); 711 } 712 713 /***************************************************************************** 714 @@@ see TODO @@@ 715 osl_thread_priority_init_Impl 716 717 set the base-priority of the main-thread to 718 oslThreadPriorityNormal (64) since 0 (lowest) is 719 the system default. This behaviour collides with 720 our enum-priority definition (highest..normal..lowest). 721 A normal user will expect the main-thread of an app. 722 to have the "normal" priority. 723 724 *****************************************************************************/ 725 static void osl_thread_priority_init_Impl (void) 726 { 727 #ifndef NO_PTHREAD_PRIORITY 728 struct sched_param param; 729 int policy=0; 730 int nRet=0; 731 732 /* @@@ see TODO: calling thread may not be main thread @@@ */ 733 734 if ((nRet = pthread_getschedparam(pthread_self(), &policy, ¶m)) != 0) 735 { 736 OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet)); 737 return; 738 } 739 740 #if defined (SOLARIS) 741 if ( policy >= _SCHED_NEXT) 742 { 743 /* mfe: pthread_getschedparam on Solaris has a possible Bug */ 744 /* one gets 959917873 as the policy */ 745 /* so set the policy to a default one */ 746 policy=SCHED_OTHER; 747 } 748 #endif /* SOLARIS */ 749 750 if ((nRet = sched_get_priority_min(policy) ) != -1) 751 { 752 OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet); 753 g_thread.m_priority.m_Lowest=nRet; 754 } 755 #if OSL_DEBUG_LEVEL > 1 756 else 757 { 758 fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno)); 759 } 760 #endif /* OSL_DEBUG_LEVEL */ 761 762 if ((nRet = sched_get_priority_max(policy) ) != -1) 763 { 764 OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet); 765 g_thread.m_priority.m_Highest=nRet; 766 } 767 #if OSL_DEBUG_LEVEL > 1 768 else 769 { 770 fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno)); 771 } 772 #endif /* OSL_DEBUG_LEVEL */ 773 774 g_thread.m_priority.m_Normal = 775 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2; 776 g_thread.m_priority.m_Below_Normal = 777 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2; 778 g_thread.m_priority.m_Above_Normal = 779 (g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2; 780 781 /* @@@ set prio of calling (not main) thread (?) @@@ */ 782 783 param.sched_priority= g_thread.m_priority.m_Normal; 784 785 if ((nRet = pthread_setschedparam(pthread_self(), policy, ¶m)) != 0) 786 { 787 OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet)); 788 OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority); 789 } 790 791 #endif /* NO_PTHREAD_PRIORITY */ 792 } 793 794 /*****************************************************************************/ 795 /* osl_setThreadPriority */ 796 /* 797 Impl-Notes: contrary to solaris-docu, which claims 798 valid priority-levels from 0 .. INT_MAX, only the 799 range 0..127 is accepted. (0 lowest, 127 highest) 800 */ 801 /*****************************************************************************/ 802 void SAL_CALL osl_setThreadPriority ( 803 oslThread Thread, 804 oslThreadPriority Priority) 805 { 806 #ifndef NO_PTHREAD_PRIORITY 807 808 struct sched_param Param; 809 int policy; 810 int nRet; 811 812 #endif /* NO_PTHREAD_PRIORITY */ 813 814 Thread_Impl* pImpl= (Thread_Impl*)Thread; 815 816 OSL_ASSERT(pImpl); 817 if (!pImpl) 818 return; /* EINVAL */ 819 820 #ifdef NO_PTHREAD_PRIORITY 821 (void) Priority; /* unused */ 822 #else /* NO_PTHREAD_PRIORITY */ 823 824 if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0) 825 return; /* ESRCH */ 826 827 #if defined (SOLARIS) 828 if ( policy >= _SCHED_NEXT) 829 { 830 /* mfe: pthread_getschedparam on Solaris has a possible Bug */ 831 /* one gets 959917873 as the policy */ 832 /* so set the policy to a default one */ 833 policy=SCHED_OTHER; 834 } 835 #endif /* SOLARIS */ 836 837 pthread_once (&(g_thread.m_once), osl_thread_init_Impl); 838 839 switch(Priority) 840 { 841 case osl_Thread_PriorityHighest: 842 Param.sched_priority= g_thread.m_priority.m_Highest; 843 break; 844 845 case osl_Thread_PriorityAboveNormal: 846 Param.sched_priority= g_thread.m_priority.m_Above_Normal; 847 break; 848 849 case osl_Thread_PriorityNormal: 850 Param.sched_priority= g_thread.m_priority.m_Normal; 851 break; 852 853 case osl_Thread_PriorityBelowNormal: 854 Param.sched_priority= g_thread.m_priority.m_Below_Normal; 855 break; 856 857 case osl_Thread_PriorityLowest: 858 Param.sched_priority= g_thread.m_priority.m_Lowest; 859 break; 860 861 case osl_Thread_PriorityUnknown: 862 OSL_ASSERT(sal_False); /* only fools try this...*/ 863 864 /* let release-version behave friendly */ 865 return; 866 867 default: 868 /* enum expanded, but forgotten here...*/ 869 OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n"); 870 871 /* let release-version behave friendly */ 872 return; 873 } 874 875 if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0) 876 { 877 OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet)); 878 } 879 880 #endif /* NO_PTHREAD_PRIORITY */ 881 } 882 883 /*****************************************************************************/ 884 /* osl_getThreadPriority */ 885 /*****************************************************************************/ 886 oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread) 887 { 888 #ifndef NO_PTHREAD_PRIORITY 889 890 struct sched_param Param; 891 int Policy; 892 893 #endif /* NO_PTHREAD_PRIORITY */ 894 895 oslThreadPriority Priority = osl_Thread_PriorityNormal; 896 Thread_Impl* pImpl= (Thread_Impl*)Thread; 897 898 OSL_ASSERT(pImpl); 899 if (!pImpl) 900 return osl_Thread_PriorityUnknown; /* EINVAL */ 901 902 #ifndef NO_PTHREAD_PRIORITY 903 904 if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0) 905 return osl_Thread_PriorityUnknown; /* ESRCH */ 906 907 pthread_once (&(g_thread.m_once), osl_thread_init_Impl); 908 909 /* map pthread priority to enum */ 910 if (Param.sched_priority==g_thread.m_priority.m_Highest) 911 { 912 /* 127 - highest */ 913 Priority= osl_Thread_PriorityHighest; 914 } 915 else if (Param.sched_priority > g_thread.m_priority.m_Normal) 916 { 917 /* 65..126 - above normal */ 918 Priority= osl_Thread_PriorityAboveNormal; 919 } 920 else if (Param.sched_priority == g_thread.m_priority.m_Normal) 921 { 922 /* normal */ 923 Priority= osl_Thread_PriorityNormal; 924 } 925 else if (Param.sched_priority > g_thread.m_priority.m_Lowest) 926 { 927 /* 63..1 -below normal */ 928 Priority= osl_Thread_PriorityBelowNormal; 929 } 930 else if (Param.sched_priority == g_thread.m_priority.m_Lowest) 931 { 932 /* 0 - lowest */ 933 Priority= osl_Thread_PriorityLowest; 934 } 935 else 936 { 937 /* unknown */ 938 Priority= osl_Thread_PriorityUnknown; 939 } 940 941 #endif /* NO_PTHREAD_PRIORITY */ 942 943 return Priority; 944 } 945 946 /*****************************************************************************/ 947 /* osl_createThreadKey */ 948 /*****************************************************************************/ 949 oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback ) 950 { 951 pthread_key_t key; 952 953 if (pthread_key_create(&key, pCallback) != 0) 954 key = 0; 955 956 return ((oslThreadKey)key); 957 } 958 959 /*****************************************************************************/ 960 /* osl_destroyThreadKey */ 961 /*****************************************************************************/ 962 void SAL_CALL osl_destroyThreadKey(oslThreadKey Key) 963 { 964 pthread_key_delete((pthread_key_t)Key); 965 } 966 967 /*****************************************************************************/ 968 /* osl_getThreadKeyData */ 969 /*****************************************************************************/ 970 void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key) 971 { 972 return (pthread_getspecific((pthread_key_t)Key)); 973 } 974 975 /*****************************************************************************/ 976 /* osl_setThreadKeyData */ 977 /*****************************************************************************/ 978 sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData) 979 { 980 return (pthread_setspecific((pthread_key_t)Key, pData) == 0); 981 } 982 983 /*****************************************************************************/ 984 /* Thread Local Text Encoding */ 985 /*****************************************************************************/ 986 static void osl_thread_textencoding_init_Impl (void) 987 { 988 rtl_TextEncoding defaultEncoding; 989 const char * pszEncoding; 990 991 /* create thread specific data key */ 992 pthread_key_create (&(g_thread.m_textencoding.m_key), NULL); 993 994 /* determine default text encoding */ 995 pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING"); 996 if (pszEncoding) 997 defaultEncoding = atoi(pszEncoding); 998 else 999 defaultEncoding = osl_getTextEncodingFromLocale(NULL); 1000 1001 OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW); 1002 1003 /* 1004 Tools string functions call abort() on an unknown encoding so ASCII 1005 is a meaningful fallback regardless whether the assertion makes sense. 1006 */ 1007 1008 if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding ) 1009 defaultEncoding = RTL_TEXTENCODING_ASCII_US; 1010 1011 g_thread.m_textencoding.m_default = defaultEncoding; 1012 } 1013 1014 /*****************************************************************************/ 1015 /* osl_getThreadTextEncoding */ 1016 /*****************************************************************************/ 1017 rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding() 1018 { 1019 rtl_TextEncoding threadEncoding; 1020 1021 pthread_once (&(g_thread.m_once), osl_thread_init_Impl); 1022 1023 /* check for thread specific encoding, use default if not set */ 1024 threadEncoding = SAL_INT_CAST( 1025 rtl_TextEncoding, 1026 (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key)); 1027 if (0 == threadEncoding) 1028 threadEncoding = g_thread.m_textencoding.m_default; 1029 1030 return threadEncoding; 1031 } 1032 1033 /*****************************************************************************/ 1034 /* osl_setThreadTextEncoding */ 1035 /*****************************************************************************/ 1036 rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding) 1037 { 1038 rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding(); 1039 1040 /* save encoding in thread local storage */ 1041 pthread_setspecific ( 1042 g_thread.m_textencoding.m_key, 1043 (void*) SAL_INT_CAST(sal_uIntPtr, Encoding)); 1044 1045 return oldThreadEncoding; 1046 } 1047