merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / unx / thread.c
blobbe98358bb2668077e1ea00c78e7535dcbf709cd6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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 ************************************************************************/
31 #include "system.h"
32 #include <string.h>
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>
38 #endif
40 /****************************************************************************
41 * @@@ TODO @@@
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
74 pthread_t m_hThread;
75 sal_uInt16 m_Ident; /* @@@ see TODO @@@ */
76 short m_Flags;
77 oslWorkerFunction m_WorkerFunction;
78 void* m_pData;
79 pthread_mutex_t m_Lock;
80 pthread_cond_t m_Cond;
81 } Thread_Impl;
83 struct osl_thread_priority_st
85 int m_Highest;
86 int m_Above_Normal;
87 int m_Normal;
88 int m_Below_Normal;
89 int m_Lowest;
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 =
113 PTHREAD_ONCE_INIT,
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));
170 if (pImpl)
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);
177 return (pImpl);
180 /*****************************************************************************/
181 /* osl_thread_destruct_Impl */
182 /*****************************************************************************/
183 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl)
185 OSL_ASSERT(ppImpl);
186 if (*ppImpl)
188 pthread_cond_destroy (&((*ppImpl)->m_Cond));
189 pthread_mutex_destroy (&((*ppImpl)->m_Lock));
191 free (*ppImpl);
192 (*ppImpl) = 0;
196 /*****************************************************************************/
197 /* osl_thread_cleanup_Impl */
198 /*****************************************************************************/
199 static void osl_thread_cleanup_Impl (void* pData)
201 pthread_t thread;
202 int attached;
203 int destroyed;
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);
218 if (attached)
220 pthread_detach (thread);
223 if (destroyed)
225 osl_thread_destruct_Impl (&pImpl);
229 /*****************************************************************************/
230 /* osl_thread_start_Impl */
231 /*****************************************************************************/
232 static void* osl_thread_start_Impl (void* pData)
234 int terminate;
235 Thread_Impl* pImpl= (Thread_Impl*)pData;
237 OSL_ASSERT(pImpl);
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));
266 if (!terminate)
268 /* call worker function */
269 pImpl->m_WorkerFunction(pImpl->m_pData);
272 /* call cleanup handler and leave */
273 pthread_cleanup_pop (1);
274 return (0);
277 /*****************************************************************************/
278 /* osl_thread_create_Impl */
279 /*****************************************************************************/
280 static oslThread osl_thread_create_Impl (
281 oslWorkerFunction pWorker,
282 void* pThreadData,
283 short nFlags)
285 Thread_Impl* pImpl;
286 int nRet=0;
288 pImpl = osl_thread_construct_Impl();
289 if (!pImpl)
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 (
299 &(pImpl->m_hThread),
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);
310 return (0);
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,
332 void * pThreadData)
334 return osl_thread_create_Impl (
335 pWorker,
336 pThreadData,
337 THREADIMPL_FLAGS_ATTACHED);
340 /*****************************************************************************/
341 /* osl_createSuspendedThread */
342 /*****************************************************************************/
343 oslThread osl_createSuspendedThread (
344 oslWorkerFunction pWorker,
345 void * pThreadData)
347 return osl_thread_create_Impl (
348 pWorker,
349 pThreadData,
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;
361 int active;
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);
366 if (!active) {
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;
379 OSL_ASSERT(pImpl);
380 if (!pImpl)
381 return; /* EINVAL */
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;
402 OSL_ASSERT(pImpl);
403 if (!pImpl)
404 return; /* EINVAL */
406 pthread_mutex_lock (&(pImpl->m_Lock));
408 pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
410 if (pthread_equal (pthread_self(), pImpl->m_hThread))
412 /* self suspend */
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)
430 sal_Bool active;
431 Thread_Impl* pImpl= (Thread_Impl*)Thread;
433 if (!pImpl)
434 return sal_False;
436 pthread_mutex_lock (&(pImpl->m_Lock));
437 active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
438 pthread_mutex_unlock (&(pImpl->m_Lock));
440 return (active);
443 /*****************************************************************************/
444 /* osl_joinWithThread */
445 /*****************************************************************************/
446 void SAL_CALL osl_joinWithThread(oslThread Thread)
448 pthread_t thread;
449 int attached;
450 Thread_Impl* pImpl= (Thread_Impl*)Thread;
452 if (!pImpl)
453 return;
455 pthread_mutex_lock (&(pImpl->m_Lock));
457 if (pthread_equal (pthread_self(), pImpl->m_hThread))
459 /* self join */
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));
470 if (attached)
472 /* install cleanup handler to ensure consistent flags and state */
473 pthread_cleanup_push (
474 osl_thread_join_cleanup_Impl, (void*)thread);
476 /* join */
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;
491 OSL_ASSERT(pImpl);
492 if (!pImpl)
493 return; /* EINVAL */
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)
514 int terminate;
515 Thread_Impl* pImpl= (Thread_Impl*)Thread;
517 OSL_ASSERT(pImpl);
518 if (!pImpl)
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 /*****************************************************************************/
545 /* osl_waitThread */
546 /*****************************************************************************/
547 void SAL_CALL osl_waitThread(const TimeValue* pDelay)
549 if (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()
569 sched_yield();
572 /*****************************************************************************/
573 /* osl_getThreadIdentifier @@@ see TODO @@@ */
574 /*****************************************************************************/
576 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
578 typedef struct _HashEntry
580 pthread_t Handle;
581 sal_uInt16 Ident;
582 struct _HashEntry *Next;
583 } HashEntry;
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)
594 HashEntry *pEntry;
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);
611 return (0);
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))
625 break;
627 pInsert = pEntry;
628 pEntry = pEntry->Next;
631 if (pEntry == NULL)
633 pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
635 pEntry->Handle = hThread;
637 ++ LastIdent;
639 if ( LastIdent == 0 )
640 LastIdent = 1;
642 pEntry->Ident = LastIdent;
644 if (pInsert)
645 pInsert->Next = pEntry;
646 else
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))
665 break;
667 pRemove = pEntry;
668 pEntry = pEntry->Next;
671 if (pEntry != NULL)
673 if (pRemove)
674 pRemove->Next = pEntry->Next;
675 else
676 HashTable[HASHID(hThread)] = pEntry->Next;
678 free(pEntry);
681 pthread_mutex_unlock(&HashLock);
684 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
686 Thread_Impl* pImpl= (Thread_Impl*)Thread;
687 sal_uInt16 Ident;
689 if (pImpl)
690 Ident = pImpl->m_Ident;
691 else
693 /* current thread */
694 pthread_t current = pthread_self();
696 Ident = lookupThreadId (current);
697 if (Ident == 0)
698 /* @@@ see TODO: alien pthread_self() @@@ */
699 Ident = insertThreadId (current);
702 return ((oslThreadIdentifier)(Ident));
705 /*****************************************************************************
706 @@@ see TODO @@@
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;
721 int policy=0;
722 int nRet=0;
724 /* @@@ see TODO: calling thread may not be main thread @@@ */
726 if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
728 OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet));
729 return;
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 */
738 policy=SCHED_OTHER;
740 #endif /* SOLARIS */
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
748 else
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
760 else
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, &param)) != 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 (
795 oslThread Thread,
796 oslThreadPriority Priority)
798 #ifndef NO_PTHREAD_PRIORITY
800 struct sched_param Param;
801 int policy;
802 int nRet;
804 #endif /* NO_PTHREAD_PRIORITY */
806 Thread_Impl* pImpl= (Thread_Impl*)Thread;
808 OSL_ASSERT(pImpl);
809 if (!pImpl)
810 return; /* EINVAL */
812 #ifdef NO_PTHREAD_PRIORITY
813 (void) Priority; /* unused */
814 #else /* NO_PTHREAD_PRIORITY */
816 if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
817 return; /* ESRCH */
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 */
825 policy=SCHED_OTHER;
827 #endif /* SOLARIS */
829 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
831 switch(Priority)
833 case osl_Thread_PriorityHighest:
834 Param.sched_priority= g_thread.m_priority.m_Highest;
835 break;
837 case osl_Thread_PriorityAboveNormal:
838 Param.sched_priority= g_thread.m_priority.m_Above_Normal;
839 break;
841 case osl_Thread_PriorityNormal:
842 Param.sched_priority= g_thread.m_priority.m_Normal;
843 break;
845 case osl_Thread_PriorityBelowNormal:
846 Param.sched_priority= g_thread.m_priority.m_Below_Normal;
847 break;
849 case osl_Thread_PriorityLowest:
850 Param.sched_priority= g_thread.m_priority.m_Lowest;
851 break;
853 case osl_Thread_PriorityUnknown:
854 OSL_ASSERT(sal_False); /* only fools try this...*/
856 /* let release-version behave friendly */
857 return;
859 default:
860 /* enum expanded, but forgotten here...*/
861 OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
863 /* let release-version behave friendly */
864 return;
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;
883 int Policy;
885 #endif /* NO_PTHREAD_PRIORITY */
887 oslThreadPriority Priority = osl_Thread_PriorityNormal;
888 Thread_Impl* pImpl= (Thread_Impl*)Thread;
890 OSL_ASSERT(pImpl);
891 if (!pImpl)
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)
904 /* 127 - 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)
914 /* 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)
924 /* 0 - lowest */
925 Priority= osl_Thread_PriorityLowest;
927 else
929 /* unknown */
930 Priority= osl_Thread_PriorityUnknown;
933 #endif /* NO_PTHREAD_PRIORITY */
935 return Priority;
938 /*****************************************************************************/
939 /* osl_createThreadKey */
940 /*****************************************************************************/
941 oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
943 pthread_key_t key;
945 if (pthread_key_create(&key, pCallback) != 0)
946 key = 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");
988 if (pszEncoding)
989 defaultEncoding = atoi(pszEncoding);
990 else
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(
1017 rtl_TextEncoding,
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;