merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / thread.c
blob18c4b033daf71450779552105103085ef29ef522
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
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
37 #if defined LINUX
38 #include <sys/prctl.h>
39 #endif
41 /****************************************************************************
42 * @@@ TODO @@@
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.
60 ****************************************************************************/
62 /*****************************************************************************/
63 /* Internal data structures and functions */
64 /*****************************************************************************/
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
73 typedef struct osl_thread_impl_st
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;
84 struct osl_thread_priority_st
86 int m_Highest;
87 int m_Above_Normal;
88 int m_Normal;
89 int m_Below_Normal;
90 int m_Lowest;
93 #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
94 static void osl_thread_priority_init_Impl (void);
96 struct osl_thread_textencoding_st
98 pthread_key_t m_key; /* key to store thread local text encoding */
99 rtl_TextEncoding m_default; /* the default text encoding */
102 #define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW }
103 static void osl_thread_textencoding_init_Impl (void);
105 struct osl_thread_global_st
107 pthread_once_t m_once;
108 struct osl_thread_priority_st m_priority;
109 struct osl_thread_textencoding_st m_textencoding;
112 static struct osl_thread_global_st g_thread =
114 PTHREAD_ONCE_INIT,
115 OSL_THREAD_PRIORITY_INITIALIZER,
116 OSL_THREAD_TEXTENCODING_INITIALIZER
119 static void osl_thread_init_Impl (void);
121 static Thread_Impl* osl_thread_construct_Impl (void);
122 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl);
124 static void* osl_thread_start_Impl (void * pData);
125 static void osl_thread_cleanup_Impl (void * pData);
127 static oslThread osl_thread_create_Impl (
128 oslWorkerFunction pWorker, void * pThreadData, short nFlags);
130 static void osl_thread_join_cleanup_Impl (void * opaque);
131 static void osl_thread_wait_cleanup_Impl (void * opaque);
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);
138 /*****************************************************************************/
139 /* osl_thread_init_Impl */
140 /*****************************************************************************/
141 static void osl_thread_init_Impl (void)
143 osl_thread_priority_init_Impl();
144 osl_thread_textencoding_init_Impl();
147 /*****************************************************************************/
148 /* osl_thread_join_cleanup_Impl */
149 /*****************************************************************************/
150 static void osl_thread_join_cleanup_Impl (void * opaque)
152 pthread_t hThread = (pthread_t)(opaque);
153 pthread_detach (hThread);
156 /*****************************************************************************/
157 /* osl_thread_wait_cleanup_Impl */
158 /*****************************************************************************/
159 static void osl_thread_wait_cleanup_Impl (void * opaque)
161 pthread_mutex_t * pMutex = (pthread_mutex_t*)(opaque);
162 pthread_mutex_unlock (pMutex);
165 /*****************************************************************************/
166 /* osl_thread_construct_Impl */
167 /*****************************************************************************/
168 Thread_Impl* osl_thread_construct_Impl (void)
170 Thread_Impl* pImpl = malloc (sizeof(Thread_Impl));
171 if (pImpl)
173 memset (pImpl, 0, sizeof(Thread_Impl));
175 pthread_mutex_init (&(pImpl->m_Lock), PTHREAD_MUTEXATTR_DEFAULT);
176 pthread_cond_init (&(pImpl->m_Cond), PTHREAD_CONDATTR_DEFAULT);
178 return (pImpl);
181 /*****************************************************************************/
182 /* osl_thread_destruct_Impl */
183 /*****************************************************************************/
184 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl)
186 OSL_ASSERT(ppImpl);
187 if (*ppImpl)
189 pthread_cond_destroy (&((*ppImpl)->m_Cond));
190 pthread_mutex_destroy (&((*ppImpl)->m_Lock));
192 free (*ppImpl);
193 (*ppImpl) = 0;
197 /*****************************************************************************/
198 /* osl_thread_cleanup_Impl */
199 /*****************************************************************************/
200 static void osl_thread_cleanup_Impl (void* pData)
202 pthread_t thread;
203 int attached;
204 int destroyed;
205 Thread_Impl* pImpl= (Thread_Impl*)pData;
207 pthread_mutex_lock (&(pImpl->m_Lock));
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);
214 pthread_mutex_unlock (&(pImpl->m_Lock));
216 /* release oslThreadIdentifier @@@ see TODO @@@ */
217 removeThreadId (thread);
219 if (attached)
221 pthread_detach (thread);
224 if (destroyed)
226 osl_thread_destruct_Impl (&pImpl);
230 /*****************************************************************************/
231 /* osl_thread_start_Impl */
232 /*****************************************************************************/
233 static void* osl_thread_start_Impl (void* pData)
235 int terminate;
236 Thread_Impl* pImpl= (Thread_Impl*)pData;
238 OSL_ASSERT(pImpl);
240 pthread_mutex_lock (&(pImpl->m_Lock));
242 /* install cleanup handler */
243 pthread_cleanup_push (osl_thread_cleanup_Impl, pData);
245 /* request oslThreadIdentifier @@@ see TODO @@@ */
246 pImpl->m_Ident = insertThreadId (pImpl->m_hThread);
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));
253 /* Check if thread is started in SUSPENDED state */
254 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
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);
262 /* check for SUSPENDED to TERMINATE state change */
263 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
265 pthread_mutex_unlock (&(pImpl->m_Lock));
267 if (!terminate)
269 /* call worker function */
270 pImpl->m_WorkerFunction(pImpl->m_pData);
273 /* call cleanup handler and leave */
274 pthread_cleanup_pop (1);
275 return (0);
278 /*****************************************************************************/
279 /* osl_thread_create_Impl */
280 /*****************************************************************************/
281 static oslThread osl_thread_create_Impl (
282 oslWorkerFunction pWorker,
283 void* pThreadData,
284 short nFlags)
286 Thread_Impl* pImpl;
287 int nRet=0;
289 pImpl = osl_thread_construct_Impl();
290 if (!pImpl)
291 return (0); /* ENOMEM */
293 pImpl->m_WorkerFunction = pWorker;
294 pImpl->m_pData = pThreadData;
295 pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP;
297 pthread_mutex_lock (&(pImpl->m_Lock));
299 if ((nRet = pthread_create (
300 &(pImpl->m_hThread),
301 PTHREAD_ATTR_DEFAULT,
302 osl_thread_start_Impl,
303 (void*)(pImpl))) != 0)
305 OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n",
306 nRet, strerror(nRet));
308 pthread_mutex_unlock (&(pImpl->m_Lock));
309 osl_thread_destruct_Impl (&pImpl);
311 return (0);
314 /* wait for change from STARTUP to ACTIVE state */
315 while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP)
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);
323 pthread_mutex_unlock (&(pImpl->m_Lock));
325 return ((oslThread)(pImpl));
328 /*****************************************************************************/
329 /* osl_createThread */
330 /*****************************************************************************/
331 oslThread osl_createThread (
332 oslWorkerFunction pWorker,
333 void * pThreadData)
335 return osl_thread_create_Impl (
336 pWorker,
337 pThreadData,
338 THREADIMPL_FLAGS_ATTACHED);
341 /*****************************************************************************/
342 /* osl_createSuspendedThread */
343 /*****************************************************************************/
344 oslThread osl_createSuspendedThread (
345 oslWorkerFunction pWorker,
346 void * pThreadData)
348 return osl_thread_create_Impl (
349 pWorker,
350 pThreadData,
351 THREADIMPL_FLAGS_ATTACHED |
352 THREADIMPL_FLAGS_SUSPENDED );
355 /*****************************************************************************/
356 /* osl_destroyThread */
357 /*****************************************************************************/
358 void SAL_CALL osl_destroyThread(oslThread Thread)
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);
373 /*****************************************************************************/
374 /* osl_resumeThread */
375 /*****************************************************************************/
376 void SAL_CALL osl_resumeThread(oslThread Thread)
378 Thread_Impl* pImpl= (Thread_Impl*)Thread;
380 OSL_ASSERT(pImpl);
381 if (!pImpl)
382 return; /* EINVAL */
384 pthread_mutex_lock (&(pImpl->m_Lock));
386 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
388 /* clear SUSPENDED flag */
389 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
390 pthread_cond_signal (&(pImpl->m_Cond));
393 pthread_mutex_unlock (&(pImpl->m_Lock));
396 /*****************************************************************************/
397 /* osl_suspendThread */
398 /*****************************************************************************/
399 void SAL_CALL osl_suspendThread(oslThread Thread)
401 Thread_Impl* pImpl= (Thread_Impl*)Thread;
403 OSL_ASSERT(pImpl);
404 if (!pImpl)
405 return; /* EINVAL */
407 pthread_mutex_lock (&(pImpl->m_Lock));
409 pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
411 if (pthread_equal (pthread_self(), pImpl->m_hThread))
413 /* self suspend */
414 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
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);
423 pthread_mutex_unlock (&(pImpl->m_Lock));
426 /*****************************************************************************/
427 /* osl_isThreadRunning */
428 /*****************************************************************************/
429 sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
431 sal_Bool active;
432 Thread_Impl* pImpl= (Thread_Impl*)Thread;
434 if (!pImpl)
435 return sal_False;
437 pthread_mutex_lock (&(pImpl->m_Lock));
438 active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
439 pthread_mutex_unlock (&(pImpl->m_Lock));
441 return (active);
444 /*****************************************************************************/
445 /* osl_joinWithThread */
446 /*****************************************************************************/
447 void SAL_CALL osl_joinWithThread(oslThread Thread)
449 pthread_t thread;
450 int attached;
451 Thread_Impl* pImpl= (Thread_Impl*)Thread;
453 if (!pImpl)
454 return;
456 pthread_mutex_lock (&(pImpl->m_Lock));
458 if (pthread_equal (pthread_self(), pImpl->m_hThread))
460 /* self join */
461 pthread_mutex_unlock (&(pImpl->m_Lock));
462 return; /* EDEADLK */
465 thread = pImpl->m_hThread;
466 attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0);
467 pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED;
469 pthread_mutex_unlock (&(pImpl->m_Lock));
471 if (attached)
473 /* install cleanup handler to ensure consistent flags and state */
474 pthread_cleanup_push (
475 osl_thread_join_cleanup_Impl, (void*)thread);
477 /* join */
478 pthread_join (thread, NULL);
480 /* remove cleanup handler */
481 pthread_cleanup_pop (0);
485 /*****************************************************************************/
486 /* osl_terminateThread */
487 /*****************************************************************************/
488 void SAL_CALL osl_terminateThread(oslThread Thread)
490 Thread_Impl* pImpl= (Thread_Impl*)Thread;
492 OSL_ASSERT(pImpl);
493 if (!pImpl)
494 return; /* EINVAL */
496 pthread_mutex_lock (&(pImpl->m_Lock));
498 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
500 /* clear SUSPENDED flag */
501 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
502 pthread_cond_signal (&(pImpl->m_Cond));
505 pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
507 pthread_mutex_unlock (&(pImpl->m_Lock));
510 /*****************************************************************************/
511 /* osl_scheduleThread */
512 /*****************************************************************************/
513 sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
515 int terminate;
516 Thread_Impl* pImpl= (Thread_Impl*)Thread;
518 OSL_ASSERT(pImpl);
519 if (!pImpl)
520 return sal_False; /* EINVAL */
522 OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread));
523 if (!(pthread_equal (pthread_self(), pImpl->m_hThread)))
524 return sal_False; /* EINVAL */
526 pthread_testcancel();
527 pthread_mutex_lock (&(pImpl->m_Lock));
529 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
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);
537 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
539 pthread_mutex_unlock(&(pImpl->m_Lock));
540 pthread_testcancel();
542 return (terminate == 0);
545 /*****************************************************************************/
546 /* osl_waitThread */
547 /*****************************************************************************/
548 void SAL_CALL osl_waitThread(const TimeValue* pDelay)
550 if (pDelay)
552 struct timespec delay;
554 SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec);
556 SLEEP_TIMESPEC(delay);
560 /*****************************************************************************/
561 /* osl_yieldThread */
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().
567 /*****************************************************************************/
568 void SAL_CALL osl_yieldThread()
570 sched_yield();
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);
580 #else
581 (void) name;
582 #endif
585 /*****************************************************************************/
586 /* osl_getThreadIdentifier @@@ see TODO @@@ */
587 /*****************************************************************************/
589 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
591 typedef struct _HashEntry
593 pthread_t Handle;
594 sal_uInt16 Ident;
595 struct _HashEntry *Next;
596 } HashEntry;
598 static HashEntry* HashTable[31];
599 static int HashSize = sizeof(HashTable) / sizeof(HashTable[0]);
601 static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER;
603 static sal_uInt16 LastIdent = 0;
605 static sal_uInt16 lookupThreadId (pthread_t hThread)
607 HashEntry *pEntry;
609 pthread_mutex_lock(&HashLock);
611 pEntry = HashTable[HASHID(hThread)];
612 while (pEntry != NULL)
614 if (pthread_equal(pEntry->Handle, hThread))
616 pthread_mutex_unlock(&HashLock);
617 return (pEntry->Ident);
619 pEntry = pEntry->Next;
622 pthread_mutex_unlock(&HashLock);
624 return (0);
627 static sal_uInt16 insertThreadId (pthread_t hThread)
629 HashEntry *pEntry, *pInsert = NULL;
631 pthread_mutex_lock(&HashLock);
633 pEntry = HashTable[HASHID(hThread)];
635 while (pEntry != NULL)
637 if (pthread_equal(pEntry->Handle, hThread))
638 break;
640 pInsert = pEntry;
641 pEntry = pEntry->Next;
644 if (pEntry == NULL)
646 pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
648 pEntry->Handle = hThread;
650 ++ LastIdent;
652 if ( LastIdent == 0 )
653 LastIdent = 1;
655 pEntry->Ident = LastIdent;
657 if (pInsert)
658 pInsert->Next = pEntry;
659 else
660 HashTable[HASHID(hThread)] = pEntry;
663 pthread_mutex_unlock(&HashLock);
665 return (pEntry->Ident);
668 static void removeThreadId (pthread_t hThread)
670 HashEntry *pEntry, *pRemove = NULL;
672 pthread_mutex_lock(&HashLock);
674 pEntry = HashTable[HASHID(hThread)];
675 while (pEntry != NULL)
677 if (pthread_equal(pEntry->Handle, hThread))
678 break;
680 pRemove = pEntry;
681 pEntry = pEntry->Next;
684 if (pEntry != NULL)
686 if (pRemove)
687 pRemove->Next = pEntry->Next;
688 else
689 HashTable[HASHID(hThread)] = pEntry->Next;
691 free(pEntry);
694 pthread_mutex_unlock(&HashLock);
697 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
699 Thread_Impl* pImpl= (Thread_Impl*)Thread;
700 sal_uInt16 Ident;
702 if (pImpl)
703 Ident = pImpl->m_Ident;
704 else
706 /* current thread */
707 pthread_t current = pthread_self();
709 Ident = lookupThreadId (current);
710 if (Ident == 0)
711 /* @@@ see TODO: alien pthread_self() @@@ */
712 Ident = insertThreadId (current);
715 return ((oslThreadIdentifier)(Ident));
718 /*****************************************************************************
719 @@@ see TODO @@@
720 osl_thread_priority_init_Impl
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.
729 *****************************************************************************/
730 static void osl_thread_priority_init_Impl (void)
732 #ifndef NO_PTHREAD_PRIORITY
733 struct sched_param param;
734 int policy=0;
735 int nRet=0;
737 /* @@@ see TODO: calling thread may not be main thread @@@ */
739 if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
741 OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet));
742 return;
745 #if defined (SOLARIS)
746 if ( policy >= _SCHED_NEXT)
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;
753 #endif /* SOLARIS */
755 if ((nRet = sched_get_priority_min(policy) ) != -1)
757 OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet);
758 g_thread.m_priority.m_Lowest=nRet;
760 #if OSL_DEBUG_LEVEL > 1
761 else
763 fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
765 #endif /* OSL_DEBUG_LEVEL */
767 if ((nRet = sched_get_priority_max(policy) ) != -1)
769 OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet);
770 g_thread.m_priority.m_Highest=nRet;
772 #if OSL_DEBUG_LEVEL > 1
773 else
775 fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
777 #endif /* OSL_DEBUG_LEVEL */
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;
786 /* @@@ set prio of calling (not main) thread (?) @@@ */
788 param.sched_priority= g_thread.m_priority.m_Normal;
790 if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
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);
796 #endif /* NO_PTHREAD_PRIORITY */
799 /*****************************************************************************/
800 /* osl_setThreadPriority */
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)
806 /*****************************************************************************/
807 void SAL_CALL osl_setThreadPriority (
808 oslThread Thread,
809 oslThreadPriority Priority)
811 #ifndef NO_PTHREAD_PRIORITY
813 struct sched_param Param;
814 int policy;
815 int nRet;
817 #endif /* NO_PTHREAD_PRIORITY */
819 Thread_Impl* pImpl= (Thread_Impl*)Thread;
821 OSL_ASSERT(pImpl);
822 if (!pImpl)
823 return; /* EINVAL */
825 #ifdef NO_PTHREAD_PRIORITY
826 (void) Priority; /* unused */
827 #else /* NO_PTHREAD_PRIORITY */
829 if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
830 return; /* ESRCH */
832 #if defined (SOLARIS)
833 if ( policy >= _SCHED_NEXT)
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;
840 #endif /* SOLARIS */
842 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
844 switch(Priority)
846 case osl_Thread_PriorityHighest:
847 Param.sched_priority= g_thread.m_priority.m_Highest;
848 break;
850 case osl_Thread_PriorityAboveNormal:
851 Param.sched_priority= g_thread.m_priority.m_Above_Normal;
852 break;
854 case osl_Thread_PriorityNormal:
855 Param.sched_priority= g_thread.m_priority.m_Normal;
856 break;
858 case osl_Thread_PriorityBelowNormal:
859 Param.sched_priority= g_thread.m_priority.m_Below_Normal;
860 break;
862 case osl_Thread_PriorityLowest:
863 Param.sched_priority= g_thread.m_priority.m_Lowest;
864 break;
866 case osl_Thread_PriorityUnknown:
867 OSL_ASSERT(sal_False); /* only fools try this...*/
869 /* let release-version behave friendly */
870 return;
872 default:
873 /* enum expanded, but forgotten here...*/
874 OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
876 /* let release-version behave friendly */
877 return;
880 if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
882 OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet));
885 #endif /* NO_PTHREAD_PRIORITY */
888 /*****************************************************************************/
889 /* osl_getThreadPriority */
890 /*****************************************************************************/
891 oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
893 #ifndef NO_PTHREAD_PRIORITY
895 struct sched_param Param;
896 int Policy;
898 #endif /* NO_PTHREAD_PRIORITY */
900 oslThreadPriority Priority = osl_Thread_PriorityNormal;
901 Thread_Impl* pImpl= (Thread_Impl*)Thread;
903 OSL_ASSERT(pImpl);
904 if (!pImpl)
905 return osl_Thread_PriorityUnknown; /* EINVAL */
907 #ifndef NO_PTHREAD_PRIORITY
909 if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0)
910 return osl_Thread_PriorityUnknown; /* ESRCH */
912 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
914 /* map pthread priority to enum */
915 if (Param.sched_priority==g_thread.m_priority.m_Highest)
917 /* 127 - highest */
918 Priority= osl_Thread_PriorityHighest;
920 else if (Param.sched_priority > g_thread.m_priority.m_Normal)
922 /* 65..126 - above normal */
923 Priority= osl_Thread_PriorityAboveNormal;
925 else if (Param.sched_priority == g_thread.m_priority.m_Normal)
927 /* normal */
928 Priority= osl_Thread_PriorityNormal;
930 else if (Param.sched_priority > g_thread.m_priority.m_Lowest)
932 /* 63..1 -below normal */
933 Priority= osl_Thread_PriorityBelowNormal;
935 else if (Param.sched_priority == g_thread.m_priority.m_Lowest)
937 /* 0 - lowest */
938 Priority= osl_Thread_PriorityLowest;
940 else
942 /* unknown */
943 Priority= osl_Thread_PriorityUnknown;
946 #endif /* NO_PTHREAD_PRIORITY */
948 return Priority;
951 /*****************************************************************************/
952 /* osl_createThreadKey */
953 /*****************************************************************************/
954 oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
956 pthread_key_t key;
958 if (pthread_key_create(&key, pCallback) != 0)
959 key = 0;
961 return ((oslThreadKey)key);
964 /*****************************************************************************/
965 /* osl_destroyThreadKey */
966 /*****************************************************************************/
967 void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
969 pthread_key_delete((pthread_key_t)Key);
972 /*****************************************************************************/
973 /* osl_getThreadKeyData */
974 /*****************************************************************************/
975 void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
977 return (pthread_getspecific((pthread_key_t)Key));
980 /*****************************************************************************/
981 /* osl_setThreadKeyData */
982 /*****************************************************************************/
983 sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
985 return (pthread_setspecific((pthread_key_t)Key, pData) == 0);
988 /*****************************************************************************/
989 /* Thread Local Text Encoding */
990 /*****************************************************************************/
991 static void osl_thread_textencoding_init_Impl (void)
993 rtl_TextEncoding defaultEncoding;
994 const char * pszEncoding;
996 /* create thread specific data key */
997 pthread_key_create (&(g_thread.m_textencoding.m_key), NULL);
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);
1006 OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
1009 Tools string functions call abort() on an unknown encoding so ASCII
1010 is a meaningfull fallback regardless wether the assertion makes sense.
1013 if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding )
1014 defaultEncoding = RTL_TEXTENCODING_ASCII_US;
1016 g_thread.m_textencoding.m_default = defaultEncoding;
1019 /*****************************************************************************/
1020 /* osl_getThreadTextEncoding */
1021 /*****************************************************************************/
1022 rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding()
1024 rtl_TextEncoding threadEncoding;
1026 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
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;
1035 return threadEncoding;
1038 /*****************************************************************************/
1039 /* osl_setThreadTextEncoding */
1040 /*****************************************************************************/
1041 rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
1043 rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
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));
1050 return oldThreadEncoding;