Bump for 3.6-28
[LibreOffice.git] / sal / osl / unx / thread.c
blobd97855825c1de486f5f4871ad7c785d14c095480
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "system.h"
30 #include <string.h>
31 #if defined(OPENBSD)
32 #include <sched.h>
33 #endif
34 #include <osl/diagnose.h>
35 #include <osl/thread.h>
36 #include <osl/nlsupport.h>
37 #include <rtl/textenc.h>
38 #include <rtl/alloc.h>
39 #include <sal/macros.h>
40 #ifdef ANDROID
41 #include <jni.h>
42 #include <osl/detail/android-bootstrap.h>
43 #endif
45 #if defined LINUX && ! defined __FreeBSD_kernel__
46 #include <sys/prctl.h>
47 #ifndef PR_SET_NAME
48 #define PR_SET_NAME 15
49 #endif
50 #endif
52 /****************************************************************************
53 * @@@ TODO @@@
55 * (1) 'osl_thread_priority_init_Impl()'
56 * - insane assumption that initializing caller is main thread
57 * - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?)
58 * - POSIX doesn't require defined prio's for SCHED_OTHER (!)
59 * - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?)
60 * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()'
61 * - cannot reliably be applied to 'alien' threads;
62 * - memory leak for 'alien' thread 'HashEntry's;
63 * - use 'PTHREAD_VALUE(pthread_t)' as identifier instead (?)
64 * - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar
65 * (3) 'oslSigAlarmHandler()' (#71232#)
66 * - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates
67 * the process. So we initialize our signal handling module and do
68 * register a SIGALRM Handler which catches and ignores it]
69 * - should this still happen, 'signal.c' needs to be fixed instead.
71 ****************************************************************************/
73 /*****************************************************************************/
74 /* Internal data structures and functions */
75 /*****************************************************************************/
77 #define THREADIMPL_FLAGS_TERMINATE 0x00001
78 #define THREADIMPL_FLAGS_STARTUP 0x00002
79 #define THREADIMPL_FLAGS_SUSPENDED 0x00004
80 #define THREADIMPL_FLAGS_ACTIVE 0x00008
81 #define THREADIMPL_FLAGS_ATTACHED 0x00010
82 #define THREADIMPL_FLAGS_DESTROYED 0x00020
84 typedef struct osl_thread_impl_st
86 pthread_t m_hThread;
87 sal_uInt16 m_Ident; /* @@@ see TODO @@@ */
88 short m_Flags;
89 oslWorkerFunction m_WorkerFunction;
90 void* m_pData;
91 pthread_mutex_t m_Lock;
92 pthread_cond_t m_Cond;
93 } Thread_Impl;
95 struct osl_thread_priority_st
97 int m_Highest;
98 int m_Above_Normal;
99 int m_Normal;
100 int m_Below_Normal;
101 int m_Lowest;
104 #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
105 static void osl_thread_priority_init_Impl (void);
107 struct osl_thread_textencoding_st
109 pthread_key_t m_key; /* key to store thread local text encoding */
110 rtl_TextEncoding m_default; /* the default text encoding */
113 #define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW }
114 static void osl_thread_textencoding_init_Impl (void);
116 struct osl_thread_global_st
118 pthread_once_t m_once;
119 struct osl_thread_priority_st m_priority;
120 struct osl_thread_textencoding_st m_textencoding;
123 static struct osl_thread_global_st g_thread =
125 PTHREAD_ONCE_INIT,
126 OSL_THREAD_PRIORITY_INITIALIZER,
127 OSL_THREAD_TEXTENCODING_INITIALIZER
130 static void osl_thread_init_Impl (void);
132 static Thread_Impl* osl_thread_construct_Impl (void);
133 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl);
135 static void* osl_thread_start_Impl (void * pData);
136 static void osl_thread_cleanup_Impl (Thread_Impl * pImpl);
138 static oslThread osl_thread_create_Impl (
139 oslWorkerFunction pWorker, void * pThreadData, short nFlags);
141 /* @@@ see TODO @@@ */
142 static sal_uInt16 insertThreadId (pthread_t hThread);
143 static sal_uInt16 lookupThreadId (pthread_t hThread);
144 static void removeThreadId (pthread_t hThread);
146 /*****************************************************************************/
147 /* osl_thread_init_Impl */
148 /*****************************************************************************/
149 static void osl_thread_init_Impl (void)
151 osl_thread_priority_init_Impl();
152 osl_thread_textencoding_init_Impl();
155 /*****************************************************************************/
156 /* osl_thread_construct_Impl */
157 /*****************************************************************************/
158 Thread_Impl* osl_thread_construct_Impl (void)
160 Thread_Impl* pImpl = malloc (sizeof(Thread_Impl));
161 if (pImpl)
163 memset (pImpl, 0, sizeof(Thread_Impl));
165 pthread_mutex_init (&(pImpl->m_Lock), PTHREAD_MUTEXATTR_DEFAULT);
166 pthread_cond_init (&(pImpl->m_Cond), PTHREAD_CONDATTR_DEFAULT);
168 return (pImpl);
171 /*****************************************************************************/
172 /* osl_thread_destruct_Impl */
173 /*****************************************************************************/
174 static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl)
176 OSL_ASSERT(ppImpl);
177 if (*ppImpl)
179 pthread_cond_destroy (&((*ppImpl)->m_Cond));
180 pthread_mutex_destroy (&((*ppImpl)->m_Lock));
182 free (*ppImpl);
183 (*ppImpl) = 0;
187 /*****************************************************************************/
188 /* osl_thread_cleanup_Impl */
189 /*****************************************************************************/
190 static void osl_thread_cleanup_Impl (Thread_Impl * pImpl)
192 pthread_t thread;
193 int attached;
194 int destroyed;
196 pthread_mutex_lock (&(pImpl->m_Lock));
198 thread = pImpl->m_hThread;
199 attached = (pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) != 0;
200 destroyed = (pImpl->m_Flags & THREADIMPL_FLAGS_DESTROYED) != 0;
201 pImpl->m_Flags &= ~(THREADIMPL_FLAGS_ACTIVE | THREADIMPL_FLAGS_ATTACHED);
203 pthread_mutex_unlock (&(pImpl->m_Lock));
205 /* release oslThreadIdentifier @@@ see TODO @@@ */
206 removeThreadId (thread);
208 if (attached)
210 pthread_detach (thread);
213 if (destroyed)
215 osl_thread_destruct_Impl (&pImpl);
219 /*****************************************************************************/
220 /* osl_thread_start_Impl */
221 /*****************************************************************************/
222 static void* osl_thread_start_Impl (void* pData)
224 int terminate;
225 Thread_Impl* pImpl= (Thread_Impl*)pData;
227 OSL_ASSERT(pImpl);
229 pthread_mutex_lock (&(pImpl->m_Lock));
231 /* request oslThreadIdentifier @@@ see TODO @@@ */
232 pImpl->m_Ident = insertThreadId (pImpl->m_hThread);
234 /* signal change from STARTUP to ACTIVE state */
235 pImpl->m_Flags &= ~THREADIMPL_FLAGS_STARTUP;
236 pImpl->m_Flags |= THREADIMPL_FLAGS_ACTIVE;
237 pthread_cond_signal (&(pImpl->m_Cond));
239 /* Check if thread is started in SUSPENDED state */
240 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
242 /* wait until SUSPENDED flag is cleared */
243 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
246 /* check for SUSPENDED to TERMINATE state change */
247 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
249 pthread_mutex_unlock (&(pImpl->m_Lock));
251 if (!terminate)
253 #ifdef ANDROID
255 JNIEnv* env = 0;
256 int res = (*lo_get_javavm())->AttachCurrentThread(lo_get_javavm(), &env, NULL); // res == 0
257 fprintf (stderr, "new sal thread started and attached %d!\n", res);
259 #endif
260 /* call worker function */
261 pImpl->m_WorkerFunction(pImpl->m_pData);
263 #ifdef ANDROID
265 int res = (*lo_get_javavm())->DetachCurrentThread(lo_get_javavm());
266 fprintf (stderr, "detached finished sal thread %d!\n", res);
268 #endif
271 osl_thread_cleanup_Impl (pImpl);
272 return (0);
275 /*****************************************************************************/
276 /* osl_thread_create_Impl */
277 /*****************************************************************************/
278 static oslThread osl_thread_create_Impl (
279 oslWorkerFunction pWorker,
280 void* pThreadData,
281 short nFlags)
283 Thread_Impl* pImpl;
284 #if defined(OPENBSD)
285 pthread_attr_t attr;
286 #endif
287 int nRet=0;
289 pImpl = osl_thread_construct_Impl();
290 if (!pImpl)
291 return (0); /* ENOMEM */
293 pImpl->m_WorkerFunction = pWorker;
294 pImpl->m_pData = pThreadData;
295 pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP;
297 pthread_mutex_lock (&(pImpl->m_Lock));
299 #if defined(OPENBSD)
300 if (pthread_attr_init(&attr) != 0)
301 return (0);
303 if (pthread_attr_setstacksize(&attr, 262144) != 0) {
304 pthread_attr_destroy(&attr);
305 return (0);
307 #endif
309 if ((nRet = pthread_create (
310 &(pImpl->m_hThread),
311 #if defined(OPENBSD)
312 &attr,
313 #else
314 PTHREAD_ATTR_DEFAULT,
315 #endif
316 osl_thread_start_Impl,
317 (void*)(pImpl))) != 0)
319 OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n",
320 nRet, strerror(nRet));
322 pthread_mutex_unlock (&(pImpl->m_Lock));
323 osl_thread_destruct_Impl (&pImpl);
325 return (0);
328 #if defined(OPENBSD)
329 pthread_attr_destroy(&attr);
330 #endif
332 /* wait for change from STARTUP to ACTIVE state */
333 while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP)
335 /* wait until STARTUP flag is cleared */
336 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
339 pthread_mutex_unlock (&(pImpl->m_Lock));
341 return ((oslThread)(pImpl));
344 /*****************************************************************************/
345 /* osl_createThread */
346 /*****************************************************************************/
347 oslThread osl_createThread (
348 oslWorkerFunction pWorker,
349 void * pThreadData)
351 return osl_thread_create_Impl (
352 pWorker,
353 pThreadData,
354 THREADIMPL_FLAGS_ATTACHED);
357 /*****************************************************************************/
358 /* osl_createSuspendedThread */
359 /*****************************************************************************/
360 oslThread osl_createSuspendedThread (
361 oslWorkerFunction pWorker,
362 void * pThreadData)
364 return osl_thread_create_Impl (
365 pWorker,
366 pThreadData,
367 THREADIMPL_FLAGS_ATTACHED |
368 THREADIMPL_FLAGS_SUSPENDED );
371 /*****************************************************************************/
372 /* osl_destroyThread */
373 /*****************************************************************************/
374 void SAL_CALL osl_destroyThread(oslThread Thread)
376 if (Thread != NULL) {
377 Thread_Impl * impl = (Thread_Impl *) Thread;
378 int active;
379 pthread_mutex_lock(&impl->m_Lock);
380 active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0;
381 impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED;
382 pthread_mutex_unlock(&impl->m_Lock);
383 if (!active) {
384 osl_thread_destruct_Impl(&impl);
389 /*****************************************************************************/
390 /* osl_resumeThread */
391 /*****************************************************************************/
392 void SAL_CALL osl_resumeThread(oslThread Thread)
394 Thread_Impl* pImpl= (Thread_Impl*)Thread;
396 OSL_ASSERT(pImpl);
397 if (!pImpl)
398 return; /* EINVAL */
400 pthread_mutex_lock (&(pImpl->m_Lock));
402 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
404 /* clear SUSPENDED flag */
405 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
406 pthread_cond_signal (&(pImpl->m_Cond));
409 pthread_mutex_unlock (&(pImpl->m_Lock));
412 /*****************************************************************************/
413 /* osl_suspendThread */
414 /*****************************************************************************/
415 void SAL_CALL osl_suspendThread(oslThread Thread)
417 Thread_Impl* pImpl= (Thread_Impl*)Thread;
419 OSL_ASSERT(pImpl);
420 if (!pImpl)
421 return; /* EINVAL */
423 pthread_mutex_lock (&(pImpl->m_Lock));
425 pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
427 if (pthread_equal (pthread_self(), pImpl->m_hThread))
429 /* self suspend */
430 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
432 /* wait until SUSPENDED flag is cleared */
433 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
437 pthread_mutex_unlock (&(pImpl->m_Lock));
440 /*****************************************************************************/
441 /* osl_isThreadRunning */
442 /*****************************************************************************/
443 sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
445 sal_Bool active;
446 Thread_Impl* pImpl= (Thread_Impl*)Thread;
448 if (!pImpl)
449 return sal_False;
451 pthread_mutex_lock (&(pImpl->m_Lock));
452 active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
453 pthread_mutex_unlock (&(pImpl->m_Lock));
455 return (active);
458 /*****************************************************************************/
459 /* osl_joinWithThread */
460 /*****************************************************************************/
461 void SAL_CALL osl_joinWithThread(oslThread Thread)
463 pthread_t thread;
464 int attached;
465 Thread_Impl* pImpl= (Thread_Impl*)Thread;
467 if (!pImpl)
468 return;
470 pthread_mutex_lock (&(pImpl->m_Lock));
472 if (pthread_equal (pthread_self(), pImpl->m_hThread))
474 /* self join */
475 pthread_mutex_unlock (&(pImpl->m_Lock));
476 return; /* EDEADLK */
479 thread = pImpl->m_hThread;
480 attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0);
481 pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED;
483 pthread_mutex_unlock (&(pImpl->m_Lock));
485 if (attached)
487 pthread_join (thread, NULL);
491 /*****************************************************************************/
492 /* osl_terminateThread */
493 /*****************************************************************************/
494 void SAL_CALL osl_terminateThread(oslThread Thread)
496 Thread_Impl* pImpl= (Thread_Impl*)Thread;
498 OSL_ASSERT(pImpl);
499 if (!pImpl)
500 return; /* EINVAL */
502 pthread_mutex_lock (&(pImpl->m_Lock));
504 if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
506 /* clear SUSPENDED flag */
507 pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
508 pthread_cond_signal (&(pImpl->m_Cond));
511 pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
513 pthread_mutex_unlock (&(pImpl->m_Lock));
516 /*****************************************************************************/
517 /* osl_scheduleThread */
518 /*****************************************************************************/
519 sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
521 int terminate;
522 Thread_Impl* pImpl= (Thread_Impl*)Thread;
524 OSL_ASSERT(pImpl);
525 if (!pImpl)
526 return sal_False; /* EINVAL */
528 OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread));
529 if (!(pthread_equal (pthread_self(), pImpl->m_hThread)))
530 return sal_False; /* EINVAL */
532 pthread_mutex_lock (&(pImpl->m_Lock));
534 while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
536 /* wait until SUSPENDED flag is cleared */
537 pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
540 terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
542 pthread_mutex_unlock(&(pImpl->m_Lock));
544 return (terminate == 0);
547 /*****************************************************************************/
548 /* osl_waitThread */
549 /*****************************************************************************/
550 void SAL_CALL osl_waitThread(const TimeValue* pDelay)
552 if (pDelay)
554 struct timespec delay;
556 SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec);
558 SLEEP_TIMESPEC(delay);
562 /*****************************************************************************/
563 /* osl_yieldThread */
565 Note that POSIX scheduling _really_ requires threads to call this
566 functions, since a thread only reschedules to other thread, when
567 it blocks (sleep, blocking I/O) OR calls sched_yield().
569 /*****************************************************************************/
570 void SAL_CALL osl_yieldThread()
572 sched_yield();
575 void SAL_CALL osl_setThreadName(char const * name) {
576 #if defined LINUX && ! defined __FreeBSD_kernel__
577 if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) {
578 OSL_TRACE(
579 "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX,
580 errno);
582 #else
583 (void) name;
584 #endif
587 /*****************************************************************************/
588 /* osl_getThreadIdentifier @@@ see TODO @@@ */
589 /*****************************************************************************/
591 #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
593 typedef struct _HashEntry
595 pthread_t Handle;
596 sal_uInt16 Ident;
597 struct _HashEntry *Next;
598 } HashEntry;
600 static HashEntry* HashTable[31];
601 static int HashSize = SAL_N_ELEMENTS(HashTable);
603 static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER;
605 static sal_uInt16 LastIdent = 0;
607 static sal_uInt16 lookupThreadId (pthread_t hThread)
609 HashEntry *pEntry;
611 pthread_mutex_lock(&HashLock);
613 pEntry = HashTable[HASHID(hThread)];
614 while (pEntry != NULL)
616 if (pthread_equal(pEntry->Handle, hThread))
618 pthread_mutex_unlock(&HashLock);
619 return (pEntry->Ident);
621 pEntry = pEntry->Next;
624 pthread_mutex_unlock(&HashLock);
626 return (0);
629 static sal_uInt16 insertThreadId (pthread_t hThread)
631 HashEntry *pEntry, *pInsert = NULL;
633 pthread_mutex_lock(&HashLock);
635 pEntry = HashTable[HASHID(hThread)];
637 while (pEntry != NULL)
639 if (pthread_equal(pEntry->Handle, hThread))
640 break;
642 pInsert = pEntry;
643 pEntry = pEntry->Next;
646 if (pEntry == NULL)
648 pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
650 pEntry->Handle = hThread;
652 ++ LastIdent;
654 if ( LastIdent == 0 )
655 LastIdent = 1;
657 pEntry->Ident = LastIdent;
659 if (pInsert)
660 pInsert->Next = pEntry;
661 else
662 HashTable[HASHID(hThread)] = pEntry;
665 pthread_mutex_unlock(&HashLock);
667 return (pEntry->Ident);
670 static void removeThreadId (pthread_t hThread)
672 HashEntry *pEntry, *pRemove = NULL;
674 pthread_mutex_lock(&HashLock);
676 pEntry = HashTable[HASHID(hThread)];
677 while (pEntry != NULL)
679 if (pthread_equal(pEntry->Handle, hThread))
680 break;
682 pRemove = pEntry;
683 pEntry = pEntry->Next;
686 if (pEntry != NULL)
688 if (pRemove)
689 pRemove->Next = pEntry->Next;
690 else
691 HashTable[HASHID(hThread)] = pEntry->Next;
693 free(pEntry);
696 pthread_mutex_unlock(&HashLock);
699 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
701 Thread_Impl* pImpl= (Thread_Impl*)Thread;
702 sal_uInt16 Ident;
704 if (pImpl)
705 Ident = pImpl->m_Ident;
706 else
708 /* current thread */
709 pthread_t current = pthread_self();
711 Ident = lookupThreadId (current);
712 if (Ident == 0)
713 /* @@@ see TODO: alien pthread_self() @@@ */
714 Ident = insertThreadId (current);
717 return ((oslThreadIdentifier)(Ident));
720 /*****************************************************************************
721 @@@ see TODO @@@
722 osl_thread_priority_init_Impl
724 set the base-priority of the main-thread to
725 oslThreadPriorityNormal (64) since 0 (lowest) is
726 the system default. This behaviour collides with
727 our enum-priority definition (highest..normal..lowest).
728 A normaluser will expect the main-thread of an app.
729 to have the "normal" priority.
731 *****************************************************************************/
732 static void osl_thread_priority_init_Impl (void)
734 #ifndef NO_PTHREAD_PRIORITY
735 struct sched_param param;
736 int policy=0;
737 int nRet=0;
739 /* @@@ see TODO: calling thread may not be main thread @@@ */
741 if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
743 OSL_TRACE("failed to get priority of thread [%s]",strerror(nRet));
744 return;
747 #if defined (SOLARIS)
748 if ( policy >= _SCHED_NEXT)
750 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
751 /* one gets 959917873 as the policy */
752 /* so set the policy to a default one */
753 policy=SCHED_OTHER;
755 #endif /* SOLARIS */
757 if ((nRet = sched_get_priority_min(policy) ) != -1)
759 OSL_TRACE("Min Prioriy for policy '%i' == '%i'",policy,nRet);
760 g_thread.m_priority.m_Lowest=nRet;
762 #if OSL_DEBUG_LEVEL > 1
763 else
765 fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
767 #endif /* OSL_DEBUG_LEVEL */
769 if ((nRet = sched_get_priority_max(policy) ) != -1)
771 OSL_TRACE("Max Prioriy for policy '%i' == '%i'",policy,nRet);
772 g_thread.m_priority.m_Highest=nRet;
774 #if OSL_DEBUG_LEVEL > 1
775 else
777 fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
779 #endif /* OSL_DEBUG_LEVEL */
781 g_thread.m_priority.m_Normal =
782 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2;
783 g_thread.m_priority.m_Below_Normal =
784 (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2;
785 g_thread.m_priority.m_Above_Normal =
786 (g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2;
788 /* @@@ set prio of calling (not main) thread (?) @@@ */
790 param.sched_priority= g_thread.m_priority.m_Normal;
792 if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
794 OSL_TRACE("failed to change base priority of thread [%s]",strerror(nRet));
795 OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority);
798 #endif /* NO_PTHREAD_PRIORITY */
801 /*****************************************************************************/
802 /* osl_setThreadPriority */
804 Impl-Notes: contrary to solaris-docu, which claims
805 valid priority-levels from 0 .. INT_MAX, only the
806 range 0..127 is accepted. (0 lowest, 127 highest)
808 /*****************************************************************************/
809 void SAL_CALL osl_setThreadPriority (
810 oslThread Thread,
811 oslThreadPriority Priority)
813 #ifndef NO_PTHREAD_PRIORITY
815 struct sched_param Param;
816 int policy;
817 int nRet;
819 #endif /* NO_PTHREAD_PRIORITY */
821 Thread_Impl* pImpl= (Thread_Impl*)Thread;
823 OSL_ASSERT(pImpl);
824 if (!pImpl)
825 return; /* EINVAL */
827 #ifdef NO_PTHREAD_PRIORITY
828 (void) Priority; /* unused */
829 #else /* NO_PTHREAD_PRIORITY */
831 if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
832 return; /* ESRCH */
834 #if defined (SOLARIS)
835 if ( policy >= _SCHED_NEXT)
837 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
838 /* one gets 959917873 as the policy */
839 /* so set the policy to a default one */
840 policy=SCHED_OTHER;
842 #endif /* SOLARIS */
844 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
846 switch(Priority)
848 case osl_Thread_PriorityHighest:
849 Param.sched_priority= g_thread.m_priority.m_Highest;
850 break;
852 case osl_Thread_PriorityAboveNormal:
853 Param.sched_priority= g_thread.m_priority.m_Above_Normal;
854 break;
856 case osl_Thread_PriorityNormal:
857 Param.sched_priority= g_thread.m_priority.m_Normal;
858 break;
860 case osl_Thread_PriorityBelowNormal:
861 Param.sched_priority= g_thread.m_priority.m_Below_Normal;
862 break;
864 case osl_Thread_PriorityLowest:
865 Param.sched_priority= g_thread.m_priority.m_Lowest;
866 break;
868 case osl_Thread_PriorityUnknown:
869 OSL_ASSERT(sal_False); /* only fools try this...*/
871 /* let release-version behave friendly */
872 return;
874 default:
875 /* enum expanded, but forgotten here...*/
876 OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
878 /* let release-version behave friendly */
879 return;
882 if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
884 OSL_TRACE("failed to change thread priority [%s]",strerror(nRet));
887 #endif /* NO_PTHREAD_PRIORITY */
890 /*****************************************************************************/
891 /* osl_getThreadPriority */
892 /*****************************************************************************/
893 oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
895 #ifndef NO_PTHREAD_PRIORITY
897 struct sched_param Param;
898 int Policy;
900 #endif /* NO_PTHREAD_PRIORITY */
902 oslThreadPriority Priority = osl_Thread_PriorityNormal;
903 Thread_Impl* pImpl= (Thread_Impl*)Thread;
905 OSL_ASSERT(pImpl);
906 if (!pImpl)
907 return osl_Thread_PriorityUnknown; /* EINVAL */
909 #ifndef NO_PTHREAD_PRIORITY
911 if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0)
912 return osl_Thread_PriorityUnknown; /* ESRCH */
914 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
916 /* map pthread priority to enum */
917 if (Param.sched_priority==g_thread.m_priority.m_Highest)
919 /* 127 - highest */
920 Priority= osl_Thread_PriorityHighest;
922 else if (Param.sched_priority > g_thread.m_priority.m_Normal)
924 /* 65..126 - above normal */
925 Priority= osl_Thread_PriorityAboveNormal;
927 else if (Param.sched_priority == g_thread.m_priority.m_Normal)
929 /* normal */
930 Priority= osl_Thread_PriorityNormal;
932 else if (Param.sched_priority > g_thread.m_priority.m_Lowest)
934 /* 63..1 -below normal */
935 Priority= osl_Thread_PriorityBelowNormal;
937 else if (Param.sched_priority == g_thread.m_priority.m_Lowest)
939 /* 0 - lowest */
940 Priority= osl_Thread_PriorityLowest;
942 else
944 /* unknown */
945 Priority= osl_Thread_PriorityUnknown;
948 #endif /* NO_PTHREAD_PRIORITY */
950 return Priority;
953 typedef struct _wrapper_pthread_key
955 pthread_key_t m_key;
956 oslThreadKeyCallbackFunction pfnCallback;
957 } wrapper_pthread_key;
959 /*****************************************************************************/
960 /* osl_createThreadKey */
961 /*****************************************************************************/
962 oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
964 wrapper_pthread_key *pKey = (wrapper_pthread_key*)rtl_allocateMemory(sizeof(wrapper_pthread_key));
966 if (pKey)
968 pKey->pfnCallback = pCallback;
970 if (pthread_key_create(&(pKey->m_key), pKey->pfnCallback) != 0)
972 rtl_freeMemory(pKey);
973 pKey = 0;
977 return ((oslThreadKey)pKey);
980 /*****************************************************************************/
981 /* osl_destroyThreadKey */
982 /*****************************************************************************/
983 void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
985 wrapper_pthread_key *pKey = (wrapper_pthread_key*)Key;
986 if (pKey)
988 pthread_key_delete(pKey->m_key);
989 rtl_freeMemory(pKey);
993 /*****************************************************************************/
994 /* osl_getThreadKeyData */
995 /*****************************************************************************/
996 void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
998 wrapper_pthread_key *pKey = (wrapper_pthread_key*)Key;
999 return pKey ? pthread_getspecific(pKey->m_key) : NULL;
1002 /*****************************************************************************/
1003 /* osl_setThreadKeyData */
1004 /*****************************************************************************/
1005 sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
1007 sal_Bool bRet;
1008 void *pOldData = NULL;
1009 wrapper_pthread_key *pKey = (wrapper_pthread_key*)Key;
1010 if (!pKey)
1011 return sal_False;
1013 if (pKey->pfnCallback)
1014 pOldData = pthread_getspecific(pKey->m_key);
1016 bRet = (pthread_setspecific(pKey->m_key, pData) == 0);
1018 if (bRet && pKey->pfnCallback && pOldData)
1019 pKey->pfnCallback(pOldData);
1021 return bRet;
1024 /*****************************************************************************/
1025 /* Thread Local Text Encoding */
1026 /*****************************************************************************/
1027 static void osl_thread_textencoding_init_Impl (void)
1029 rtl_TextEncoding defaultEncoding;
1030 const char * pszEncoding;
1032 /* create thread specific data key */
1033 pthread_key_create (&(g_thread.m_textencoding.m_key), NULL);
1035 /* determine default text encoding */
1036 pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
1037 if (pszEncoding)
1038 defaultEncoding = atoi(pszEncoding);
1039 else
1040 defaultEncoding = osl_getTextEncodingFromLocale(NULL);
1042 OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
1045 Tools string functions call abort() on an unknown encoding so ASCII
1046 is a meaningfull fallback regardless wether the assertion makes sense.
1049 if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding )
1050 defaultEncoding = RTL_TEXTENCODING_ASCII_US;
1052 g_thread.m_textencoding.m_default = defaultEncoding;
1055 /*****************************************************************************/
1056 /* osl_getThreadTextEncoding */
1057 /*****************************************************************************/
1058 rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding()
1060 rtl_TextEncoding threadEncoding;
1062 pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
1064 /* check for thread specific encoding, use default if not set */
1065 threadEncoding = SAL_INT_CAST(
1066 rtl_TextEncoding,
1067 (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key));
1068 if (0 == threadEncoding)
1069 threadEncoding = g_thread.m_textencoding.m_default;
1071 return threadEncoding;
1074 /*****************************************************************************/
1075 /* osl_setThreadTextEncoding */
1076 /*****************************************************************************/
1077 rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
1079 rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
1081 /* save encoding in thread local storage */
1082 pthread_setspecific (
1083 g_thread.m_textencoding.m_key,
1084 (void*) SAL_INT_CAST(sal_uIntPtr, Encoding));
1086 return oldThreadEncoding;
1089 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */