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