Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / sal / osl / unx / thread.c
blob0140936999e064247a91526beffafe36374dabdc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "system.h"
21 #include <string.h>
22 #if defined(OPENBSD)
23 #include <sched.h>
24 #endif
25 #include <osl/diagnose.h>
26 #include <osl/thread.h>
27 #include <osl/nlsupport.h>
28 #include <rtl/textenc.h>
29 #include <rtl/alloc.h>
30 #include <sal/macros.h>
31 #ifdef ANDROID
32 #include <jni.h>
33 #include <android/log.h>
34 #include <osl/detail/android-bootstrap.h>
35 #endif
37 #if defined LINUX && ! defined __FreeBSD_kernel__
38 #include <sys/prctl.h>
39 #ifndef PR_SET_NAME
40 #define PR_SET_NAME 15
41 #endif
42 #endif
44 /****************************************************************************
45 * @@@ TODO @@@
47 * (1) 'osl_thread_priority_init_Impl()'
48 * - insane assumption that initializing caller is main thread
49 * - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?)
50 * - POSIX doesn't require defined prio's for SCHED_OTHER (!)
51 * - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?)
52 * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()'
53 * - cannot reliably be applied to 'alien' threads;
54 * - memory leak for 'alien' thread 'HashEntry's;
55 * - use 'PTHREAD_VALUE(pthread_t)' as identifier instead (?)
56 * - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar
57 * (3) 'oslSigAlarmHandler()' (#71232#)
58 * - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates
59 * the process. So we initialize our signal handling module and do
60 * register a SIGALRM Handler which catches and ignores it]
61 * - should this still happen, 'signal.c' needs to be fixed instead.
63 ****************************************************************************/
65 /*****************************************************************************/
66 /* Internal data structures and functions */
67 /*****************************************************************************/
69 #define THREADIMPL_FLAGS_TERMINATE 0x00001
70 #define THREADIMPL_FLAGS_STARTUP 0x00002
71 #define THREADIMPL_FLAGS_SUSPENDED 0x00004
72 #define THREADIMPL_FLAGS_ACTIVE 0x00008
73 #define THREADIMPL_FLAGS_ATTACHED 0x00010
74 #define THREADIMPL_FLAGS_DESTROYED 0x00020
76 typedef struct osl_thread_impl_st
78 pthread_t m_hThread;
79 sal_uInt16 m_Ident; /* @@@ see TODO @@@ */
80 short m_Flags;
81 oslWorkerFunction m_WorkerFunction;
82 void* m_pData;
83 pthread_mutex_t m_Lock;
84 pthread_cond_t m_Cond;
85 } Thread_Impl;
87 struct osl_thread_priority_st
89 int m_Highest;
90 int m_Above_Normal;
91 int m_Normal;
92 int m_Below_Normal;
93 int m_Lowest;
96 #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
97 static void osl_thread_priority_init_Impl (void);
99 struct osl_thread_textencoding_st
101 pthread_key_t m_key; /* key to store thread local text encoding */
102 rtl_TextEncoding m_default; /* the default text encoding */
105 #define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW }
106 static void osl_thread_textencoding_init_Impl (void);
108 struct osl_thread_global_st
110 pthread_once_t m_once;
111 struct osl_thread_priority_st m_priority;
112 struct osl_thread_textencoding_st m_textencoding;
115 static struct osl_thread_global_st g_thread =
117 PTHREAD_ONCE_INIT,
118 OSL_THREAD_PRIORITY_INITIALIZER,
119 OSL_THREAD_TEXTENCODING_INITIALIZER
122 static void osl_thread_init_Impl (void);
124 static Thread_Impl* osl_thread_construct_Impl (void);
125 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl);
127 static void* osl_thread_start_Impl (void * pData);
128 static void osl_thread_cleanup_Impl (Thread_Impl * pImpl);
130 static oslThread osl_thread_create_Impl (
131 oslWorkerFunction pWorker, void * pThreadData, short nFlags);
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 static void osl_thread_init_Impl (void)
140 osl_thread_priority_init_Impl();
141 osl_thread_textencoding_init_Impl();
144 Thread_Impl* osl_thread_construct_Impl (void)
146 Thread_Impl* pImpl = malloc (sizeof(Thread_Impl));
147 if (pImpl)
149 memset (pImpl, 0, sizeof(Thread_Impl));
151 pthread_mutex_init (&(pImpl->m_Lock), PTHREAD_MUTEXATTR_DEFAULT);
152 pthread_cond_init (&(pImpl->m_Cond), PTHREAD_CONDATTR_DEFAULT);
154 return (pImpl);
157 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl)
159 OSL_ASSERT(ppImpl);
160 if (*ppImpl)
162 pthread_cond_destroy (&((*ppImpl)->m_Cond));
163 pthread_mutex_destroy (&((*ppImpl)->m_Lock));
165 free (*ppImpl);
166 (*ppImpl) = 0;
170 static void osl_thread_cleanup_Impl (Thread_Impl * pImpl)
172 pthread_t thread;
173 int attached;
174 int destroyed;
176 pthread_mutex_lock (&(pImpl->m_Lock));
178 thread = pImpl->m_hThread;
179 attached = (pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) != 0;
180 destroyed = (pImpl->m_Flags & THREADIMPL_FLAGS_DESTROYED) != 0;
181 pImpl->m_Flags &= ~(THREADIMPL_FLAGS_ACTIVE | THREADIMPL_FLAGS_ATTACHED);
183 pthread_mutex_unlock (&(pImpl->m_Lock));
185 /* release oslThreadIdentifier @@@ see TODO @@@ */
186 removeThreadId (thread);
188 if (attached)
190 pthread_detach (thread);
193 if (destroyed)
195 osl_thread_destruct_Impl (&pImpl);
199 static void* osl_thread_start_Impl (void* pData)
201 int terminate;
202 Thread_Impl* pImpl= (Thread_Impl*)pData;
204 OSL_ASSERT(pImpl);
206 pthread_mutex_lock (&(pImpl->m_Lock));
208 /* request oslThreadIdentifier @@@ see TODO @@@ */
209 pImpl->m_Ident = insertThreadId (pImpl->m_hThread);
211 /* signal change from STARTUP to ACTIVE state */
212 pImpl->m_Flags &= ~THREADIMPL_FLAGS_STARTUP;
213 pImpl->m_Flags |= THREADIMPL_FLAGS_ACTIVE;
214 pthread_cond_signal (&(pImpl->m_Cond));
216 /* Check if thread is started in SUSPENDED state */
217 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
219 /* wait until SUSPENDED flag is cleared */
220 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
223 /* check for SUSPENDED to TERMINATE state change */
224 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
226 pthread_mutex_unlock (&(pImpl->m_Lock));
228 if (!terminate)
230 #ifdef ANDROID
231 JNIEnv* env = 0;
232 int res = (*lo_get_javavm())->AttachCurrentThread(lo_get_javavm(), &env, NULL);
233 __android_log_print(ANDROID_LOG_INFO, "LibreOffice", "New sal thread started and attached res=%d", res);
234 #endif
235 /* call worker function */
236 pImpl->m_WorkerFunction(pImpl->m_pData);
238 #ifdef ANDROID
239 res = (*lo_get_javavm())->DetachCurrentThread(lo_get_javavm());
240 __android_log_print(ANDROID_LOG_INFO, "LibreOffice", "Detached finished sal thread res=%d", res);
241 #endif
244 osl_thread_cleanup_Impl (pImpl);
245 return (0);
248 static oslThread osl_thread_create_Impl (
249 oslWorkerFunction pWorker,
250 void* pThreadData,
251 short nFlags)
253 Thread_Impl* pImpl;
254 #if defined(OPENBSD)
255 pthread_attr_t attr;
256 #endif
257 int nRet=0;
259 pImpl = osl_thread_construct_Impl();
260 if (!pImpl)
261 return (0); /* ENOMEM */
263 pImpl->m_WorkerFunction = pWorker;
264 pImpl->m_pData = pThreadData;
265 pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP;
267 pthread_mutex_lock (&(pImpl->m_Lock));
269 #if defined(OPENBSD)
270 if (pthread_attr_init(&attr) != 0)
271 return (0);
273 if (pthread_attr_setstacksize(&attr, 262144) != 0) {
274 pthread_attr_destroy(&attr);
275 return (0);
277 #endif
279 if ((nRet = pthread_create (
280 &(pImpl->m_hThread),
281 #if defined(OPENBSD)
282 &attr,
283 #else
284 PTHREAD_ATTR_DEFAULT,
285 #endif
286 osl_thread_start_Impl,
287 (void*)(pImpl))) != 0)
289 OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n",
290 nRet, strerror(nRet));
292 pthread_mutex_unlock (&(pImpl->m_Lock));
293 osl_thread_destruct_Impl (&pImpl);
295 return (0);
298 #if defined(OPENBSD)
299 pthread_attr_destroy(&attr);
300 #endif
302 /* wait for change from STARTUP to ACTIVE state */
303 while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP)
305 /* wait until STARTUP flag is cleared */
306 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
309 pthread_mutex_unlock (&(pImpl->m_Lock));
311 return ((oslThread)(pImpl));
314 oslThread osl_createThread (
315 oslWorkerFunction pWorker,
316 void * pThreadData)
318 return osl_thread_create_Impl (
319 pWorker,
320 pThreadData,
321 THREADIMPL_FLAGS_ATTACHED);
324 oslThread osl_createSuspendedThread (
325 oslWorkerFunction pWorker,
326 void * pThreadData)
328 return osl_thread_create_Impl (
329 pWorker,
330 pThreadData,
331 THREADIMPL_FLAGS_ATTACHED |
332 THREADIMPL_FLAGS_SUSPENDED );
335 void SAL_CALL osl_destroyThread(oslThread Thread)
337 if (Thread != NULL) {
338 Thread_Impl * impl = (Thread_Impl *) Thread;
339 int active;
340 pthread_mutex_lock(&impl->m_Lock);
341 active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0;
342 impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED;
343 pthread_mutex_unlock(&impl->m_Lock);
344 if (!active) {
345 osl_thread_destruct_Impl(&impl);
350 void SAL_CALL osl_resumeThread(oslThread Thread)
352 Thread_Impl* pImpl= (Thread_Impl*)Thread;
354 OSL_ASSERT(pImpl);
355 if (!pImpl)
356 return; /* EINVAL */
358 pthread_mutex_lock (&(pImpl->m_Lock));
360 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
362 /* clear SUSPENDED flag */
363 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
364 pthread_cond_signal (&(pImpl->m_Cond));
367 pthread_mutex_unlock (&(pImpl->m_Lock));
370 void SAL_CALL osl_suspendThread(oslThread Thread)
372 Thread_Impl* pImpl= (Thread_Impl*)Thread;
374 OSL_ASSERT(pImpl);
375 if (!pImpl)
376 return; /* EINVAL */
378 pthread_mutex_lock (&(pImpl->m_Lock));
380 pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
382 if (pthread_equal (pthread_self(), pImpl->m_hThread))
384 /* self suspend */
385 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
387 /* wait until SUSPENDED flag is cleared */
388 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
392 pthread_mutex_unlock (&(pImpl->m_Lock));
395 sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
397 sal_Bool active;
398 Thread_Impl* pImpl= (Thread_Impl*)Thread;
400 if (!pImpl)
401 return sal_False;
403 pthread_mutex_lock (&(pImpl->m_Lock));
404 active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
405 pthread_mutex_unlock (&(pImpl->m_Lock));
407 return (active);
410 void SAL_CALL osl_joinWithThread(oslThread Thread)
412 pthread_t thread;
413 int attached;
414 Thread_Impl* pImpl= (Thread_Impl*)Thread;
416 if (!pImpl)
417 return;
419 pthread_mutex_lock (&(pImpl->m_Lock));
421 if (pthread_equal (pthread_self(), pImpl->m_hThread))
423 /* self join */
424 pthread_mutex_unlock (&(pImpl->m_Lock));
425 return; /* EDEADLK */
428 thread = pImpl->m_hThread;
429 attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0);
430 pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED;
432 pthread_mutex_unlock (&(pImpl->m_Lock));
434 if (attached)
436 pthread_join (thread, NULL);
440 void SAL_CALL osl_terminateThread(oslThread Thread)
442 Thread_Impl* pImpl= (Thread_Impl*)Thread;
444 OSL_ASSERT(pImpl);
445 if (!pImpl)
446 return; /* EINVAL */
448 pthread_mutex_lock (&(pImpl->m_Lock));
450 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
452 /* clear SUSPENDED flag */
453 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
454 pthread_cond_signal (&(pImpl->m_Cond));
457 pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
459 pthread_mutex_unlock (&(pImpl->m_Lock));
462 sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
464 int terminate;
465 Thread_Impl* pImpl= (Thread_Impl*)Thread;
467 OSL_ASSERT(pImpl);
468 if (!pImpl)
469 return sal_False; /* EINVAL */
471 OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread));
472 if (!(pthread_equal (pthread_self(), pImpl->m_hThread)))
473 return sal_False; /* EINVAL */
475 pthread_mutex_lock (&(pImpl->m_Lock));
477 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
479 /* wait until SUSPENDED flag is cleared */
480 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
483 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
485 pthread_mutex_unlock(&(pImpl->m_Lock));
487 return (terminate == 0);
490 void SAL_CALL osl_waitThread(const TimeValue* pDelay)
492 if (pDelay)
494 struct timespec delay;
496 SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec);
498 SLEEP_TIMESPEC(delay);
502 /*****************************************************************************/
503 /* osl_yieldThread */
505 Note that POSIX scheduling _really_ requires threads to call this
506 functions, since a thread only reschedules to other thread, when
507 it blocks (sleep, blocking I/O) OR calls sched_yield().
509 /*****************************************************************************/
510 void SAL_CALL osl_yieldThread()
512 sched_yield();
515 void SAL_CALL osl_setThreadName(char const * name) {
516 #if defined LINUX && ! defined __FreeBSD_kernel__
517 if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) {
518 OSL_TRACE(
519 "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX,
520 errno);
522 #else
523 (void) name;
524 #endif
527 /*****************************************************************************/
528 /* osl_getThreadIdentifier @@@ see TODO @@@ */
529 /*****************************************************************************/
531 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
533 typedef struct _HashEntry
535 pthread_t Handle;
536 sal_uInt16 Ident;
537 struct _HashEntry *Next;
538 } HashEntry;
540 static HashEntry* HashTable[31];
541 static int HashSize = SAL_N_ELEMENTS(HashTable);
543 static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER;
545 static sal_uInt16 LastIdent = 0;
547 static sal_uInt16 lookupThreadId (pthread_t hThread)
549 HashEntry *pEntry;
551 pthread_mutex_lock(&HashLock);
553 pEntry = HashTable[HASHID(hThread)];
554 while (pEntry != NULL)
556 if (pthread_equal(pEntry->Handle, hThread))
558 pthread_mutex_unlock(&HashLock);
559 return (pEntry->Ident);
561 pEntry = pEntry->Next;
564 pthread_mutex_unlock(&HashLock);
566 return (0);
569 static sal_uInt16 insertThreadId (pthread_t hThread)
571 HashEntry *pEntry, *pInsert = NULL;
573 pthread_mutex_lock(&HashLock);
575 pEntry = HashTable[HASHID(hThread)];
577 while (pEntry != NULL)
579 if (pthread_equal(pEntry->Handle, hThread))
580 break;
582 pInsert = pEntry;
583 pEntry = pEntry->Next;
586 if (pEntry == NULL)
588 pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
590 pEntry->Handle = hThread;
592 ++ LastIdent;
594 if ( LastIdent == 0 )
595 LastIdent = 1;
597 pEntry->Ident = LastIdent;
599 if (pInsert)
600 pInsert->Next = pEntry;
601 else
602 HashTable[HASHID(hThread)] = pEntry;
605 pthread_mutex_unlock(&HashLock);
607 return (pEntry->Ident);
610 static void removeThreadId (pthread_t hThread)
612 HashEntry *pEntry, *pRemove = NULL;
614 pthread_mutex_lock(&HashLock);
616 pEntry = HashTable[HASHID(hThread)];
617 while (pEntry != NULL)
619 if (pthread_equal(pEntry->Handle, hThread))
620 break;
622 pRemove = pEntry;
623 pEntry = pEntry->Next;
626 if (pEntry != NULL)
628 if (pRemove)
629 pRemove->Next = pEntry->Next;
630 else
631 HashTable[HASHID(hThread)] = pEntry->Next;
633 free(pEntry);
636 pthread_mutex_unlock(&HashLock);
639 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
641 Thread_Impl* pImpl= (Thread_Impl*)Thread;
642 sal_uInt16 Ident;
644 if (pImpl)
645 Ident = pImpl->m_Ident;
646 else
648 /* current thread */
649 pthread_t current = pthread_self();
651 Ident = lookupThreadId (current);
652 if (Ident == 0)
653 /* @@@ see TODO: alien pthread_self() @@@ */
654 Ident = insertThreadId (current);
657 return ((oslThreadIdentifier)(Ident));
660 /*****************************************************************************
661 @@@ see TODO @@@
662 osl_thread_priority_init_Impl
664 set the base-priority of the main-thread to
665 oslThreadPriorityNormal (64) since 0 (lowest) is
666 the system default. This behaviour collides with
667 our enum-priority definition (highest..normal..lowest).
668 A normaluser will expect the main-thread of an app.
669 to have the "normal" priority.
671 *****************************************************************************/
672 static void osl_thread_priority_init_Impl (void)
674 #ifndef NO_PTHREAD_PRIORITY
675 struct sched_param param;
676 int policy=0;
677 int nRet=0;
679 /* @@@ see TODO: calling thread may not be main thread @@@ */
681 if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
683 OSL_TRACE("failed to get priority of thread [%s]",strerror(nRet));
684 return;
687 #if defined (SOLARIS)
688 if ( policy >= _SCHED_NEXT)
690 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
691 /* one gets 959917873 as the policy */
692 /* so set the policy to a default one */
693 policy=SCHED_OTHER;
695 #endif /* SOLARIS */
697 if ((nRet = sched_get_priority_min(policy) ) != -1)
699 OSL_TRACE("Min Prioriy for policy '%i' == '%i'",policy,nRet);
700 g_thread.m_priority.m_Lowest=nRet;
702 #if OSL_DEBUG_LEVEL > 1
703 else
705 fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
707 #endif /* OSL_DEBUG_LEVEL */
709 if ((nRet = sched_get_priority_max(policy) ) != -1)
711 OSL_TRACE("Max Prioriy for policy '%i' == '%i'",policy,nRet);
712 g_thread.m_priority.m_Highest=nRet;
714 #if OSL_DEBUG_LEVEL > 1
715 else
717 fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
719 #endif /* OSL_DEBUG_LEVEL */
721 g_thread.m_priority.m_Normal =
722 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2;
723 g_thread.m_priority.m_Below_Normal =
724 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2;
725 g_thread.m_priority.m_Above_Normal =
726 (g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2;
728 /* @@@ set prio of calling (not main) thread (?) @@@ */
730 param.sched_priority= g_thread.m_priority.m_Normal;
732 if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
734 OSL_TRACE("failed to change base priority of thread [%s]",strerror(nRet));
735 OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority);
738 #endif /* NO_PTHREAD_PRIORITY */
741 /*****************************************************************************/
742 /* osl_setThreadPriority */
744 Impl-Notes: contrary to solaris-docu, which claims
745 valid priority-levels from 0 .. INT_MAX, only the
746 range 0..127 is accepted. (0 lowest, 127 highest)
748 /*****************************************************************************/
749 void SAL_CALL osl_setThreadPriority (
750 oslThread Thread,
751 oslThreadPriority Priority)
753 #ifndef NO_PTHREAD_PRIORITY
755 struct sched_param Param;
756 int policy;
757 int nRet;
759 #endif /* NO_PTHREAD_PRIORITY */
761 Thread_Impl* pImpl= (Thread_Impl*)Thread;
763 OSL_ASSERT(pImpl);
764 if (!pImpl)
765 return; /* EINVAL */
767 #ifdef NO_PTHREAD_PRIORITY
768 (void) Priority; /* unused */
769 #else /* NO_PTHREAD_PRIORITY */
771 if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
772 return; /* ESRCH */
774 #if defined (SOLARIS)
775 if ( policy >= _SCHED_NEXT)
777 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
778 /* one gets 959917873 as the policy */
779 /* so set the policy to a default one */
780 policy=SCHED_OTHER;
782 #endif /* SOLARIS */
784 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
786 switch(Priority)
788 case osl_Thread_PriorityHighest:
789 Param.sched_priority= g_thread.m_priority.m_Highest;
790 break;
792 case osl_Thread_PriorityAboveNormal:
793 Param.sched_priority= g_thread.m_priority.m_Above_Normal;
794 break;
796 case osl_Thread_PriorityNormal:
797 Param.sched_priority= g_thread.m_priority.m_Normal;
798 break;
800 case osl_Thread_PriorityBelowNormal:
801 Param.sched_priority= g_thread.m_priority.m_Below_Normal;
802 break;
804 case osl_Thread_PriorityLowest:
805 Param.sched_priority= g_thread.m_priority.m_Lowest;
806 break;
808 case osl_Thread_PriorityUnknown:
809 OSL_ASSERT(sal_False); /* only fools try this...*/
811 /* let release-version behave friendly */
812 return;
814 default:
815 /* enum expanded, but forgotten here...*/
816 OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
818 /* let release-version behave friendly */
819 return;
822 if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
824 OSL_TRACE("failed to change thread priority [%s]",strerror(nRet));
827 #endif /* NO_PTHREAD_PRIORITY */
830 oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
832 #ifndef NO_PTHREAD_PRIORITY
834 struct sched_param Param;
835 int Policy;
837 #endif /* NO_PTHREAD_PRIORITY */
839 oslThreadPriority Priority = osl_Thread_PriorityNormal;
840 Thread_Impl* pImpl= (Thread_Impl*)Thread;
842 OSL_ASSERT(pImpl);
843 if (!pImpl)
844 return osl_Thread_PriorityUnknown; /* EINVAL */
846 #ifndef NO_PTHREAD_PRIORITY
848 if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0)
849 return osl_Thread_PriorityUnknown; /* ESRCH */
851 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
853 /* map pthread priority to enum */
854 if (Param.sched_priority==g_thread.m_priority.m_Highest)
856 /* 127 - highest */
857 Priority= osl_Thread_PriorityHighest;
859 else if (Param.sched_priority > g_thread.m_priority.m_Normal)
861 /* 65..126 - above normal */
862 Priority= osl_Thread_PriorityAboveNormal;
864 else if (Param.sched_priority == g_thread.m_priority.m_Normal)
866 /* normal */
867 Priority= osl_Thread_PriorityNormal;
869 else if (Param.sched_priority > g_thread.m_priority.m_Lowest)
871 /* 63..1 -below normal */
872 Priority= osl_Thread_PriorityBelowNormal;
874 else if (Param.sched_priority == g_thread.m_priority.m_Lowest)
876 /* 0 - lowest */
877 Priority= osl_Thread_PriorityLowest;
879 else
881 /* unknown */
882 Priority= osl_Thread_PriorityUnknown;
885 #endif /* NO_PTHREAD_PRIORITY */
887 return Priority;
890 typedef struct _wrapper_pthread_key
892 pthread_key_t m_key;
893 oslThreadKeyCallbackFunction pfnCallback;
894 } wrapper_pthread_key;
896 oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
898 wrapper_pthread_key *pKey = (wrapper_pthread_key*)rtl_allocateMemory(sizeof(wrapper_pthread_key));
900 if (pKey)
902 pKey->pfnCallback = pCallback;
904 if (pthread_key_create(&(pKey->m_key), pKey->pfnCallback) != 0)
906 rtl_freeMemory(pKey);
907 pKey = 0;
911 return ((oslThreadKey)pKey);
914 void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
916 wrapper_pthread_key *pKey = (wrapper_pthread_key*)Key;
917 if (pKey)
919 pthread_key_delete(pKey->m_key);
920 rtl_freeMemory(pKey);
924 void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
926 wrapper_pthread_key *pKey = (wrapper_pthread_key*)Key;
927 return pKey ? pthread_getspecific(pKey->m_key) : NULL;
930 sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
932 sal_Bool bRet;
933 void *pOldData = NULL;
934 wrapper_pthread_key *pKey = (wrapper_pthread_key*)Key;
935 if (!pKey)
936 return sal_False;
938 if (pKey->pfnCallback)
939 pOldData = pthread_getspecific(pKey->m_key);
941 bRet = (pthread_setspecific(pKey->m_key, pData) == 0);
943 if (bRet && pKey->pfnCallback && pOldData)
944 pKey->pfnCallback(pOldData);
946 return bRet;
949 /*****************************************************************************/
950 /* Thread Local Text Encoding */
951 /*****************************************************************************/
952 static void osl_thread_textencoding_init_Impl (void)
954 rtl_TextEncoding defaultEncoding;
956 /* create thread specific data key */
957 pthread_key_create (&(g_thread.m_textencoding.m_key), NULL);
959 /* determine default text encoding */
960 defaultEncoding = osl_getTextEncodingFromLocale(NULL);
961 OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
964 Tools string functions call abort() on an unknown encoding so ASCII
965 is a meaningfull fallback regardless whether the assertion makes sense.
968 if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding )
969 defaultEncoding = RTL_TEXTENCODING_ASCII_US;
971 g_thread.m_textencoding.m_default = defaultEncoding;
974 rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding()
976 rtl_TextEncoding threadEncoding;
978 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
980 /* check for thread specific encoding, use default if not set */
981 threadEncoding = SAL_INT_CAST(
982 rtl_TextEncoding,
983 (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key));
984 if (0 == threadEncoding)
985 threadEncoding = g_thread.m_textencoding.m_default;
987 return threadEncoding;
990 rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
992 rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
994 /* save encoding in thread local storage */
995 pthread_setspecific (
996 g_thread.m_textencoding.m_key,
997 (void*) SAL_INT_CAST(sal_uIntPtr, Encoding));
999 return oldThreadEncoding;
1002 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */