1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: thread.c,v $
10 * $Revision: 1.31.48.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
33 #include <osl/diagnose.h>
34 #include <osl/thread.h>
35 #include <osl/nlsupport.h>
36 #ifndef _RTL_TEXTENC_H_
37 #include <rtl/textenc.h>
40 /****************************************************************************
43 * (1) 'osl_thread_priority_init_Impl()'
44 * - insane assumption that initializing caller is main thread
45 * - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?)
46 * - POSIX doesn't require defined prio's for SCHED_OTHER (!)
47 * - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?)
48 * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()'
49 * - cannot reliably be applied to 'alien' threads;
50 * - memory leak for 'alien' thread 'HashEntry's;
51 * - use 'PTHREAD_VALUE(pthread_t)' as identifier instead (?)
52 * - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar
53 * (3) 'oslSigAlarmHandler()' (#71232#)
54 * - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates
55 * the process. So we initialize our signal handling module and do
56 * register a SIGALRM Handler which catches and ignores it]
57 * - should this still happen, 'signal.c' needs to be fixed instead.
59 ****************************************************************************/
61 /*****************************************************************************/
62 /* Internal data structures and functions */
63 /*****************************************************************************/
65 #define THREADIMPL_FLAGS_TERMINATE 0x00001
66 #define THREADIMPL_FLAGS_STARTUP 0x00002
67 #define THREADIMPL_FLAGS_SUSPENDED 0x00004
68 #define THREADIMPL_FLAGS_ACTIVE 0x00008
69 #define THREADIMPL_FLAGS_ATTACHED 0x00010
70 #define THREADIMPL_FLAGS_DESTROYED 0x00020
72 typedef struct osl_thread_impl_st
75 sal_uInt16 m_Ident
; /* @@@ see TODO @@@ */
77 oslWorkerFunction m_WorkerFunction
;
79 pthread_mutex_t m_Lock
;
80 pthread_cond_t m_Cond
;
83 struct osl_thread_priority_st
92 #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
93 static void osl_thread_priority_init_Impl (void);
95 struct osl_thread_textencoding_st
97 pthread_key_t m_key
; /* key to store thread local text encoding */
98 rtl_TextEncoding m_default
; /* the default text encoding */
101 #define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW }
102 static void osl_thread_textencoding_init_Impl (void);
104 struct osl_thread_global_st
106 pthread_once_t m_once
;
107 struct osl_thread_priority_st m_priority
;
108 struct osl_thread_textencoding_st m_textencoding
;
111 static struct osl_thread_global_st g_thread
=
114 OSL_THREAD_PRIORITY_INITIALIZER
,
115 OSL_THREAD_TEXTENCODING_INITIALIZER
118 static void osl_thread_init_Impl (void);
120 static Thread_Impl
* osl_thread_construct_Impl (void);
121 static void osl_thread_destruct_Impl (Thread_Impl
** ppImpl
);
123 static void* osl_thread_start_Impl (void * pData
);
124 static void osl_thread_cleanup_Impl (void * pData
);
126 static oslThread
osl_thread_create_Impl (
127 oslWorkerFunction pWorker
, void * pThreadData
, short nFlags
);
129 static void osl_thread_join_cleanup_Impl (void * opaque
);
130 static void osl_thread_wait_cleanup_Impl (void * opaque
);
132 /* @@@ see TODO @@@ */
133 static sal_uInt16
insertThreadId (pthread_t hThread
);
134 static sal_uInt16
lookupThreadId (pthread_t hThread
);
135 static void removeThreadId (pthread_t hThread
);
137 /*****************************************************************************/
138 /* osl_thread_init_Impl */
139 /*****************************************************************************/
140 static void osl_thread_init_Impl (void)
142 osl_thread_priority_init_Impl();
143 osl_thread_textencoding_init_Impl();
146 /*****************************************************************************/
147 /* osl_thread_join_cleanup_Impl */
148 /*****************************************************************************/
149 static void osl_thread_join_cleanup_Impl (void * opaque
)
151 pthread_t hThread
= (pthread_t
)(opaque
);
152 pthread_detach (hThread
);
155 /*****************************************************************************/
156 /* osl_thread_wait_cleanup_Impl */
157 /*****************************************************************************/
158 static void osl_thread_wait_cleanup_Impl (void * opaque
)
160 pthread_mutex_t
* pMutex
= (pthread_mutex_t
*)(opaque
);
161 pthread_mutex_unlock (pMutex
);
164 /*****************************************************************************/
165 /* osl_thread_construct_Impl */
166 /*****************************************************************************/
167 Thread_Impl
* osl_thread_construct_Impl (void)
169 Thread_Impl
* pImpl
= malloc (sizeof(Thread_Impl
));
172 memset (pImpl
, 0, sizeof(Thread_Impl
));
174 pthread_mutex_init (&(pImpl
->m_Lock
), PTHREAD_MUTEXATTR_DEFAULT
);
175 pthread_cond_init (&(pImpl
->m_Cond
), PTHREAD_CONDATTR_DEFAULT
);
180 /*****************************************************************************/
181 /* osl_thread_destruct_Impl */
182 /*****************************************************************************/
183 static void osl_thread_destruct_Impl (Thread_Impl
** ppImpl
)
188 pthread_cond_destroy (&((*ppImpl
)->m_Cond
));
189 pthread_mutex_destroy (&((*ppImpl
)->m_Lock
));
196 /*****************************************************************************/
197 /* osl_thread_cleanup_Impl */
198 /*****************************************************************************/
199 static void osl_thread_cleanup_Impl (void* pData
)
204 Thread_Impl
* pImpl
= (Thread_Impl
*)pData
;
206 pthread_mutex_lock (&(pImpl
->m_Lock
));
208 thread
= pImpl
->m_hThread
;
209 attached
= (pImpl
->m_Flags
& THREADIMPL_FLAGS_ATTACHED
) != 0;
210 destroyed
= (pImpl
->m_Flags
& THREADIMPL_FLAGS_DESTROYED
) != 0;
211 pImpl
->m_Flags
&= ~(THREADIMPL_FLAGS_ACTIVE
| THREADIMPL_FLAGS_ATTACHED
);
213 pthread_mutex_unlock (&(pImpl
->m_Lock
));
215 /* release oslThreadIdentifier @@@ see TODO @@@ */
216 removeThreadId (thread
);
220 pthread_detach (thread
);
225 osl_thread_destruct_Impl (&pImpl
);
229 /*****************************************************************************/
230 /* osl_thread_start_Impl */
231 /*****************************************************************************/
232 static void* osl_thread_start_Impl (void* pData
)
235 Thread_Impl
* pImpl
= (Thread_Impl
*)pData
;
239 pthread_mutex_lock (&(pImpl
->m_Lock
));
241 /* install cleanup handler */
242 pthread_cleanup_push (osl_thread_cleanup_Impl
, pData
);
244 /* request oslThreadIdentifier @@@ see TODO @@@ */
245 pImpl
->m_Ident
= insertThreadId (pImpl
->m_hThread
);
247 /* signal change from STARTUP to ACTIVE state */
248 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_STARTUP
;
249 pImpl
->m_Flags
|= THREADIMPL_FLAGS_ACTIVE
;
250 pthread_cond_signal (&(pImpl
->m_Cond
));
252 /* Check if thread is started in SUSPENDED state */
253 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
255 /* wait until SUSPENDED flag is cleared */
256 pthread_cleanup_push (osl_thread_wait_cleanup_Impl
, &(pImpl
->m_Lock
));
257 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
258 pthread_cleanup_pop (0);
261 /* check for SUSPENDED to TERMINATE state change */
262 terminate
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_TERMINATE
) > 0);
264 pthread_mutex_unlock (&(pImpl
->m_Lock
));
268 /* call worker function */
269 pImpl
->m_WorkerFunction(pImpl
->m_pData
);
272 /* call cleanup handler and leave */
273 pthread_cleanup_pop (1);
277 /*****************************************************************************/
278 /* osl_thread_create_Impl */
279 /*****************************************************************************/
280 static oslThread
osl_thread_create_Impl (
281 oslWorkerFunction pWorker
,
288 pImpl
= osl_thread_construct_Impl();
290 return (0); /* ENOMEM */
292 pImpl
->m_WorkerFunction
= pWorker
;
293 pImpl
->m_pData
= pThreadData
;
294 pImpl
->m_Flags
= nFlags
| THREADIMPL_FLAGS_STARTUP
;
296 pthread_mutex_lock (&(pImpl
->m_Lock
));
298 if ((nRet
= pthread_create (
300 PTHREAD_ATTR_DEFAULT
,
301 osl_thread_start_Impl
,
302 (void*)(pImpl
))) != 0)
304 OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n",
305 nRet
, strerror(nRet
));
307 pthread_mutex_unlock (&(pImpl
->m_Lock
));
308 osl_thread_destruct_Impl (&pImpl
);
313 /* wait for change from STARTUP to ACTIVE state */
314 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_STARTUP
)
316 /* wait until STARTUP flag is cleared */
317 pthread_cleanup_push (osl_thread_wait_cleanup_Impl
, &(pImpl
->m_Lock
));
318 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
319 pthread_cleanup_pop (0);
322 pthread_mutex_unlock (&(pImpl
->m_Lock
));
324 return ((oslThread
)(pImpl
));
327 /*****************************************************************************/
328 /* osl_createThread */
329 /*****************************************************************************/
330 oslThread
osl_createThread (
331 oslWorkerFunction pWorker
,
334 return osl_thread_create_Impl (
337 THREADIMPL_FLAGS_ATTACHED
);
340 /*****************************************************************************/
341 /* osl_createSuspendedThread */
342 /*****************************************************************************/
343 oslThread
osl_createSuspendedThread (
344 oslWorkerFunction pWorker
,
347 return osl_thread_create_Impl (
350 THREADIMPL_FLAGS_ATTACHED
|
351 THREADIMPL_FLAGS_SUSPENDED
);
354 /*****************************************************************************/
355 /* osl_destroyThread */
356 /*****************************************************************************/
357 void SAL_CALL
osl_destroyThread(oslThread Thread
)
359 if (Thread
!= NULL
) {
360 Thread_Impl
* impl
= (Thread_Impl
*) Thread
;
362 pthread_mutex_lock(&impl
->m_Lock
);
363 active
= (impl
->m_Flags
& THREADIMPL_FLAGS_ACTIVE
) != 0;
364 impl
->m_Flags
|= THREADIMPL_FLAGS_DESTROYED
;
365 pthread_mutex_unlock(&impl
->m_Lock
);
367 osl_thread_destruct_Impl(&impl
);
372 /*****************************************************************************/
373 /* osl_resumeThread */
374 /*****************************************************************************/
375 void SAL_CALL
osl_resumeThread(oslThread Thread
)
377 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
383 pthread_mutex_lock (&(pImpl
->m_Lock
));
385 if (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
387 /* clear SUSPENDED flag */
388 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_SUSPENDED
;
389 pthread_cond_signal (&(pImpl
->m_Cond
));
392 pthread_mutex_unlock (&(pImpl
->m_Lock
));
395 /*****************************************************************************/
396 /* osl_suspendThread */
397 /*****************************************************************************/
398 void SAL_CALL
osl_suspendThread(oslThread Thread
)
400 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
406 pthread_mutex_lock (&(pImpl
->m_Lock
));
408 pImpl
->m_Flags
|= THREADIMPL_FLAGS_SUSPENDED
;
410 if (pthread_equal (pthread_self(), pImpl
->m_hThread
))
413 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
415 /* wait until SUSPENDED flag is cleared */
416 pthread_cleanup_push (osl_thread_wait_cleanup_Impl
, &(pImpl
->m_Lock
));
417 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
418 pthread_cleanup_pop (0);
422 pthread_mutex_unlock (&(pImpl
->m_Lock
));
425 /*****************************************************************************/
426 /* osl_isThreadRunning */
427 /*****************************************************************************/
428 sal_Bool SAL_CALL
osl_isThreadRunning(const oslThread Thread
)
431 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
436 pthread_mutex_lock (&(pImpl
->m_Lock
));
437 active
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_ACTIVE
) > 0);
438 pthread_mutex_unlock (&(pImpl
->m_Lock
));
443 /*****************************************************************************/
444 /* osl_joinWithThread */
445 /*****************************************************************************/
446 void SAL_CALL
osl_joinWithThread(oslThread Thread
)
450 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
455 pthread_mutex_lock (&(pImpl
->m_Lock
));
457 if (pthread_equal (pthread_self(), pImpl
->m_hThread
))
460 pthread_mutex_unlock (&(pImpl
->m_Lock
));
461 return; /* EDEADLK */
464 thread
= pImpl
->m_hThread
;
465 attached
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_ATTACHED
) > 0);
466 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_ATTACHED
;
468 pthread_mutex_unlock (&(pImpl
->m_Lock
));
472 /* install cleanup handler to ensure consistent flags and state */
473 pthread_cleanup_push (
474 osl_thread_join_cleanup_Impl
, (void*)thread
);
477 pthread_join (thread
, NULL
);
479 /* remove cleanup handler */
480 pthread_cleanup_pop (0);
484 /*****************************************************************************/
485 /* osl_terminateThread */
486 /*****************************************************************************/
487 void SAL_CALL
osl_terminateThread(oslThread Thread
)
489 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
495 pthread_mutex_lock (&(pImpl
->m_Lock
));
497 if (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
499 /* clear SUSPENDED flag */
500 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_SUSPENDED
;
501 pthread_cond_signal (&(pImpl
->m_Cond
));
504 pImpl
->m_Flags
|= THREADIMPL_FLAGS_TERMINATE
;
506 pthread_mutex_unlock (&(pImpl
->m_Lock
));
509 /*****************************************************************************/
510 /* osl_scheduleThread */
511 /*****************************************************************************/
512 sal_Bool SAL_CALL
osl_scheduleThread(oslThread Thread
)
515 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
519 return sal_False
; /* EINVAL */
521 OSL_ASSERT(pthread_equal (pthread_self(), pImpl
->m_hThread
));
522 if (!(pthread_equal (pthread_self(), pImpl
->m_hThread
)))
523 return sal_False
; /* EINVAL */
525 pthread_testcancel();
526 pthread_mutex_lock (&(pImpl
->m_Lock
));
528 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
530 /* wait until SUSPENDED flag is cleared */
531 pthread_cleanup_push (osl_thread_wait_cleanup_Impl
, &(pImpl
->m_Lock
));
532 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
533 pthread_cleanup_pop (0);
536 terminate
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_TERMINATE
) > 0);
538 pthread_mutex_unlock(&(pImpl
->m_Lock
));
539 pthread_testcancel();
541 return (terminate
== 0);
544 /*****************************************************************************/
546 /*****************************************************************************/
547 void SAL_CALL
osl_waitThread(const TimeValue
* pDelay
)
551 struct timespec delay
;
553 SET_TIMESPEC(delay
, pDelay
->Seconds
, pDelay
->Nanosec
);
555 SLEEP_TIMESPEC(delay
);
559 /*****************************************************************************/
560 /* osl_yieldThread */
562 Note that POSIX scheduling _really_ requires threads to call this
563 functions, since a thread only reschedules to other thread, when
564 it blocks (sleep, blocking I/O) OR calls sched_yield().
566 /*****************************************************************************/
567 void SAL_CALL
osl_yieldThread()
572 /*****************************************************************************/
573 /* osl_getThreadIdentifier @@@ see TODO @@@ */
574 /*****************************************************************************/
576 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
578 typedef struct _HashEntry
582 struct _HashEntry
*Next
;
585 static HashEntry
* HashTable
[31];
586 static int HashSize
= sizeof(HashTable
) / sizeof(HashTable
[0]);
588 static pthread_mutex_t HashLock
= PTHREAD_MUTEX_INITIALIZER
;
590 static sal_uInt16 LastIdent
= 0;
592 static sal_uInt16
lookupThreadId (pthread_t hThread
)
596 pthread_mutex_lock(&HashLock
);
598 pEntry
= HashTable
[HASHID(hThread
)];
599 while (pEntry
!= NULL
)
601 if (pthread_equal(pEntry
->Handle
, hThread
))
603 pthread_mutex_unlock(&HashLock
);
604 return (pEntry
->Ident
);
606 pEntry
= pEntry
->Next
;
609 pthread_mutex_unlock(&HashLock
);
614 static sal_uInt16
insertThreadId (pthread_t hThread
)
616 HashEntry
*pEntry
, *pInsert
= NULL
;
618 pthread_mutex_lock(&HashLock
);
620 pEntry
= HashTable
[HASHID(hThread
)];
622 while (pEntry
!= NULL
)
624 if (pthread_equal(pEntry
->Handle
, hThread
))
628 pEntry
= pEntry
->Next
;
633 pEntry
= (HashEntry
*) calloc(sizeof(HashEntry
), 1);
635 pEntry
->Handle
= hThread
;
639 if ( LastIdent
== 0 )
642 pEntry
->Ident
= LastIdent
;
645 pInsert
->Next
= pEntry
;
647 HashTable
[HASHID(hThread
)] = pEntry
;
650 pthread_mutex_unlock(&HashLock
);
652 return (pEntry
->Ident
);
655 static void removeThreadId (pthread_t hThread
)
657 HashEntry
*pEntry
, *pRemove
= NULL
;
659 pthread_mutex_lock(&HashLock
);
661 pEntry
= HashTable
[HASHID(hThread
)];
662 while (pEntry
!= NULL
)
664 if (pthread_equal(pEntry
->Handle
, hThread
))
668 pEntry
= pEntry
->Next
;
674 pRemove
->Next
= pEntry
->Next
;
676 HashTable
[HASHID(hThread
)] = pEntry
->Next
;
681 pthread_mutex_unlock(&HashLock
);
684 oslThreadIdentifier SAL_CALL
osl_getThreadIdentifier(oslThread Thread
)
686 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
690 Ident
= pImpl
->m_Ident
;
694 pthread_t current
= pthread_self();
696 Ident
= lookupThreadId (current
);
698 /* @@@ see TODO: alien pthread_self() @@@ */
699 Ident
= insertThreadId (current
);
702 return ((oslThreadIdentifier
)(Ident
));
705 /*****************************************************************************
707 osl_thread_priority_init_Impl
709 set the base-priority of the main-thread to
710 oslThreadPriorityNormal (64) since 0 (lowest) is
711 the system default. This behaviour collides with
712 our enum-priority definition (highest..normal..lowest).
713 A normaluser will expect the main-thread of an app.
714 to have the "normal" priority.
716 *****************************************************************************/
717 static void osl_thread_priority_init_Impl (void)
719 #ifndef NO_PTHREAD_PRIORITY
720 struct sched_param param
;
724 /* @@@ see TODO: calling thread may not be main thread @@@ */
726 if ((nRet
= pthread_getschedparam(pthread_self(), &policy
, ¶m
)) != 0)
728 OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet
));
732 #if defined (SOLARIS)
733 if ( policy
>= _SCHED_NEXT
)
735 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
736 /* one gets 959917873 as the policy */
737 /* so set the policy to a default one */
742 if ((nRet
= sched_get_priority_min(policy
) ) != -1)
744 OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy
,nRet
);
745 g_thread
.m_priority
.m_Lowest
=nRet
;
747 #if OSL_DEBUG_LEVEL > 1
750 fprintf(stderr
,"failed to get min sched param [%s]\n",strerror(errno
));
752 #endif /* OSL_DEBUG_LEVEL */
754 if ((nRet
= sched_get_priority_max(policy
) ) != -1)
756 OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy
,nRet
);
757 g_thread
.m_priority
.m_Highest
=nRet
;
759 #if OSL_DEBUG_LEVEL > 1
762 fprintf(stderr
,"failed to get max sched param [%s]\n",strerror(errno
));
764 #endif /* OSL_DEBUG_LEVEL */
766 g_thread
.m_priority
.m_Normal
=
767 (g_thread
.m_priority
.m_Lowest
+ g_thread
.m_priority
.m_Highest
) / 2;
768 g_thread
.m_priority
.m_Below_Normal
=
769 (g_thread
.m_priority
.m_Lowest
+ g_thread
.m_priority
.m_Normal
) / 2;
770 g_thread
.m_priority
.m_Above_Normal
=
771 (g_thread
.m_priority
.m_Normal
+ g_thread
.m_priority
.m_Highest
) / 2;
773 /* @@@ set prio of calling (not main) thread (?) @@@ */
775 param
.sched_priority
= g_thread
.m_priority
.m_Normal
;
777 if ((nRet
= pthread_setschedparam(pthread_self(), policy
, ¶m
)) != 0)
779 OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet
));
780 OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy
,param
.sched_priority
);
783 #endif /* NO_PTHREAD_PRIORITY */
786 /*****************************************************************************/
787 /* osl_setThreadPriority */
789 Impl-Notes: contrary to solaris-docu, which claims
790 valid priority-levels from 0 .. INT_MAX, only the
791 range 0..127 is accepted. (0 lowest, 127 highest)
793 /*****************************************************************************/
794 void SAL_CALL
osl_setThreadPriority (
796 oslThreadPriority Priority
)
798 #ifndef NO_PTHREAD_PRIORITY
800 struct sched_param Param
;
804 #endif /* NO_PTHREAD_PRIORITY */
806 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
812 #ifdef NO_PTHREAD_PRIORITY
813 (void) Priority
; /* unused */
814 #else /* NO_PTHREAD_PRIORITY */
816 if (pthread_getschedparam(pImpl
->m_hThread
, &policy
, &Param
) != 0)
819 #if defined (SOLARIS)
820 if ( policy
>= _SCHED_NEXT
)
822 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
823 /* one gets 959917873 as the policy */
824 /* so set the policy to a default one */
829 pthread_once (&(g_thread
.m_once
), osl_thread_init_Impl
);
833 case osl_Thread_PriorityHighest
:
834 Param
.sched_priority
= g_thread
.m_priority
.m_Highest
;
837 case osl_Thread_PriorityAboveNormal
:
838 Param
.sched_priority
= g_thread
.m_priority
.m_Above_Normal
;
841 case osl_Thread_PriorityNormal
:
842 Param
.sched_priority
= g_thread
.m_priority
.m_Normal
;
845 case osl_Thread_PriorityBelowNormal
:
846 Param
.sched_priority
= g_thread
.m_priority
.m_Below_Normal
;
849 case osl_Thread_PriorityLowest
:
850 Param
.sched_priority
= g_thread
.m_priority
.m_Lowest
;
853 case osl_Thread_PriorityUnknown
:
854 OSL_ASSERT(sal_False
); /* only fools try this...*/
856 /* let release-version behave friendly */
860 /* enum expanded, but forgotten here...*/
861 OSL_ENSURE(sal_False
,"osl_setThreadPriority : unknown priority\n");
863 /* let release-version behave friendly */
867 if ((nRet
= pthread_setschedparam(pImpl
->m_hThread
, policy
, &Param
)) != 0)
869 OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet
));
872 #endif /* NO_PTHREAD_PRIORITY */
875 /*****************************************************************************/
876 /* osl_getThreadPriority */
877 /*****************************************************************************/
878 oslThreadPriority SAL_CALL
osl_getThreadPriority(const oslThread Thread
)
880 #ifndef NO_PTHREAD_PRIORITY
882 struct sched_param Param
;
885 #endif /* NO_PTHREAD_PRIORITY */
887 oslThreadPriority Priority
= osl_Thread_PriorityNormal
;
888 Thread_Impl
* pImpl
= (Thread_Impl
*)Thread
;
892 return osl_Thread_PriorityUnknown
; /* EINVAL */
894 #ifndef NO_PTHREAD_PRIORITY
896 if (pthread_getschedparam(pImpl
->m_hThread
, &Policy
, &Param
) != 0)
897 return osl_Thread_PriorityUnknown
; /* ESRCH */
899 pthread_once (&(g_thread
.m_once
), osl_thread_init_Impl
);
901 /* map pthread priority to enum */
902 if (Param
.sched_priority
==g_thread
.m_priority
.m_Highest
)
905 Priority
= osl_Thread_PriorityHighest
;
907 else if (Param
.sched_priority
> g_thread
.m_priority
.m_Normal
)
909 /* 65..126 - above normal */
910 Priority
= osl_Thread_PriorityAboveNormal
;
912 else if (Param
.sched_priority
== g_thread
.m_priority
.m_Normal
)
915 Priority
= osl_Thread_PriorityNormal
;
917 else if (Param
.sched_priority
> g_thread
.m_priority
.m_Lowest
)
919 /* 63..1 -below normal */
920 Priority
= osl_Thread_PriorityBelowNormal
;
922 else if (Param
.sched_priority
== g_thread
.m_priority
.m_Lowest
)
925 Priority
= osl_Thread_PriorityLowest
;
930 Priority
= osl_Thread_PriorityUnknown
;
933 #endif /* NO_PTHREAD_PRIORITY */
938 /*****************************************************************************/
939 /* osl_createThreadKey */
940 /*****************************************************************************/
941 oslThreadKey SAL_CALL
osl_createThreadKey( oslThreadKeyCallbackFunction pCallback
)
945 if (pthread_key_create(&key
, pCallback
) != 0)
948 return ((oslThreadKey
)key
);
951 /*****************************************************************************/
952 /* osl_destroyThreadKey */
953 /*****************************************************************************/
954 void SAL_CALL
osl_destroyThreadKey(oslThreadKey Key
)
956 pthread_key_delete((pthread_key_t
)Key
);
959 /*****************************************************************************/
960 /* osl_getThreadKeyData */
961 /*****************************************************************************/
962 void* SAL_CALL
osl_getThreadKeyData(oslThreadKey Key
)
964 return (pthread_getspecific((pthread_key_t
)Key
));
967 /*****************************************************************************/
968 /* osl_setThreadKeyData */
969 /*****************************************************************************/
970 sal_Bool SAL_CALL
osl_setThreadKeyData(oslThreadKey Key
, void *pData
)
972 return (pthread_setspecific((pthread_key_t
)Key
, pData
) == 0);
975 /*****************************************************************************/
976 /* Thread Local Text Encoding */
977 /*****************************************************************************/
978 static void osl_thread_textencoding_init_Impl (void)
980 rtl_TextEncoding defaultEncoding
;
981 const char * pszEncoding
;
983 /* create thread specific data key */
984 pthread_key_create (&(g_thread
.m_textencoding
.m_key
), NULL
);
986 /* determine default text encoding */
987 pszEncoding
= getenv ("SOLAR_USER_RTL_TEXTENCODING");
989 defaultEncoding
= atoi(pszEncoding
);
991 defaultEncoding
= osl_getTextEncodingFromLocale(NULL
);
993 OSL_ASSERT(defaultEncoding
!= RTL_TEXTENCODING_DONTKNOW
);
996 Tools string functions call abort() on an unknown encoding so ASCII
997 is a meaningfull fallback regardless wether the assertion makes sense.
1000 if ( RTL_TEXTENCODING_DONTKNOW
== defaultEncoding
)
1001 defaultEncoding
= RTL_TEXTENCODING_ASCII_US
;
1003 g_thread
.m_textencoding
.m_default
= defaultEncoding
;
1006 /*****************************************************************************/
1007 /* osl_getThreadTextEncoding */
1008 /*****************************************************************************/
1009 rtl_TextEncoding SAL_CALL
osl_getThreadTextEncoding()
1011 rtl_TextEncoding threadEncoding
;
1013 pthread_once (&(g_thread
.m_once
), osl_thread_init_Impl
);
1015 /* check for thread specific encoding, use default if not set */
1016 threadEncoding
= SAL_INT_CAST(
1018 (sal_uIntPtr
) pthread_getspecific(g_thread
.m_textencoding
.m_key
));
1019 if (0 == threadEncoding
)
1020 threadEncoding
= g_thread
.m_textencoding
.m_default
;
1022 return threadEncoding
;
1025 /*****************************************************************************/
1026 /* osl_setThreadTextEncoding */
1027 /*****************************************************************************/
1028 rtl_TextEncoding
osl_setThreadTextEncoding(rtl_TextEncoding Encoding
)
1030 rtl_TextEncoding oldThreadEncoding
= osl_getThreadTextEncoding();
1032 /* save encoding in thread local storage */
1033 pthread_setspecific (
1034 g_thread
.m_textencoding
.m_key
,
1035 (void*) SAL_INT_CAST(sal_uIntPtr
, Encoding
));
1037 return oldThreadEncoding
;