xref: /trunk/main/sal/osl/unx/thread.c (revision 6e2e4a188da9cb15953b6ac809239c8d1048848e)
1647f063dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3647f063dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4647f063dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5647f063dSAndrew Rist  * distributed with this work for additional information
6647f063dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7647f063dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8647f063dSAndrew Rist  * "License"); you may not use this file except in compliance
9647f063dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13647f063dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14647f063dSAndrew Rist  * software distributed under the License is distributed on an
15647f063dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16647f063dSAndrew Rist  * KIND, either express or implied.  See the License for the
17647f063dSAndrew Rist  * specific language governing permissions and limitations
18647f063dSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20647f063dSAndrew Rist  *************************************************************/
21647f063dSAndrew Rist 
22647f063dSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "system.h"
25cdf0e10cSrcweir #include <string.h>
26cdf0e10cSrcweir #include <osl/diagnose.h>
27cdf0e10cSrcweir #include <osl/thread.h>
28cdf0e10cSrcweir #include <osl/nlsupport.h>
29cdf0e10cSrcweir #ifndef _RTL_TEXTENC_H_
30cdf0e10cSrcweir #include <rtl/textenc.h>
31cdf0e10cSrcweir #endif
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #if defined LINUX
34cdf0e10cSrcweir #include <sys/prctl.h>
35cdf0e10cSrcweir #endif
36cdf0e10cSrcweir 
37cdf0e10cSrcweir /****************************************************************************
38cdf0e10cSrcweir  * @@@ TODO @@@
39cdf0e10cSrcweir  *
40cdf0e10cSrcweir  * (1) 'osl_thread_priority_init_Impl()'
41cdf0e10cSrcweir  *     - insane assumption that initializing caller is main thread
42cdf0e10cSrcweir  *     - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?)
43cdf0e10cSrcweir  *     - POSIX doesn't require defined prio's for SCHED_OTHER (!)
44cdf0e10cSrcweir  *     - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?)
45cdf0e10cSrcweir  * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()'
46cdf0e10cSrcweir  *     - cannot reliably be applied to 'alien' threads;
47cdf0e10cSrcweir  *     - memory leak for 'alien' thread 'HashEntry's;
48cdf0e10cSrcweir  *     - use 'PTHREAD_VALUE(pthread_t)' as identifier instead (?)
49cdf0e10cSrcweir  *     - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar
50cdf0e10cSrcweir  * (3) 'oslSigAlarmHandler()' (#71232#)
51cdf0e10cSrcweir  *     - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates
52cdf0e10cSrcweir  *       the process. So we initialize our signal handling module and do
53cdf0e10cSrcweir  *       register a SIGALRM Handler which catches and ignores it]
54cdf0e10cSrcweir  *     - should this still happen, 'signal.c' needs to be fixed instead.
55cdf0e10cSrcweir  *
56cdf0e10cSrcweir  ****************************************************************************/
57cdf0e10cSrcweir 
58cdf0e10cSrcweir /*****************************************************************************/
59cdf0e10cSrcweir /*  Internal data structures and functions */
60cdf0e10cSrcweir /*****************************************************************************/
61cdf0e10cSrcweir 
62cdf0e10cSrcweir #define THREADIMPL_FLAGS_TERMINATE  0x00001
63cdf0e10cSrcweir #define THREADIMPL_FLAGS_STARTUP    0x00002
64cdf0e10cSrcweir #define THREADIMPL_FLAGS_SUSPENDED  0x00004
65cdf0e10cSrcweir #define THREADIMPL_FLAGS_ACTIVE     0x00008
66cdf0e10cSrcweir #define THREADIMPL_FLAGS_ATTACHED   0x00010
67cdf0e10cSrcweir #define THREADIMPL_FLAGS_DESTROYED  0x00020
68cdf0e10cSrcweir 
69cdf0e10cSrcweir typedef struct osl_thread_impl_st
70cdf0e10cSrcweir {
71cdf0e10cSrcweir     pthread_t           m_hThread;
72cdf0e10cSrcweir     sal_uInt16          m_Ident; /* @@@ see TODO @@@ */
73cdf0e10cSrcweir     short               m_Flags;
74cdf0e10cSrcweir     oslWorkerFunction   m_WorkerFunction;
75cdf0e10cSrcweir     void*               m_pData;
76cdf0e10cSrcweir     pthread_mutex_t     m_Lock;
77cdf0e10cSrcweir     pthread_cond_t      m_Cond;
78cdf0e10cSrcweir } Thread_Impl;
79cdf0e10cSrcweir 
80cdf0e10cSrcweir struct osl_thread_priority_st
81cdf0e10cSrcweir {
82cdf0e10cSrcweir     int m_Highest;
83cdf0e10cSrcweir     int m_Above_Normal;
84cdf0e10cSrcweir     int m_Normal;
85cdf0e10cSrcweir     int m_Below_Normal;
86cdf0e10cSrcweir     int m_Lowest;
87cdf0e10cSrcweir };
88cdf0e10cSrcweir 
89cdf0e10cSrcweir #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
90cdf0e10cSrcweir static void osl_thread_priority_init_Impl (void);
91cdf0e10cSrcweir 
92cdf0e10cSrcweir struct osl_thread_textencoding_st
93cdf0e10cSrcweir {
94cdf0e10cSrcweir     pthread_key_t    m_key;     /* key to store thread local text encoding */
95cdf0e10cSrcweir     rtl_TextEncoding m_default; /* the default text encoding */
96cdf0e10cSrcweir };
97cdf0e10cSrcweir 
98cdf0e10cSrcweir #define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW }
99cdf0e10cSrcweir static void osl_thread_textencoding_init_Impl (void);
100cdf0e10cSrcweir 
101cdf0e10cSrcweir struct osl_thread_global_st
102cdf0e10cSrcweir {
103cdf0e10cSrcweir     pthread_once_t                    m_once;
104cdf0e10cSrcweir     struct osl_thread_priority_st     m_priority;
105cdf0e10cSrcweir     struct osl_thread_textencoding_st m_textencoding;
106cdf0e10cSrcweir };
107cdf0e10cSrcweir 
108cdf0e10cSrcweir static struct osl_thread_global_st g_thread =
109cdf0e10cSrcweir {
110cdf0e10cSrcweir     PTHREAD_ONCE_INIT,
111cdf0e10cSrcweir     OSL_THREAD_PRIORITY_INITIALIZER,
112cdf0e10cSrcweir     OSL_THREAD_TEXTENCODING_INITIALIZER
113cdf0e10cSrcweir };
114cdf0e10cSrcweir 
115cdf0e10cSrcweir static void osl_thread_init_Impl (void);
116cdf0e10cSrcweir 
117cdf0e10cSrcweir static Thread_Impl* osl_thread_construct_Impl (void);
118cdf0e10cSrcweir static void         osl_thread_destruct_Impl (Thread_Impl ** ppImpl);
119cdf0e10cSrcweir 
120cdf0e10cSrcweir static void* osl_thread_start_Impl (void * pData);
121cdf0e10cSrcweir static void  osl_thread_cleanup_Impl (void * pData);
122cdf0e10cSrcweir 
123cdf0e10cSrcweir static oslThread osl_thread_create_Impl (
124cdf0e10cSrcweir     oslWorkerFunction pWorker, void * pThreadData, short nFlags);
125cdf0e10cSrcweir 
126cdf0e10cSrcweir static void osl_thread_join_cleanup_Impl (void * opaque);
127cdf0e10cSrcweir static void osl_thread_wait_cleanup_Impl (void * opaque);
128cdf0e10cSrcweir 
129cdf0e10cSrcweir /* @@@ see TODO @@@ */
130cdf0e10cSrcweir static sal_uInt16 insertThreadId (pthread_t hThread);
131cdf0e10cSrcweir static sal_uInt16 lookupThreadId (pthread_t hThread);
132cdf0e10cSrcweir static void       removeThreadId (pthread_t hThread);
133cdf0e10cSrcweir 
134cdf0e10cSrcweir /*****************************************************************************/
135cdf0e10cSrcweir /* osl_thread_init_Impl */
136cdf0e10cSrcweir /*****************************************************************************/
osl_thread_init_Impl(void)137cdf0e10cSrcweir static void osl_thread_init_Impl (void)
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     osl_thread_priority_init_Impl();
140cdf0e10cSrcweir     osl_thread_textencoding_init_Impl();
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir /*****************************************************************************/
144cdf0e10cSrcweir /* osl_thread_join_cleanup_Impl */
145cdf0e10cSrcweir /*****************************************************************************/
osl_thread_join_cleanup_Impl(void * opaque)146cdf0e10cSrcweir static void osl_thread_join_cleanup_Impl (void * opaque)
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     pthread_t hThread = (pthread_t)(opaque);
149cdf0e10cSrcweir     pthread_detach (hThread);
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir /*****************************************************************************/
153cdf0e10cSrcweir /* osl_thread_wait_cleanup_Impl */
154cdf0e10cSrcweir /*****************************************************************************/
osl_thread_wait_cleanup_Impl(void * opaque)155cdf0e10cSrcweir static void osl_thread_wait_cleanup_Impl (void * opaque)
156cdf0e10cSrcweir {
157cdf0e10cSrcweir     pthread_mutex_t * pMutex = (pthread_mutex_t*)(opaque);
158cdf0e10cSrcweir     pthread_mutex_unlock (pMutex);
159cdf0e10cSrcweir }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir /*****************************************************************************/
162cdf0e10cSrcweir /* osl_thread_construct_Impl */
163cdf0e10cSrcweir /*****************************************************************************/
osl_thread_construct_Impl(void)164cdf0e10cSrcweir Thread_Impl* osl_thread_construct_Impl (void)
165cdf0e10cSrcweir {
166cdf0e10cSrcweir     Thread_Impl* pImpl = malloc (sizeof(Thread_Impl));
167cdf0e10cSrcweir     if (pImpl)
168cdf0e10cSrcweir     {
169cdf0e10cSrcweir         memset (pImpl, 0, sizeof(Thread_Impl));
170cdf0e10cSrcweir 
171cdf0e10cSrcweir         pthread_mutex_init (&(pImpl->m_Lock), PTHREAD_MUTEXATTR_DEFAULT);
172cdf0e10cSrcweir         pthread_cond_init  (&(pImpl->m_Cond), PTHREAD_CONDATTR_DEFAULT);
173cdf0e10cSrcweir     }
174cdf0e10cSrcweir     return (pImpl);
175cdf0e10cSrcweir }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir /*****************************************************************************/
178cdf0e10cSrcweir /* osl_thread_destruct_Impl */
179cdf0e10cSrcweir /*****************************************************************************/
osl_thread_destruct_Impl(Thread_Impl ** ppImpl)180cdf0e10cSrcweir static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl)
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     OSL_ASSERT(ppImpl);
183cdf0e10cSrcweir     if (*ppImpl)
184cdf0e10cSrcweir     {
185cdf0e10cSrcweir         pthread_cond_destroy  (&((*ppImpl)->m_Cond));
186cdf0e10cSrcweir         pthread_mutex_destroy (&((*ppImpl)->m_Lock));
187cdf0e10cSrcweir 
188cdf0e10cSrcweir         free (*ppImpl);
189509a48ffSpfg         (*ppImpl) = NULL;
190cdf0e10cSrcweir     }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir 
193cdf0e10cSrcweir /*****************************************************************************/
194cdf0e10cSrcweir /* osl_thread_cleanup_Impl */
195cdf0e10cSrcweir /*****************************************************************************/
osl_thread_cleanup_Impl(void * pData)196cdf0e10cSrcweir static void osl_thread_cleanup_Impl (void* pData)
197cdf0e10cSrcweir {
198cdf0e10cSrcweir     pthread_t thread;
199cdf0e10cSrcweir     int attached;
200cdf0e10cSrcweir     int destroyed;
201cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)pData;
202cdf0e10cSrcweir 
203cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     thread = pImpl->m_hThread;
206cdf0e10cSrcweir     attached = (pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) != 0;
207cdf0e10cSrcweir     destroyed = (pImpl->m_Flags & THREADIMPL_FLAGS_DESTROYED) != 0;
208cdf0e10cSrcweir     pImpl->m_Flags &= ~(THREADIMPL_FLAGS_ACTIVE | THREADIMPL_FLAGS_ATTACHED);
209cdf0e10cSrcweir 
210cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     /* release oslThreadIdentifier @@@ see TODO @@@ */
213cdf0e10cSrcweir     removeThreadId (thread);
214cdf0e10cSrcweir 
215cdf0e10cSrcweir     if (attached)
216cdf0e10cSrcweir     {
217cdf0e10cSrcweir         pthread_detach (thread);
218cdf0e10cSrcweir     }
219cdf0e10cSrcweir 
220cdf0e10cSrcweir     if (destroyed)
221cdf0e10cSrcweir     {
222cdf0e10cSrcweir         osl_thread_destruct_Impl (&pImpl);
223cdf0e10cSrcweir     }
224cdf0e10cSrcweir }
225cdf0e10cSrcweir 
226cdf0e10cSrcweir /*****************************************************************************/
227cdf0e10cSrcweir /* osl_thread_start_Impl */
228cdf0e10cSrcweir /*****************************************************************************/
osl_thread_start_Impl(void * pData)229cdf0e10cSrcweir static void* osl_thread_start_Impl (void* pData)
230cdf0e10cSrcweir {
231cdf0e10cSrcweir     int terminate;
232cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)pData;
233cdf0e10cSrcweir 
234cdf0e10cSrcweir     OSL_ASSERT(pImpl);
235cdf0e10cSrcweir 
236cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
237cdf0e10cSrcweir 
238cdf0e10cSrcweir     /* install cleanup handler */
239cdf0e10cSrcweir     pthread_cleanup_push (osl_thread_cleanup_Impl, pData);
240cdf0e10cSrcweir 
241cdf0e10cSrcweir     /* request oslThreadIdentifier @@@ see TODO @@@ */
242cdf0e10cSrcweir     pImpl->m_Ident = insertThreadId (pImpl->m_hThread);
243cdf0e10cSrcweir 
244cdf0e10cSrcweir     /* signal change from STARTUP to ACTIVE state */
245cdf0e10cSrcweir     pImpl->m_Flags &= ~THREADIMPL_FLAGS_STARTUP;
246cdf0e10cSrcweir     pImpl->m_Flags |=  THREADIMPL_FLAGS_ACTIVE;
247cdf0e10cSrcweir     pthread_cond_signal (&(pImpl->m_Cond));
248cdf0e10cSrcweir 
249cdf0e10cSrcweir     /* Check if thread is started in SUSPENDED state */
250cdf0e10cSrcweir     while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
251cdf0e10cSrcweir     {
252cdf0e10cSrcweir         /* wait until SUSPENDED flag is cleared */
253cdf0e10cSrcweir         pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
254cdf0e10cSrcweir         pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
255cdf0e10cSrcweir         pthread_cleanup_pop (0);
256cdf0e10cSrcweir     }
257cdf0e10cSrcweir 
258cdf0e10cSrcweir     /* check for SUSPENDED to TERMINATE state change */
259cdf0e10cSrcweir     terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
262cdf0e10cSrcweir 
263cdf0e10cSrcweir     if (!terminate)
264cdf0e10cSrcweir     {
265cdf0e10cSrcweir         /* call worker function */
266cdf0e10cSrcweir         pImpl->m_WorkerFunction(pImpl->m_pData);
267cdf0e10cSrcweir     }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir     /* call cleanup handler and leave */
270cdf0e10cSrcweir     pthread_cleanup_pop (1);
271cdf0e10cSrcweir     return (0);
272cdf0e10cSrcweir }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir /*****************************************************************************/
275cdf0e10cSrcweir /* osl_thread_create_Impl */
276cdf0e10cSrcweir /*****************************************************************************/
osl_thread_create_Impl(oslWorkerFunction pWorker,void * pThreadData,short nFlags)277cdf0e10cSrcweir static oslThread osl_thread_create_Impl (
278cdf0e10cSrcweir     oslWorkerFunction pWorker,
279cdf0e10cSrcweir     void*             pThreadData,
280cdf0e10cSrcweir     short             nFlags)
281cdf0e10cSrcweir {
282cdf0e10cSrcweir     Thread_Impl* pImpl;
283cdf0e10cSrcweir     int nRet=0;
284cdf0e10cSrcweir 
285cdf0e10cSrcweir     pImpl = osl_thread_construct_Impl();
286cdf0e10cSrcweir     if (!pImpl)
287cdf0e10cSrcweir         return (0); /* ENOMEM */
288cdf0e10cSrcweir 
289cdf0e10cSrcweir     pImpl->m_WorkerFunction = pWorker;
290cdf0e10cSrcweir     pImpl->m_pData = pThreadData;
291cdf0e10cSrcweir     pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP;
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
294cdf0e10cSrcweir 
295cdf0e10cSrcweir     if ((nRet = pthread_create (
296cdf0e10cSrcweir         &(pImpl->m_hThread),
297cdf0e10cSrcweir         PTHREAD_ATTR_DEFAULT,
298cdf0e10cSrcweir         osl_thread_start_Impl,
299cdf0e10cSrcweir         (void*)(pImpl))) != 0)
300cdf0e10cSrcweir     {
301*6e2e4a18Smseidel         OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n", nRet, strerror(nRet));
302cdf0e10cSrcweir 
303cdf0e10cSrcweir         pthread_mutex_unlock (&(pImpl->m_Lock));
304cdf0e10cSrcweir         osl_thread_destruct_Impl (&pImpl);
305cdf0e10cSrcweir 
306cdf0e10cSrcweir         return (0);
307cdf0e10cSrcweir     }
308cdf0e10cSrcweir 
309cdf0e10cSrcweir     /* wait for change from STARTUP to ACTIVE state */
310cdf0e10cSrcweir     while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP)
311cdf0e10cSrcweir     {
312cdf0e10cSrcweir         /* wait until STARTUP flag is cleared */
313cdf0e10cSrcweir         pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
314cdf0e10cSrcweir         pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
315cdf0e10cSrcweir         pthread_cleanup_pop (0);
316cdf0e10cSrcweir     }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
319cdf0e10cSrcweir 
320cdf0e10cSrcweir     return ((oslThread)(pImpl));
321cdf0e10cSrcweir }
322cdf0e10cSrcweir 
323cdf0e10cSrcweir /*****************************************************************************/
324cdf0e10cSrcweir /* osl_createThread */
325cdf0e10cSrcweir /*****************************************************************************/
osl_createThread(oslWorkerFunction pWorker,void * pThreadData)326cdf0e10cSrcweir oslThread osl_createThread (
327cdf0e10cSrcweir     oslWorkerFunction pWorker,
328cdf0e10cSrcweir     void *            pThreadData)
329cdf0e10cSrcweir {
330cdf0e10cSrcweir     return osl_thread_create_Impl (
331cdf0e10cSrcweir         pWorker,
332cdf0e10cSrcweir         pThreadData,
333cdf0e10cSrcweir         THREADIMPL_FLAGS_ATTACHED);
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir /*****************************************************************************/
337cdf0e10cSrcweir /* osl_createSuspendedThread */
338cdf0e10cSrcweir /*****************************************************************************/
osl_createSuspendedThread(oslWorkerFunction pWorker,void * pThreadData)339cdf0e10cSrcweir oslThread osl_createSuspendedThread (
340cdf0e10cSrcweir     oslWorkerFunction pWorker,
341cdf0e10cSrcweir     void *            pThreadData)
342cdf0e10cSrcweir {
343cdf0e10cSrcweir     return osl_thread_create_Impl (
344cdf0e10cSrcweir         pWorker,
345cdf0e10cSrcweir         pThreadData,
346cdf0e10cSrcweir         THREADIMPL_FLAGS_ATTACHED |
347cdf0e10cSrcweir         THREADIMPL_FLAGS_SUSPENDED );
348cdf0e10cSrcweir }
349cdf0e10cSrcweir 
350cdf0e10cSrcweir /*****************************************************************************/
351cdf0e10cSrcweir /* osl_destroyThread */
352cdf0e10cSrcweir /*****************************************************************************/
osl_destroyThread(oslThread Thread)353cdf0e10cSrcweir void SAL_CALL osl_destroyThread(oslThread Thread)
354cdf0e10cSrcweir {
355cdf0e10cSrcweir     if (Thread != NULL) {
356cdf0e10cSrcweir         Thread_Impl * impl = (Thread_Impl *) Thread;
357cdf0e10cSrcweir         int active;
358cdf0e10cSrcweir         pthread_mutex_lock(&impl->m_Lock);
359cdf0e10cSrcweir         active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0;
360cdf0e10cSrcweir         impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED;
361cdf0e10cSrcweir         pthread_mutex_unlock(&impl->m_Lock);
362cdf0e10cSrcweir         if (!active) {
363cdf0e10cSrcweir             osl_thread_destruct_Impl(&impl);
364cdf0e10cSrcweir         }
365cdf0e10cSrcweir     }
366cdf0e10cSrcweir }
367cdf0e10cSrcweir 
368cdf0e10cSrcweir /*****************************************************************************/
369cdf0e10cSrcweir /* osl_resumeThread */
370cdf0e10cSrcweir /*****************************************************************************/
osl_resumeThread(oslThread Thread)371cdf0e10cSrcweir void SAL_CALL osl_resumeThread(oslThread Thread)
372cdf0e10cSrcweir {
373cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
374cdf0e10cSrcweir 
375cdf0e10cSrcweir     OSL_ASSERT(pImpl);
376cdf0e10cSrcweir     if (!pImpl)
377cdf0e10cSrcweir         return; /* EINVAL */
378cdf0e10cSrcweir 
379cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
380cdf0e10cSrcweir 
381cdf0e10cSrcweir     if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
382cdf0e10cSrcweir     {
383cdf0e10cSrcweir         /* clear SUSPENDED flag */
384cdf0e10cSrcweir         pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
385cdf0e10cSrcweir         pthread_cond_signal (&(pImpl->m_Cond));
386cdf0e10cSrcweir     }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
389cdf0e10cSrcweir }
390cdf0e10cSrcweir 
391cdf0e10cSrcweir /*****************************************************************************/
392cdf0e10cSrcweir /* osl_suspendThread */
393cdf0e10cSrcweir /*****************************************************************************/
osl_suspendThread(oslThread Thread)394cdf0e10cSrcweir void SAL_CALL osl_suspendThread(oslThread Thread)
395cdf0e10cSrcweir {
396cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
397cdf0e10cSrcweir 
398cdf0e10cSrcweir     OSL_ASSERT(pImpl);
399cdf0e10cSrcweir     if (!pImpl)
400cdf0e10cSrcweir         return; /* EINVAL */
401cdf0e10cSrcweir 
402cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
403cdf0e10cSrcweir 
404cdf0e10cSrcweir     pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir     if (pthread_equal (pthread_self(), pImpl->m_hThread))
407cdf0e10cSrcweir     {
408cdf0e10cSrcweir         /* self suspend */
409cdf0e10cSrcweir         while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
410cdf0e10cSrcweir         {
411cdf0e10cSrcweir             /* wait until SUSPENDED flag is cleared */
412cdf0e10cSrcweir             pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
413cdf0e10cSrcweir             pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
414cdf0e10cSrcweir             pthread_cleanup_pop (0);
415cdf0e10cSrcweir         }
416cdf0e10cSrcweir     }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir /*****************************************************************************/
422cdf0e10cSrcweir /* osl_isThreadRunning */
423cdf0e10cSrcweir /*****************************************************************************/
osl_isThreadRunning(const oslThread Thread)424cdf0e10cSrcweir sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
425cdf0e10cSrcweir {
426cdf0e10cSrcweir     sal_Bool active;
427cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
428cdf0e10cSrcweir 
429cdf0e10cSrcweir     if (!pImpl)
430cdf0e10cSrcweir         return sal_False;
431cdf0e10cSrcweir 
432cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
433cdf0e10cSrcweir     active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
434cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
435cdf0e10cSrcweir 
436cdf0e10cSrcweir     return (active);
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir /*****************************************************************************/
440cdf0e10cSrcweir /* osl_joinWithThread */
441cdf0e10cSrcweir /*****************************************************************************/
osl_joinWithThread(oslThread Thread)442cdf0e10cSrcweir void SAL_CALL osl_joinWithThread(oslThread Thread)
443cdf0e10cSrcweir {
444cdf0e10cSrcweir     pthread_t thread;
445cdf0e10cSrcweir     int attached;
446cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     if (!pImpl)
449cdf0e10cSrcweir         return;
450cdf0e10cSrcweir 
451cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
452cdf0e10cSrcweir 
453cdf0e10cSrcweir     if (pthread_equal (pthread_self(), pImpl->m_hThread))
454cdf0e10cSrcweir     {
455cdf0e10cSrcweir         /* self join */
456cdf0e10cSrcweir         pthread_mutex_unlock (&(pImpl->m_Lock));
457cdf0e10cSrcweir         return; /* EDEADLK */
458cdf0e10cSrcweir     }
459cdf0e10cSrcweir 
460cdf0e10cSrcweir     thread = pImpl->m_hThread;
461cdf0e10cSrcweir     attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0);
462cdf0e10cSrcweir     pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED;
463cdf0e10cSrcweir 
464cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
465cdf0e10cSrcweir 
466cdf0e10cSrcweir     if (attached)
467cdf0e10cSrcweir     {
468cdf0e10cSrcweir         /* install cleanup handler to ensure consistent flags and state */
469cdf0e10cSrcweir         pthread_cleanup_push (
470cdf0e10cSrcweir             osl_thread_join_cleanup_Impl, (void*)thread);
471cdf0e10cSrcweir 
472cdf0e10cSrcweir         /* join */
473cdf0e10cSrcweir         pthread_join (thread, NULL);
474cdf0e10cSrcweir 
475cdf0e10cSrcweir         /* remove cleanup handler */
476cdf0e10cSrcweir         pthread_cleanup_pop (0);
477cdf0e10cSrcweir     }
478cdf0e10cSrcweir }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir /*****************************************************************************/
481cdf0e10cSrcweir /* osl_terminateThread */
482cdf0e10cSrcweir /*****************************************************************************/
osl_terminateThread(oslThread Thread)483cdf0e10cSrcweir void SAL_CALL osl_terminateThread(oslThread Thread)
484cdf0e10cSrcweir {
485cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
486cdf0e10cSrcweir 
487cdf0e10cSrcweir     OSL_ASSERT(pImpl);
488cdf0e10cSrcweir     if (!pImpl)
489cdf0e10cSrcweir         return; /* EINVAL */
490cdf0e10cSrcweir 
491cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
492cdf0e10cSrcweir 
493cdf0e10cSrcweir     if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
494cdf0e10cSrcweir     {
495cdf0e10cSrcweir         /* clear SUSPENDED flag */
496cdf0e10cSrcweir         pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
497cdf0e10cSrcweir         pthread_cond_signal (&(pImpl->m_Cond));
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir 
500cdf0e10cSrcweir     pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
501cdf0e10cSrcweir 
502cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
503cdf0e10cSrcweir }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir /*****************************************************************************/
506cdf0e10cSrcweir /* osl_scheduleThread */
507cdf0e10cSrcweir /*****************************************************************************/
osl_scheduleThread(oslThread Thread)508cdf0e10cSrcweir sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
509cdf0e10cSrcweir {
510cdf0e10cSrcweir     int terminate;
511cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
512cdf0e10cSrcweir 
513cdf0e10cSrcweir     OSL_ASSERT(pImpl);
514cdf0e10cSrcweir     if (!pImpl)
515cdf0e10cSrcweir         return sal_False; /* EINVAL */
516cdf0e10cSrcweir 
517cdf0e10cSrcweir     OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread));
518cdf0e10cSrcweir     if (!(pthread_equal (pthread_self(), pImpl->m_hThread)))
519cdf0e10cSrcweir         return sal_False; /* EINVAL */
520cdf0e10cSrcweir 
521cdf0e10cSrcweir     pthread_testcancel();
522cdf0e10cSrcweir     pthread_mutex_lock (&(pImpl->m_Lock));
523cdf0e10cSrcweir 
524cdf0e10cSrcweir     while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
525cdf0e10cSrcweir     {
526cdf0e10cSrcweir         /* wait until SUSPENDED flag is cleared */
527cdf0e10cSrcweir         pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
528cdf0e10cSrcweir         pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
529cdf0e10cSrcweir         pthread_cleanup_pop (0);
530cdf0e10cSrcweir     }
531cdf0e10cSrcweir 
532cdf0e10cSrcweir     terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
533cdf0e10cSrcweir 
534cdf0e10cSrcweir     pthread_mutex_unlock(&(pImpl->m_Lock));
535cdf0e10cSrcweir     pthread_testcancel();
536cdf0e10cSrcweir 
537cdf0e10cSrcweir     return (terminate == 0);
538cdf0e10cSrcweir }
539cdf0e10cSrcweir 
540cdf0e10cSrcweir /*****************************************************************************/
541cdf0e10cSrcweir /* osl_waitThread */
542cdf0e10cSrcweir /*****************************************************************************/
osl_waitThread(const TimeValue * pDelay)543cdf0e10cSrcweir void SAL_CALL osl_waitThread(const TimeValue* pDelay)
544cdf0e10cSrcweir {
545cdf0e10cSrcweir     if (pDelay)
546cdf0e10cSrcweir     {
547cdf0e10cSrcweir         struct timespec delay;
548cdf0e10cSrcweir 
549cdf0e10cSrcweir         SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec);
550cdf0e10cSrcweir 
551cdf0e10cSrcweir         SLEEP_TIMESPEC(delay);
552cdf0e10cSrcweir     }
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir /*****************************************************************************/
556cdf0e10cSrcweir /* osl_yieldThread */
557cdf0e10cSrcweir /*
558cdf0e10cSrcweir     Note that POSIX scheduling _really_ requires threads to call this
559cdf0e10cSrcweir     functions, since a thread only reschedules to other thread, when
560cdf0e10cSrcweir     it blocks (sleep, blocking I/O) OR calls sched_yield().
561cdf0e10cSrcweir */
562cdf0e10cSrcweir /*****************************************************************************/
osl_yieldThread()563cdf0e10cSrcweir void SAL_CALL osl_yieldThread()
564cdf0e10cSrcweir {
565cdf0e10cSrcweir     sched_yield();
566cdf0e10cSrcweir }
567cdf0e10cSrcweir 
osl_setThreadName(char const * name)568cdf0e10cSrcweir void SAL_CALL osl_setThreadName(char const * name) {
569cdf0e10cSrcweir #if defined LINUX
570cdf0e10cSrcweir     if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) {
571cdf0e10cSrcweir         OSL_TRACE(
572cdf0e10cSrcweir             "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX,
573cdf0e10cSrcweir             errno);
574cdf0e10cSrcweir     }
575cdf0e10cSrcweir #else
576cdf0e10cSrcweir     (void) name;
577cdf0e10cSrcweir #endif
578cdf0e10cSrcweir }
579cdf0e10cSrcweir 
580cdf0e10cSrcweir /*****************************************************************************/
581cdf0e10cSrcweir /* osl_getThreadIdentifier @@@ see TODO @@@ */
582cdf0e10cSrcweir /*****************************************************************************/
583cdf0e10cSrcweir 
584cdf0e10cSrcweir #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
585cdf0e10cSrcweir 
586cdf0e10cSrcweir typedef struct _HashEntry
587cdf0e10cSrcweir {
588cdf0e10cSrcweir     pthread_t         Handle;
589cdf0e10cSrcweir     sal_uInt16        Ident;
590cdf0e10cSrcweir     struct _HashEntry *Next;
591cdf0e10cSrcweir } HashEntry;
592cdf0e10cSrcweir 
593cdf0e10cSrcweir static HashEntry* HashTable[31];
594cdf0e10cSrcweir static int HashSize = sizeof(HashTable) / sizeof(HashTable[0]);
595cdf0e10cSrcweir 
596cdf0e10cSrcweir static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER;
597cdf0e10cSrcweir 
598cdf0e10cSrcweir static sal_uInt16 LastIdent = 0;
599cdf0e10cSrcweir 
lookupThreadId(pthread_t hThread)600cdf0e10cSrcweir static sal_uInt16 lookupThreadId (pthread_t hThread)
601cdf0e10cSrcweir {
602cdf0e10cSrcweir     HashEntry *pEntry;
603cdf0e10cSrcweir 
604cdf0e10cSrcweir     pthread_mutex_lock(&HashLock);
605cdf0e10cSrcweir 
606cdf0e10cSrcweir         pEntry = HashTable[HASHID(hThread)];
607cdf0e10cSrcweir         while (pEntry != NULL)
608cdf0e10cSrcweir         {
609cdf0e10cSrcweir             if (pthread_equal(pEntry->Handle, hThread))
610cdf0e10cSrcweir             {
611cdf0e10cSrcweir                 pthread_mutex_unlock(&HashLock);
612cdf0e10cSrcweir                 return (pEntry->Ident);
613cdf0e10cSrcweir             }
614cdf0e10cSrcweir             pEntry = pEntry->Next;
615cdf0e10cSrcweir         }
616cdf0e10cSrcweir 
617cdf0e10cSrcweir     pthread_mutex_unlock(&HashLock);
618cdf0e10cSrcweir 
619cdf0e10cSrcweir     return (0);
620cdf0e10cSrcweir }
621cdf0e10cSrcweir 
insertThreadId(pthread_t hThread)622cdf0e10cSrcweir static sal_uInt16 insertThreadId (pthread_t hThread)
623cdf0e10cSrcweir {
624cdf0e10cSrcweir     HashEntry *pEntry, *pInsert = NULL;
625cdf0e10cSrcweir 
626cdf0e10cSrcweir     pthread_mutex_lock(&HashLock);
627cdf0e10cSrcweir 
628cdf0e10cSrcweir     pEntry = HashTable[HASHID(hThread)];
629cdf0e10cSrcweir 
630cdf0e10cSrcweir     while (pEntry != NULL)
631cdf0e10cSrcweir     {
632cdf0e10cSrcweir         if (pthread_equal(pEntry->Handle, hThread))
633cdf0e10cSrcweir             break;
634cdf0e10cSrcweir 
635cdf0e10cSrcweir         pInsert = pEntry;
636cdf0e10cSrcweir         pEntry = pEntry->Next;
637cdf0e10cSrcweir     }
638cdf0e10cSrcweir 
639cdf0e10cSrcweir     if (pEntry == NULL)
640cdf0e10cSrcweir     {
641cdf0e10cSrcweir         pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
642cdf0e10cSrcweir 
643cdf0e10cSrcweir         pEntry->Handle = hThread;
644cdf0e10cSrcweir 
645cdf0e10cSrcweir         ++ LastIdent;
646cdf0e10cSrcweir 
647cdf0e10cSrcweir         if ( LastIdent == 0 )
648cdf0e10cSrcweir             LastIdent = 1;
649cdf0e10cSrcweir 
650cdf0e10cSrcweir         pEntry->Ident = LastIdent;
651cdf0e10cSrcweir 
652cdf0e10cSrcweir         if (pInsert)
653cdf0e10cSrcweir             pInsert->Next = pEntry;
654cdf0e10cSrcweir         else
655cdf0e10cSrcweir             HashTable[HASHID(hThread)] = pEntry;
656cdf0e10cSrcweir     }
657cdf0e10cSrcweir 
658cdf0e10cSrcweir     pthread_mutex_unlock(&HashLock);
659cdf0e10cSrcweir 
660cdf0e10cSrcweir     return (pEntry->Ident);
661cdf0e10cSrcweir }
662cdf0e10cSrcweir 
removeThreadId(pthread_t hThread)663cdf0e10cSrcweir static void removeThreadId (pthread_t hThread)
664cdf0e10cSrcweir {
665cdf0e10cSrcweir     HashEntry *pEntry, *pRemove = NULL;
666cdf0e10cSrcweir 
667cdf0e10cSrcweir     pthread_mutex_lock(&HashLock);
668cdf0e10cSrcweir 
669cdf0e10cSrcweir     pEntry = HashTable[HASHID(hThread)];
670cdf0e10cSrcweir     while (pEntry != NULL)
671cdf0e10cSrcweir     {
672cdf0e10cSrcweir         if (pthread_equal(pEntry->Handle, hThread))
673cdf0e10cSrcweir             break;
674cdf0e10cSrcweir 
675cdf0e10cSrcweir         pRemove = pEntry;
676cdf0e10cSrcweir         pEntry = pEntry->Next;
677cdf0e10cSrcweir     }
678cdf0e10cSrcweir 
679cdf0e10cSrcweir     if (pEntry != NULL)
680cdf0e10cSrcweir     {
681cdf0e10cSrcweir         if (pRemove)
682cdf0e10cSrcweir             pRemove->Next = pEntry->Next;
683cdf0e10cSrcweir         else
684cdf0e10cSrcweir             HashTable[HASHID(hThread)] = pEntry->Next;
685cdf0e10cSrcweir 
686cdf0e10cSrcweir         free(pEntry);
687cdf0e10cSrcweir     }
688cdf0e10cSrcweir 
689cdf0e10cSrcweir     pthread_mutex_unlock(&HashLock);
690cdf0e10cSrcweir }
691cdf0e10cSrcweir 
osl_getThreadIdentifier(oslThread Thread)692cdf0e10cSrcweir oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
693cdf0e10cSrcweir {
694cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
695cdf0e10cSrcweir     sal_uInt16   Ident;
696cdf0e10cSrcweir 
697cdf0e10cSrcweir     if (pImpl)
698cdf0e10cSrcweir         Ident = pImpl->m_Ident;
699cdf0e10cSrcweir     else
700cdf0e10cSrcweir     {
701cdf0e10cSrcweir         /* current thread */
702cdf0e10cSrcweir         pthread_t current = pthread_self();
703cdf0e10cSrcweir 
704cdf0e10cSrcweir         Ident = lookupThreadId (current);
705cdf0e10cSrcweir         if (Ident == 0)
706cdf0e10cSrcweir             /* @@@ see TODO: alien pthread_self() @@@ */
707cdf0e10cSrcweir             Ident = insertThreadId (current);
708cdf0e10cSrcweir     }
709cdf0e10cSrcweir 
710cdf0e10cSrcweir     return ((oslThreadIdentifier)(Ident));
711cdf0e10cSrcweir }
712cdf0e10cSrcweir 
713cdf0e10cSrcweir /*****************************************************************************
714cdf0e10cSrcweir     @@@ see TODO @@@
715cdf0e10cSrcweir     osl_thread_priority_init_Impl
716cdf0e10cSrcweir 
717cdf0e10cSrcweir     set the base-priority of the main-thread to
718cdf0e10cSrcweir     oslThreadPriorityNormal (64) since 0 (lowest) is
719cdf0e10cSrcweir     the system default. This behaviour collides with
720cdf0e10cSrcweir     our enum-priority definition (highest..normal..lowest).
721cdf0e10cSrcweir     A normal user will expect the main-thread of an app.
722cdf0e10cSrcweir     to have the "normal" priority.
723cdf0e10cSrcweir 
724cdf0e10cSrcweir *****************************************************************************/
osl_thread_priority_init_Impl(void)725cdf0e10cSrcweir static void osl_thread_priority_init_Impl (void)
726cdf0e10cSrcweir {
727cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
728cdf0e10cSrcweir     struct sched_param param;
729cdf0e10cSrcweir     int policy=0;
730cdf0e10cSrcweir     int nRet=0;
731cdf0e10cSrcweir 
732cdf0e10cSrcweir /* @@@ see TODO: calling thread may not be main thread @@@ */
733cdf0e10cSrcweir 
734cdf0e10cSrcweir     if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
735cdf0e10cSrcweir     {
736cdf0e10cSrcweir         OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet));
737cdf0e10cSrcweir         return;
738cdf0e10cSrcweir     }
739cdf0e10cSrcweir 
740cdf0e10cSrcweir #if defined (SOLARIS)
741cdf0e10cSrcweir     if ( policy >= _SCHED_NEXT)
742cdf0e10cSrcweir     {
743cdf0e10cSrcweir         /* mfe: pthread_getschedparam on Solaris has a possible Bug */
744cdf0e10cSrcweir         /*      one gets 959917873 as the policy                    */
745cdf0e10cSrcweir         /*      so set the policy to a default one                  */
746cdf0e10cSrcweir         policy=SCHED_OTHER;
747cdf0e10cSrcweir     }
748cdf0e10cSrcweir #endif /* SOLARIS */
749cdf0e10cSrcweir 
750cdf0e10cSrcweir     if ((nRet = sched_get_priority_min(policy) ) != -1)
751cdf0e10cSrcweir     {
752cdf0e10cSrcweir         OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet);
753cdf0e10cSrcweir         g_thread.m_priority.m_Lowest=nRet;
754cdf0e10cSrcweir     }
755cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
756cdf0e10cSrcweir     else
757cdf0e10cSrcweir     {
758cdf0e10cSrcweir         fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
759cdf0e10cSrcweir     }
760cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
761cdf0e10cSrcweir 
762cdf0e10cSrcweir     if ((nRet = sched_get_priority_max(policy) ) != -1)
763cdf0e10cSrcweir     {
764cdf0e10cSrcweir         OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet);
765cdf0e10cSrcweir         g_thread.m_priority.m_Highest=nRet;
766cdf0e10cSrcweir     }
767cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
768cdf0e10cSrcweir     else
769cdf0e10cSrcweir     {
770cdf0e10cSrcweir         fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
771cdf0e10cSrcweir     }
772cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
773cdf0e10cSrcweir 
774cdf0e10cSrcweir     g_thread.m_priority.m_Normal =
775cdf0e10cSrcweir         (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2;
776cdf0e10cSrcweir     g_thread.m_priority.m_Below_Normal =
777cdf0e10cSrcweir         (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2;
778cdf0e10cSrcweir     g_thread.m_priority.m_Above_Normal =
779cdf0e10cSrcweir         (g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2;
780cdf0e10cSrcweir 
781cdf0e10cSrcweir /* @@@ set prio of calling (not main) thread (?) @@@ */
782cdf0e10cSrcweir 
783cdf0e10cSrcweir     param.sched_priority= g_thread.m_priority.m_Normal;
784cdf0e10cSrcweir 
785cdf0e10cSrcweir     if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
786cdf0e10cSrcweir     {
787cdf0e10cSrcweir         OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet));
788cdf0e10cSrcweir         OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority);
789cdf0e10cSrcweir     }
790cdf0e10cSrcweir 
791cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
792cdf0e10cSrcweir }
793cdf0e10cSrcweir 
794cdf0e10cSrcweir /*****************************************************************************/
795cdf0e10cSrcweir /* osl_setThreadPriority */
796cdf0e10cSrcweir /*
797cdf0e10cSrcweir     Impl-Notes: contrary to solaris-docu, which claims
798cdf0e10cSrcweir     valid priority-levels from 0 .. INT_MAX, only the
799cdf0e10cSrcweir     range 0..127 is accepted. (0 lowest, 127 highest)
800cdf0e10cSrcweir */
801cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadPriority(oslThread Thread,oslThreadPriority Priority)802cdf0e10cSrcweir void SAL_CALL osl_setThreadPriority (
803cdf0e10cSrcweir     oslThread         Thread,
804cdf0e10cSrcweir     oslThreadPriority Priority)
805cdf0e10cSrcweir {
806cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
807cdf0e10cSrcweir 
808cdf0e10cSrcweir     struct sched_param Param;
809cdf0e10cSrcweir     int policy;
810cdf0e10cSrcweir     int nRet;
811cdf0e10cSrcweir 
812cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
813cdf0e10cSrcweir 
814cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
815cdf0e10cSrcweir 
816cdf0e10cSrcweir     OSL_ASSERT(pImpl);
817cdf0e10cSrcweir     if (!pImpl)
818cdf0e10cSrcweir         return; /* EINVAL */
819cdf0e10cSrcweir 
820cdf0e10cSrcweir #ifdef NO_PTHREAD_PRIORITY
821cdf0e10cSrcweir     (void) Priority; /* unused */
822cdf0e10cSrcweir #else /* NO_PTHREAD_PRIORITY */
823cdf0e10cSrcweir 
824cdf0e10cSrcweir     if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
825cdf0e10cSrcweir         return; /* ESRCH */
826cdf0e10cSrcweir 
827cdf0e10cSrcweir #if defined (SOLARIS)
828cdf0e10cSrcweir     if ( policy >= _SCHED_NEXT)
829cdf0e10cSrcweir     {
830cdf0e10cSrcweir         /* mfe: pthread_getschedparam on Solaris has a possible Bug */
831cdf0e10cSrcweir         /*      one gets 959917873 as the policy                   */
832cdf0e10cSrcweir         /*      so set the policy to a default one                 */
833cdf0e10cSrcweir         policy=SCHED_OTHER;
834cdf0e10cSrcweir     }
835cdf0e10cSrcweir #endif /* SOLARIS */
836cdf0e10cSrcweir 
837cdf0e10cSrcweir     pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     switch(Priority)
840cdf0e10cSrcweir     {
841cdf0e10cSrcweir         case osl_Thread_PriorityHighest:
842cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Highest;
843cdf0e10cSrcweir             break;
844cdf0e10cSrcweir 
845cdf0e10cSrcweir         case osl_Thread_PriorityAboveNormal:
846cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Above_Normal;
847cdf0e10cSrcweir             break;
848cdf0e10cSrcweir 
849cdf0e10cSrcweir         case osl_Thread_PriorityNormal:
850cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Normal;
851cdf0e10cSrcweir             break;
852cdf0e10cSrcweir 
853cdf0e10cSrcweir         case osl_Thread_PriorityBelowNormal:
854cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Below_Normal;
855cdf0e10cSrcweir             break;
856cdf0e10cSrcweir 
857cdf0e10cSrcweir         case osl_Thread_PriorityLowest:
858cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Lowest;
859cdf0e10cSrcweir             break;
860cdf0e10cSrcweir 
861cdf0e10cSrcweir         case osl_Thread_PriorityUnknown:
862cdf0e10cSrcweir             OSL_ASSERT(sal_False);      /* only fools try this...*/
863cdf0e10cSrcweir 
864cdf0e10cSrcweir             /* let release-version behave friendly */
865cdf0e10cSrcweir             return;
866cdf0e10cSrcweir 
867cdf0e10cSrcweir         default:
868cdf0e10cSrcweir             /* enum expanded, but forgotten here...*/
869cdf0e10cSrcweir             OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
870cdf0e10cSrcweir 
871cdf0e10cSrcweir             /* let release-version behave friendly */
872cdf0e10cSrcweir             return;
873cdf0e10cSrcweir     }
874cdf0e10cSrcweir 
875cdf0e10cSrcweir     if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
876cdf0e10cSrcweir     {
877cdf0e10cSrcweir         OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet));
878cdf0e10cSrcweir     }
879cdf0e10cSrcweir 
880cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
881cdf0e10cSrcweir }
882cdf0e10cSrcweir 
883cdf0e10cSrcweir /*****************************************************************************/
884cdf0e10cSrcweir /* osl_getThreadPriority */
885cdf0e10cSrcweir /*****************************************************************************/
osl_getThreadPriority(const oslThread Thread)886cdf0e10cSrcweir oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
887cdf0e10cSrcweir {
888cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
889cdf0e10cSrcweir 
890cdf0e10cSrcweir     struct sched_param Param;
891cdf0e10cSrcweir     int Policy;
892cdf0e10cSrcweir 
893cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
894cdf0e10cSrcweir 
895cdf0e10cSrcweir     oslThreadPriority Priority = osl_Thread_PriorityNormal;
896cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
897cdf0e10cSrcweir 
898cdf0e10cSrcweir     OSL_ASSERT(pImpl);
899cdf0e10cSrcweir     if (!pImpl)
900cdf0e10cSrcweir         return osl_Thread_PriorityUnknown; /* EINVAL */
901cdf0e10cSrcweir 
902cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
903cdf0e10cSrcweir 
904cdf0e10cSrcweir     if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0)
905cdf0e10cSrcweir         return osl_Thread_PriorityUnknown; /* ESRCH */
906cdf0e10cSrcweir 
907cdf0e10cSrcweir     pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
908cdf0e10cSrcweir 
909cdf0e10cSrcweir     /* map pthread priority to enum */
910cdf0e10cSrcweir     if (Param.sched_priority==g_thread.m_priority.m_Highest)
911cdf0e10cSrcweir     {
912cdf0e10cSrcweir         /* 127 - highest */
913cdf0e10cSrcweir         Priority= osl_Thread_PriorityHighest;
914cdf0e10cSrcweir     }
915cdf0e10cSrcweir     else if (Param.sched_priority > g_thread.m_priority.m_Normal)
916cdf0e10cSrcweir     {
917cdf0e10cSrcweir         /* 65..126 - above normal */
918cdf0e10cSrcweir         Priority= osl_Thread_PriorityAboveNormal;
919cdf0e10cSrcweir     }
920cdf0e10cSrcweir     else if (Param.sched_priority == g_thread.m_priority.m_Normal)
921cdf0e10cSrcweir     {
922cdf0e10cSrcweir         /* normal */
923cdf0e10cSrcweir         Priority= osl_Thread_PriorityNormal;
924cdf0e10cSrcweir     }
925cdf0e10cSrcweir     else if (Param.sched_priority > g_thread.m_priority.m_Lowest)
926cdf0e10cSrcweir     {
927cdf0e10cSrcweir         /* 63..1 -below normal */
928cdf0e10cSrcweir         Priority= osl_Thread_PriorityBelowNormal;
929cdf0e10cSrcweir     }
930cdf0e10cSrcweir     else if (Param.sched_priority == g_thread.m_priority.m_Lowest)
931cdf0e10cSrcweir     {
932cdf0e10cSrcweir         /* 0 - lowest */
933cdf0e10cSrcweir         Priority= osl_Thread_PriorityLowest;
934cdf0e10cSrcweir     }
935cdf0e10cSrcweir     else
936cdf0e10cSrcweir     {
937cdf0e10cSrcweir         /* unknown */
938cdf0e10cSrcweir         Priority= osl_Thread_PriorityUnknown;
939cdf0e10cSrcweir     }
940cdf0e10cSrcweir 
941cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
942cdf0e10cSrcweir 
943cdf0e10cSrcweir     return Priority;
944cdf0e10cSrcweir }
945cdf0e10cSrcweir 
946cdf0e10cSrcweir /*****************************************************************************/
947cdf0e10cSrcweir /* osl_createThreadKey */
948cdf0e10cSrcweir /*****************************************************************************/
osl_createThreadKey(oslThreadKeyCallbackFunction pCallback)949cdf0e10cSrcweir oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
950cdf0e10cSrcweir {
951cdf0e10cSrcweir     pthread_key_t key;
952cdf0e10cSrcweir 
953cdf0e10cSrcweir     if (pthread_key_create(&key, pCallback) != 0)
954cdf0e10cSrcweir         key = 0;
955cdf0e10cSrcweir 
956cdf0e10cSrcweir     return ((oslThreadKey)key);
957cdf0e10cSrcweir }
958cdf0e10cSrcweir 
959cdf0e10cSrcweir /*****************************************************************************/
960cdf0e10cSrcweir /* osl_destroyThreadKey */
961cdf0e10cSrcweir /*****************************************************************************/
osl_destroyThreadKey(oslThreadKey Key)962cdf0e10cSrcweir void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
963cdf0e10cSrcweir {
964cdf0e10cSrcweir     pthread_key_delete((pthread_key_t)Key);
965cdf0e10cSrcweir }
966cdf0e10cSrcweir 
967cdf0e10cSrcweir /*****************************************************************************/
968cdf0e10cSrcweir /* osl_getThreadKeyData */
969cdf0e10cSrcweir /*****************************************************************************/
osl_getThreadKeyData(oslThreadKey Key)970cdf0e10cSrcweir void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
971cdf0e10cSrcweir {
972cdf0e10cSrcweir     return (pthread_getspecific((pthread_key_t)Key));
973cdf0e10cSrcweir }
974cdf0e10cSrcweir 
975cdf0e10cSrcweir /*****************************************************************************/
976cdf0e10cSrcweir /* osl_setThreadKeyData */
977cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadKeyData(oslThreadKey Key,void * pData)978cdf0e10cSrcweir sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
979cdf0e10cSrcweir {
980cdf0e10cSrcweir     return (pthread_setspecific((pthread_key_t)Key, pData) == 0);
981cdf0e10cSrcweir }
982cdf0e10cSrcweir 
983cdf0e10cSrcweir /*****************************************************************************/
984cdf0e10cSrcweir /* Thread Local Text Encoding */
985cdf0e10cSrcweir /*****************************************************************************/
osl_thread_textencoding_init_Impl(void)986cdf0e10cSrcweir static void osl_thread_textencoding_init_Impl (void)
987cdf0e10cSrcweir {
988cdf0e10cSrcweir     rtl_TextEncoding defaultEncoding;
989cdf0e10cSrcweir     const char *     pszEncoding;
990cdf0e10cSrcweir 
991cdf0e10cSrcweir     /* create thread specific data key */
992cdf0e10cSrcweir     pthread_key_create (&(g_thread.m_textencoding.m_key), NULL);
993cdf0e10cSrcweir 
994cdf0e10cSrcweir     /* determine default text encoding */
995cdf0e10cSrcweir     pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
996cdf0e10cSrcweir     if (pszEncoding)
997cdf0e10cSrcweir         defaultEncoding = atoi(pszEncoding);
998cdf0e10cSrcweir     else
999cdf0e10cSrcweir         defaultEncoding = osl_getTextEncodingFromLocale(NULL);
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir     OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir     /*
1004cdf0e10cSrcweir     Tools string functions call abort() on an unknown encoding so ASCII
100574cbd1f1SMatthias Seidel     is a meaningful fallback regardless whether the assertion makes sense.
1006cdf0e10cSrcweir     */
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir     if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding )
1009cdf0e10cSrcweir         defaultEncoding = RTL_TEXTENCODING_ASCII_US;
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir     g_thread.m_textencoding.m_default = defaultEncoding;
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir /*****************************************************************************/
1015cdf0e10cSrcweir /* osl_getThreadTextEncoding */
1016cdf0e10cSrcweir /*****************************************************************************/
osl_getThreadTextEncoding()1017cdf0e10cSrcweir rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding()
1018cdf0e10cSrcweir {
1019cdf0e10cSrcweir     rtl_TextEncoding threadEncoding;
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir     pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
1022cdf0e10cSrcweir 
1023cdf0e10cSrcweir     /* check for thread specific encoding, use default if not set */
1024cdf0e10cSrcweir     threadEncoding = SAL_INT_CAST(
1025cdf0e10cSrcweir         rtl_TextEncoding,
1026cdf0e10cSrcweir         (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key));
1027cdf0e10cSrcweir     if (0 == threadEncoding)
1028cdf0e10cSrcweir         threadEncoding = g_thread.m_textencoding.m_default;
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir     return threadEncoding;
1031cdf0e10cSrcweir }
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir /*****************************************************************************/
1034cdf0e10cSrcweir /* osl_setThreadTextEncoding */
1035cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadTextEncoding(rtl_TextEncoding Encoding)1036cdf0e10cSrcweir rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
1037cdf0e10cSrcweir {
1038cdf0e10cSrcweir     rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir     /* save encoding in thread local storage */
1041cdf0e10cSrcweir     pthread_setspecific (
1042cdf0e10cSrcweir         g_thread.m_textencoding.m_key,
1043cdf0e10cSrcweir         (void*) SAL_INT_CAST(sal_uIntPtr, Encoding));
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir     return oldThreadEncoding;
1046cdf0e10cSrcweir }
1047