1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
33 #include <android/log.h>
34 #include <osl/detail/android-bootstrap.h>
37 #if defined LINUX && ! defined __FreeBSD_kernel__
38 #include <sys/prctl.h>
40 #define PR_SET_NAME 15
44 /****************************************************************************
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
79 sal_uInt16 m_Ident
; /* @@@ see TODO @@@ */
81 oslWorkerFunction m_WorkerFunction
;
83 pthread_mutex_t m_Lock
;
84 pthread_cond_t m_Cond
;
87 struct osl_thread_priority_st
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
=
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
));
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
);
157 static void osl_thread_destruct_Impl (Thread_Impl
** ppImpl
)
162 pthread_cond_destroy (&((*ppImpl
)->m_Cond
));
163 pthread_mutex_destroy (&((*ppImpl
)->m_Lock
));
170 static void osl_thread_cleanup_Impl (Thread_Impl
* pImpl
)
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
);
190 pthread_detach (thread
);
195 osl_thread_destruct_Impl (&pImpl
);
199 static void* osl_thread_start_Impl (void* pData
)
202 Thread_Impl
* pImpl
= (Thread_Impl
*)pData
;
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
));
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
);
235 /* call worker function */
236 pImpl
->m_WorkerFunction(pImpl
->m_pData
);
239 res
= (*lo_get_javavm())->DetachCurrentThread(lo_get_javavm());
240 __android_log_print(ANDROID_LOG_INFO
, "LibreOffice", "Detached finished sal thread res=%d", res
);
244 osl_thread_cleanup_Impl (pImpl
);
248 static oslThread
osl_thread_create_Impl (
249 oslWorkerFunction pWorker
,
259 pImpl
= osl_thread_construct_Impl();
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
));
270 if (pthread_attr_init(&attr
) != 0)
273 if (pthread_attr_setstacksize(&attr
, 262144) != 0) {
274 pthread_attr_destroy(&attr
);
279 if ((nRet
= pthread_create (
284 PTHREAD_ATTR_DEFAULT
,
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
);
299 pthread_attr_destroy(&attr
);
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
,
318 return osl_thread_create_Impl (
321 THREADIMPL_FLAGS_ATTACHED
);
324 oslThread
osl_createSuspendedThread (
325 oslWorkerFunction pWorker
,
328 return osl_thread_create_Impl (
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
;
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
);
345 osl_thread_destruct_Impl(&impl
);
350 void SAL_CALL
osl_resumeThread(oslThread Thread
)
352 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
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
;
378 pthread_mutex_lock (&(pImpl
->m_Lock
));
380 pImpl
->m_Flags
|= THREADIMPL_FLAGS_SUSPENDED
;
382 if (pthread_equal (pthread_self(), pImpl
->m_hThread
))
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
)
398 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
403 pthread_mutex_lock (&(pImpl
->m_Lock
));
404 active
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_ACTIVE
) > 0);
405 pthread_mutex_unlock (&(pImpl
->m_Lock
));
410 void SAL_CALL
osl_joinWithThread(oslThread Thread
)
414 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
419 pthread_mutex_lock (&(pImpl
->m_Lock
));
421 if (pthread_equal (pthread_self(), pImpl
->m_hThread
))
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
));
436 pthread_join (thread
, NULL
);
440 void SAL_CALL
osl_terminateThread(oslThread Thread
)
442 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
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
)
465 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
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
)
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()
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) {
519 "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX
,
527 /*****************************************************************************/
528 /* osl_getThreadIdentifier @@@ see TODO @@@ */
529 /*****************************************************************************/
531 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
533 typedef struct _HashEntry
537 struct _HashEntry
*Next
;
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
)
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
);
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
))
583 pEntry
= pEntry
->Next
;
588 pEntry
= (HashEntry
*) calloc(sizeof(HashEntry
), 1);
590 pEntry
->Handle
= hThread
;
594 if ( LastIdent
== 0 )
597 pEntry
->Ident
= LastIdent
;
600 pInsert
->Next
= pEntry
;
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
))
623 pEntry
= pEntry
->Next
;
629 pRemove
->Next
= pEntry
->Next
;
631 HashTable
[HASHID(hThread
)] = pEntry
->Next
;
636 pthread_mutex_unlock(&HashLock
);
639 oslThreadIdentifier SAL_CALL
osl_getThreadIdentifier(oslThread Thread
)
641 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
645 Ident
= pImpl
->m_Ident
;
649 pthread_t current
= pthread_self();
651 Ident
= lookupThreadId (current
);
653 /* @@@ see TODO: alien pthread_self() @@@ */
654 Ident
= insertThreadId (current
);
657 return ((oslThreadIdentifier
)(Ident
));
660 /*****************************************************************************
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
;
679 /* @@@ see TODO: calling thread may not be main thread @@@ */
681 if ((nRet
= pthread_getschedparam(pthread_self(), &policy
, ¶m
)) != 0)
683 OSL_TRACE("failed to get priority of thread [%s]",strerror(nRet
));
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 */
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
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
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
, ¶m
)) != 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 (
751 oslThreadPriority Priority
)
753 #ifndef NO_PTHREAD_PRIORITY
755 struct sched_param Param
;
759 #endif /* NO_PTHREAD_PRIORITY */
761 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
767 #ifdef NO_PTHREAD_PRIORITY
768 (void) Priority
; /* unused */
769 #else /* NO_PTHREAD_PRIORITY */
771 if (pthread_getschedparam(pImpl
->m_hThread
, &policy
, &Param
) != 0)
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 */
784 pthread_once (&(g_thread
.m_once
), osl_thread_init_Impl
);
788 case osl_Thread_PriorityHighest
:
789 Param
.sched_priority
= g_thread
.m_priority
.m_Highest
;
792 case osl_Thread_PriorityAboveNormal
:
793 Param
.sched_priority
= g_thread
.m_priority
.m_Above_Normal
;
796 case osl_Thread_PriorityNormal
:
797 Param
.sched_priority
= g_thread
.m_priority
.m_Normal
;
800 case osl_Thread_PriorityBelowNormal
:
801 Param
.sched_priority
= g_thread
.m_priority
.m_Below_Normal
;
804 case osl_Thread_PriorityLowest
:
805 Param
.sched_priority
= g_thread
.m_priority
.m_Lowest
;
808 case osl_Thread_PriorityUnknown
:
809 OSL_ASSERT(sal_False
); /* only fools try this...*/
811 /* let release-version behave friendly */
815 /* enum expanded, but forgotten here...*/
816 OSL_ENSURE(sal_False
,"osl_setThreadPriority : unknown priority\n");
818 /* let release-version behave friendly */
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
;
837 #endif /* NO_PTHREAD_PRIORITY */
839 oslThreadPriority Priority
= osl_Thread_PriorityNormal
;
840 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
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
)
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
)
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
)
877 Priority
= osl_Thread_PriorityLowest
;
882 Priority
= osl_Thread_PriorityUnknown
;
885 #endif /* NO_PTHREAD_PRIORITY */
890 typedef struct _wrapper_pthread_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
));
902 pKey
->pfnCallback
= pCallback
;
904 if (pthread_key_create(&(pKey
->m_key
), pKey
->pfnCallback
) != 0)
906 rtl_freeMemory(pKey
);
911 return ((oslThreadKey
)pKey
);
914 void SAL_CALL
osl_destroyThreadKey(oslThreadKey Key
)
916 wrapper_pthread_key
*pKey
= (wrapper_pthread_key
*)Key
;
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
)
933 void *pOldData
= NULL
;
934 wrapper_pthread_key
*pKey
= (wrapper_pthread_key
*)Key
;
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
);
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(
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: */