xref: /aoo41x/main/sal/osl/unx/thread.c (revision 647f063d)
1*647f063dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*647f063dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*647f063dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*647f063dSAndrew Rist  * distributed with this work for additional information
6*647f063dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*647f063dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*647f063dSAndrew Rist  * "License"); you may not use this file except in compliance
9*647f063dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*647f063dSAndrew Rist  *
11*647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*647f063dSAndrew Rist  *
13*647f063dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*647f063dSAndrew Rist  * software distributed under the License is distributed on an
15*647f063dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*647f063dSAndrew Rist  * KIND, either express or implied.  See the License for the
17*647f063dSAndrew Rist  * specific language governing permissions and limitations
18*647f063dSAndrew Rist  * under the License.
19*647f063dSAndrew Rist  *
20*647f063dSAndrew Rist  *************************************************************/
21*647f063dSAndrew Rist 
22*647f063dSAndrew 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);
189cdf0e10cSrcweir 		(*ppImpl) = 0;
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 	{
301cdf0e10cSrcweir 	    OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n",
302cdf0e10cSrcweir 			      nRet, strerror(nRet));
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 		pthread_mutex_unlock (&(pImpl->m_Lock));
305cdf0e10cSrcweir 		osl_thread_destruct_Impl (&pImpl);
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 		return (0);
308cdf0e10cSrcweir 	}
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 	/* wait for change from STARTUP to ACTIVE state */
311cdf0e10cSrcweir 	while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP)
312cdf0e10cSrcweir 	{
313cdf0e10cSrcweir 		/* wait until STARTUP flag is cleared */
314cdf0e10cSrcweir 		pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
315cdf0e10cSrcweir         pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
316cdf0e10cSrcweir 		pthread_cleanup_pop (0);
317cdf0e10cSrcweir     }
318cdf0e10cSrcweir 
319cdf0e10cSrcweir     pthread_mutex_unlock (&(pImpl->m_Lock));
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 	return ((oslThread)(pImpl));
322cdf0e10cSrcweir }
323cdf0e10cSrcweir 
324cdf0e10cSrcweir /*****************************************************************************/
325cdf0e10cSrcweir /* osl_createThread */
326cdf0e10cSrcweir /*****************************************************************************/
osl_createThread(oslWorkerFunction pWorker,void * pThreadData)327cdf0e10cSrcweir oslThread osl_createThread (
328cdf0e10cSrcweir 	oslWorkerFunction pWorker,
329cdf0e10cSrcweir 	void *            pThreadData)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir     return osl_thread_create_Impl (
332cdf0e10cSrcweir 		pWorker,
333cdf0e10cSrcweir 		pThreadData,
334cdf0e10cSrcweir 		THREADIMPL_FLAGS_ATTACHED);
335cdf0e10cSrcweir }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir /*****************************************************************************/
338cdf0e10cSrcweir /* osl_createSuspendedThread */
339cdf0e10cSrcweir /*****************************************************************************/
osl_createSuspendedThread(oslWorkerFunction pWorker,void * pThreadData)340cdf0e10cSrcweir oslThread osl_createSuspendedThread (
341cdf0e10cSrcweir 	oslWorkerFunction pWorker,
342cdf0e10cSrcweir 	void *            pThreadData)
343cdf0e10cSrcweir {
344cdf0e10cSrcweir     return osl_thread_create_Impl (
345cdf0e10cSrcweir 		pWorker,
346cdf0e10cSrcweir 		pThreadData,
347cdf0e10cSrcweir 		THREADIMPL_FLAGS_ATTACHED |
348cdf0e10cSrcweir 		THREADIMPL_FLAGS_SUSPENDED );
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir /*****************************************************************************/
352cdf0e10cSrcweir /* osl_destroyThread */
353cdf0e10cSrcweir /*****************************************************************************/
osl_destroyThread(oslThread Thread)354cdf0e10cSrcweir void SAL_CALL osl_destroyThread(oslThread Thread)
355cdf0e10cSrcweir {
356cdf0e10cSrcweir     if (Thread != NULL) {
357cdf0e10cSrcweir         Thread_Impl * impl = (Thread_Impl *) Thread;
358cdf0e10cSrcweir         int active;
359cdf0e10cSrcweir         pthread_mutex_lock(&impl->m_Lock);
360cdf0e10cSrcweir         active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0;
361cdf0e10cSrcweir         impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED;
362cdf0e10cSrcweir         pthread_mutex_unlock(&impl->m_Lock);
363cdf0e10cSrcweir         if (!active) {
364cdf0e10cSrcweir             osl_thread_destruct_Impl(&impl);
365cdf0e10cSrcweir         }
366cdf0e10cSrcweir     }
367cdf0e10cSrcweir }
368cdf0e10cSrcweir 
369cdf0e10cSrcweir /*****************************************************************************/
370cdf0e10cSrcweir /* osl_resumeThread */
371cdf0e10cSrcweir /*****************************************************************************/
osl_resumeThread(oslThread Thread)372cdf0e10cSrcweir void SAL_CALL osl_resumeThread(oslThread Thread)
373cdf0e10cSrcweir {
374cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
375cdf0e10cSrcweir 
376cdf0e10cSrcweir 	OSL_ASSERT(pImpl);
377cdf0e10cSrcweir 	if (!pImpl)
378cdf0e10cSrcweir 		return; /* EINVAL */
379cdf0e10cSrcweir 
380cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
381cdf0e10cSrcweir 
382cdf0e10cSrcweir 	if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
383cdf0e10cSrcweir     {
384cdf0e10cSrcweir 		/* clear SUSPENDED flag */
385cdf0e10cSrcweir 		pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
386cdf0e10cSrcweir 		pthread_cond_signal (&(pImpl->m_Cond));
387cdf0e10cSrcweir     }
388cdf0e10cSrcweir 
389cdf0e10cSrcweir 	pthread_mutex_unlock (&(pImpl->m_Lock));
390cdf0e10cSrcweir }
391cdf0e10cSrcweir 
392cdf0e10cSrcweir /*****************************************************************************/
393cdf0e10cSrcweir /* osl_suspendThread */
394cdf0e10cSrcweir /*****************************************************************************/
osl_suspendThread(oslThread Thread)395cdf0e10cSrcweir void SAL_CALL osl_suspendThread(oslThread Thread)
396cdf0e10cSrcweir {
397cdf0e10cSrcweir     Thread_Impl* pImpl= (Thread_Impl*)Thread;
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 	OSL_ASSERT(pImpl);
400cdf0e10cSrcweir 	if (!pImpl)
401cdf0e10cSrcweir 		return; /* EINVAL */
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
404cdf0e10cSrcweir 
405cdf0e10cSrcweir 	pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir 	if (pthread_equal (pthread_self(), pImpl->m_hThread))
408cdf0e10cSrcweir     {
409cdf0e10cSrcweir 		/* self suspend */
410cdf0e10cSrcweir         while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
411cdf0e10cSrcweir         {
412cdf0e10cSrcweir             /* wait until SUSPENDED flag is cleared */
413cdf0e10cSrcweir 			pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
414cdf0e10cSrcweir 			pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
415cdf0e10cSrcweir 			pthread_cleanup_pop (0);
416cdf0e10cSrcweir         }
417cdf0e10cSrcweir     }
418cdf0e10cSrcweir 
419cdf0e10cSrcweir 	pthread_mutex_unlock (&(pImpl->m_Lock));
420cdf0e10cSrcweir }
421cdf0e10cSrcweir 
422cdf0e10cSrcweir /*****************************************************************************/
423cdf0e10cSrcweir /* osl_isThreadRunning */
424cdf0e10cSrcweir /*****************************************************************************/
osl_isThreadRunning(const oslThread Thread)425cdf0e10cSrcweir sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
426cdf0e10cSrcweir {
427cdf0e10cSrcweir 	sal_Bool active;
428cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 	if (!pImpl)
431cdf0e10cSrcweir 		return sal_False;
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
434cdf0e10cSrcweir 	active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
435cdf0e10cSrcweir 	pthread_mutex_unlock (&(pImpl->m_Lock));
436cdf0e10cSrcweir 
437cdf0e10cSrcweir 	return (active);
438cdf0e10cSrcweir }
439cdf0e10cSrcweir 
440cdf0e10cSrcweir /*****************************************************************************/
441cdf0e10cSrcweir /* osl_joinWithThread */
442cdf0e10cSrcweir /*****************************************************************************/
osl_joinWithThread(oslThread Thread)443cdf0e10cSrcweir void SAL_CALL osl_joinWithThread(oslThread Thread)
444cdf0e10cSrcweir {
445cdf0e10cSrcweir     pthread_t thread;
446cdf0e10cSrcweir 	int attached;
447cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
448cdf0e10cSrcweir 
449cdf0e10cSrcweir 	if (!pImpl)
450cdf0e10cSrcweir 		return;
451cdf0e10cSrcweir 
452cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
453cdf0e10cSrcweir 
454cdf0e10cSrcweir 	if (pthread_equal (pthread_self(), pImpl->m_hThread))
455cdf0e10cSrcweir 	{
456cdf0e10cSrcweir 		/* self join */
457cdf0e10cSrcweir 		pthread_mutex_unlock (&(pImpl->m_Lock));
458cdf0e10cSrcweir 		return; /* EDEADLK */
459cdf0e10cSrcweir 	}
460cdf0e10cSrcweir 
461cdf0e10cSrcweir     thread = pImpl->m_hThread;
462cdf0e10cSrcweir 	attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0);
463cdf0e10cSrcweir 	pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED;
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 	pthread_mutex_unlock (&(pImpl->m_Lock));
466cdf0e10cSrcweir 
467cdf0e10cSrcweir 	if (attached)
468cdf0e10cSrcweir 	{
469cdf0e10cSrcweir 		/* install cleanup handler to ensure consistent flags and state */
470cdf0e10cSrcweir 		pthread_cleanup_push (
471cdf0e10cSrcweir 			osl_thread_join_cleanup_Impl, (void*)thread);
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 		/* join */
474cdf0e10cSrcweir 		pthread_join (thread, NULL);
475cdf0e10cSrcweir 
476cdf0e10cSrcweir 		/* remove cleanup handler */
477cdf0e10cSrcweir 		pthread_cleanup_pop (0);
478cdf0e10cSrcweir 	}
479cdf0e10cSrcweir }
480cdf0e10cSrcweir 
481cdf0e10cSrcweir /*****************************************************************************/
482cdf0e10cSrcweir /* osl_terminateThread */
483cdf0e10cSrcweir /*****************************************************************************/
osl_terminateThread(oslThread Thread)484cdf0e10cSrcweir void SAL_CALL osl_terminateThread(oslThread Thread)
485cdf0e10cSrcweir {
486cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
487cdf0e10cSrcweir 
488cdf0e10cSrcweir 	OSL_ASSERT(pImpl);
489cdf0e10cSrcweir 	if (!pImpl)
490cdf0e10cSrcweir 		return; /* EINVAL */
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
493cdf0e10cSrcweir 
494cdf0e10cSrcweir 	if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
495cdf0e10cSrcweir     {
496cdf0e10cSrcweir 		/* clear SUSPENDED flag */
497cdf0e10cSrcweir 		pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
498cdf0e10cSrcweir 		pthread_cond_signal (&(pImpl->m_Cond));
499cdf0e10cSrcweir     }
500cdf0e10cSrcweir 
501cdf0e10cSrcweir 	pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
502cdf0e10cSrcweir 
503cdf0e10cSrcweir 	pthread_mutex_unlock (&(pImpl->m_Lock));
504cdf0e10cSrcweir }
505cdf0e10cSrcweir 
506cdf0e10cSrcweir /*****************************************************************************/
507cdf0e10cSrcweir /* osl_scheduleThread */
508cdf0e10cSrcweir /*****************************************************************************/
osl_scheduleThread(oslThread Thread)509cdf0e10cSrcweir sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
510cdf0e10cSrcweir {
511cdf0e10cSrcweir 	int terminate;
512cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
513cdf0e10cSrcweir 
514cdf0e10cSrcweir 	OSL_ASSERT(pImpl);
515cdf0e10cSrcweir 	if (!pImpl)
516cdf0e10cSrcweir 		return sal_False; /* EINVAL */
517cdf0e10cSrcweir 
518cdf0e10cSrcweir 	OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread));
519cdf0e10cSrcweir 	if (!(pthread_equal (pthread_self(), pImpl->m_hThread)))
520cdf0e10cSrcweir 		return sal_False; /* EINVAL */
521cdf0e10cSrcweir 
522cdf0e10cSrcweir 	pthread_testcancel();
523cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
524cdf0e10cSrcweir 
525cdf0e10cSrcweir 	while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
526cdf0e10cSrcweir     {
527cdf0e10cSrcweir 		/* wait until SUSPENDED flag is cleared */
528cdf0e10cSrcweir 		pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
529cdf0e10cSrcweir 		pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
530cdf0e10cSrcweir 		pthread_cleanup_pop (0);
531cdf0e10cSrcweir     }
532cdf0e10cSrcweir 
533cdf0e10cSrcweir 	terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
534cdf0e10cSrcweir 
535cdf0e10cSrcweir 	pthread_mutex_unlock(&(pImpl->m_Lock));
536cdf0e10cSrcweir 	pthread_testcancel();
537cdf0e10cSrcweir 
538cdf0e10cSrcweir 	return (terminate == 0);
539cdf0e10cSrcweir }
540cdf0e10cSrcweir 
541cdf0e10cSrcweir /*****************************************************************************/
542cdf0e10cSrcweir /* osl_waitThread */
543cdf0e10cSrcweir /*****************************************************************************/
osl_waitThread(const TimeValue * pDelay)544cdf0e10cSrcweir void SAL_CALL osl_waitThread(const TimeValue* pDelay)
545cdf0e10cSrcweir {
546cdf0e10cSrcweir 	if (pDelay)
547cdf0e10cSrcweir 	{
548cdf0e10cSrcweir 		struct timespec delay;
549cdf0e10cSrcweir 
550cdf0e10cSrcweir 		SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec);
551cdf0e10cSrcweir 
552cdf0e10cSrcweir 		SLEEP_TIMESPEC(delay);
553cdf0e10cSrcweir 	}
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
556cdf0e10cSrcweir /*****************************************************************************/
557cdf0e10cSrcweir /* osl_yieldThread */
558cdf0e10cSrcweir /*
559cdf0e10cSrcweir 	Note that POSIX scheduling _really_ requires threads to call this
560cdf0e10cSrcweir 	functions, since a thread only reschedules to other thread, when
561cdf0e10cSrcweir     it blocks (sleep, blocking I/O) OR calls sched_yield().
562cdf0e10cSrcweir */
563cdf0e10cSrcweir /*****************************************************************************/
osl_yieldThread()564cdf0e10cSrcweir void SAL_CALL osl_yieldThread()
565cdf0e10cSrcweir {
566cdf0e10cSrcweir     sched_yield();
567cdf0e10cSrcweir }
568cdf0e10cSrcweir 
osl_setThreadName(char const * name)569cdf0e10cSrcweir void SAL_CALL osl_setThreadName(char const * name) {
570cdf0e10cSrcweir #if defined LINUX
571cdf0e10cSrcweir     if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) {
572cdf0e10cSrcweir         OSL_TRACE(
573cdf0e10cSrcweir             "%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX,
574cdf0e10cSrcweir             errno);
575cdf0e10cSrcweir     }
576cdf0e10cSrcweir #else
577cdf0e10cSrcweir     (void) name;
578cdf0e10cSrcweir #endif
579cdf0e10cSrcweir }
580cdf0e10cSrcweir 
581cdf0e10cSrcweir /*****************************************************************************/
582cdf0e10cSrcweir /* osl_getThreadIdentifier @@@ see TODO @@@ */
583cdf0e10cSrcweir /*****************************************************************************/
584cdf0e10cSrcweir 
585cdf0e10cSrcweir #define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
586cdf0e10cSrcweir 
587cdf0e10cSrcweir typedef struct _HashEntry
588cdf0e10cSrcweir {
589cdf0e10cSrcweir 	pthread_t         Handle;
590cdf0e10cSrcweir 	sal_uInt16	      Ident;
591cdf0e10cSrcweir 	struct _HashEntry *Next;
592cdf0e10cSrcweir } HashEntry;
593cdf0e10cSrcweir 
594cdf0e10cSrcweir static HashEntry* HashTable[31];
595cdf0e10cSrcweir static int HashSize = sizeof(HashTable) / sizeof(HashTable[0]);
596cdf0e10cSrcweir 
597cdf0e10cSrcweir static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER;
598cdf0e10cSrcweir 
599cdf0e10cSrcweir static sal_uInt16 LastIdent = 0;
600cdf0e10cSrcweir 
lookupThreadId(pthread_t hThread)601cdf0e10cSrcweir static sal_uInt16 lookupThreadId (pthread_t hThread)
602cdf0e10cSrcweir {
603cdf0e10cSrcweir 	HashEntry *pEntry;
604cdf0e10cSrcweir 
605cdf0e10cSrcweir 	pthread_mutex_lock(&HashLock);
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 		pEntry = HashTable[HASHID(hThread)];
608cdf0e10cSrcweir 		while (pEntry != NULL)
609cdf0e10cSrcweir 		{
610cdf0e10cSrcweir 			if (pthread_equal(pEntry->Handle, hThread))
611cdf0e10cSrcweir 			{
612cdf0e10cSrcweir 				pthread_mutex_unlock(&HashLock);
613cdf0e10cSrcweir 				return (pEntry->Ident);
614cdf0e10cSrcweir 			}
615cdf0e10cSrcweir 			pEntry = pEntry->Next;
616cdf0e10cSrcweir 		}
617cdf0e10cSrcweir 
618cdf0e10cSrcweir 	pthread_mutex_unlock(&HashLock);
619cdf0e10cSrcweir 
620cdf0e10cSrcweir 	return (0);
621cdf0e10cSrcweir }
622cdf0e10cSrcweir 
insertThreadId(pthread_t hThread)623cdf0e10cSrcweir static sal_uInt16 insertThreadId (pthread_t hThread)
624cdf0e10cSrcweir {
625cdf0e10cSrcweir 	HashEntry *pEntry, *pInsert = NULL;
626cdf0e10cSrcweir 
627cdf0e10cSrcweir 	pthread_mutex_lock(&HashLock);
628cdf0e10cSrcweir 
629cdf0e10cSrcweir 	pEntry = HashTable[HASHID(hThread)];
630cdf0e10cSrcweir 
631cdf0e10cSrcweir 	while (pEntry != NULL)
632cdf0e10cSrcweir 	{
633cdf0e10cSrcweir 		if (pthread_equal(pEntry->Handle, hThread))
634cdf0e10cSrcweir 			break;
635cdf0e10cSrcweir 
636cdf0e10cSrcweir 		pInsert = pEntry;
637cdf0e10cSrcweir 		pEntry = pEntry->Next;
638cdf0e10cSrcweir 	}
639cdf0e10cSrcweir 
640cdf0e10cSrcweir 	if (pEntry == NULL)
641cdf0e10cSrcweir 	{
642cdf0e10cSrcweir 		pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
643cdf0e10cSrcweir 
644cdf0e10cSrcweir 		pEntry->Handle = hThread;
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 		++ LastIdent;
647cdf0e10cSrcweir 
648cdf0e10cSrcweir         if ( LastIdent == 0 )
649cdf0e10cSrcweir             LastIdent = 1;
650cdf0e10cSrcweir 
651cdf0e10cSrcweir         pEntry->Ident  = LastIdent;
652cdf0e10cSrcweir 
653cdf0e10cSrcweir 		if (pInsert)
654cdf0e10cSrcweir 			pInsert->Next = pEntry;
655cdf0e10cSrcweir 		else
656cdf0e10cSrcweir 			HashTable[HASHID(hThread)] = pEntry;
657cdf0e10cSrcweir 	}
658cdf0e10cSrcweir 
659cdf0e10cSrcweir 	pthread_mutex_unlock(&HashLock);
660cdf0e10cSrcweir 
661cdf0e10cSrcweir 	return (pEntry->Ident);
662cdf0e10cSrcweir }
663cdf0e10cSrcweir 
removeThreadId(pthread_t hThread)664cdf0e10cSrcweir static void removeThreadId (pthread_t hThread)
665cdf0e10cSrcweir {
666cdf0e10cSrcweir 	HashEntry *pEntry, *pRemove = NULL;
667cdf0e10cSrcweir 
668cdf0e10cSrcweir 	pthread_mutex_lock(&HashLock);
669cdf0e10cSrcweir 
670cdf0e10cSrcweir 	pEntry = HashTable[HASHID(hThread)];
671cdf0e10cSrcweir 	while (pEntry != NULL)
672cdf0e10cSrcweir 	{
673cdf0e10cSrcweir 		if (pthread_equal(pEntry->Handle, hThread))
674cdf0e10cSrcweir 			break;
675cdf0e10cSrcweir 
676cdf0e10cSrcweir 		pRemove = pEntry;
677cdf0e10cSrcweir 		pEntry = pEntry->Next;
678cdf0e10cSrcweir 	}
679cdf0e10cSrcweir 
680cdf0e10cSrcweir 	if (pEntry != NULL)
681cdf0e10cSrcweir 	{
682cdf0e10cSrcweir 		if (pRemove)
683cdf0e10cSrcweir 			pRemove->Next = pEntry->Next;
684cdf0e10cSrcweir 		else
685cdf0e10cSrcweir 			HashTable[HASHID(hThread)] = pEntry->Next;
686cdf0e10cSrcweir 
687cdf0e10cSrcweir 		free(pEntry);
688cdf0e10cSrcweir 	}
689cdf0e10cSrcweir 
690cdf0e10cSrcweir 	pthread_mutex_unlock(&HashLock);
691cdf0e10cSrcweir }
692cdf0e10cSrcweir 
osl_getThreadIdentifier(oslThread Thread)693cdf0e10cSrcweir oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
694cdf0e10cSrcweir {
695cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
696cdf0e10cSrcweir 	sal_uInt16   Ident;
697cdf0e10cSrcweir 
698cdf0e10cSrcweir 	if (pImpl)
699cdf0e10cSrcweir 		Ident = pImpl->m_Ident;
700cdf0e10cSrcweir 	else
701cdf0e10cSrcweir 	{
702cdf0e10cSrcweir 		/* current thread */
703cdf0e10cSrcweir 		pthread_t current = pthread_self();
704cdf0e10cSrcweir 
705cdf0e10cSrcweir 		Ident = lookupThreadId (current);
706cdf0e10cSrcweir 		if (Ident == 0)
707cdf0e10cSrcweir 			/* @@@ see TODO: alien pthread_self() @@@ */
708cdf0e10cSrcweir 			Ident = insertThreadId (current);
709cdf0e10cSrcweir 	}
710cdf0e10cSrcweir 
711cdf0e10cSrcweir 	return ((oslThreadIdentifier)(Ident));
712cdf0e10cSrcweir }
713cdf0e10cSrcweir 
714cdf0e10cSrcweir /*****************************************************************************
715cdf0e10cSrcweir     @@@ see TODO @@@
716cdf0e10cSrcweir 	osl_thread_priority_init_Impl
717cdf0e10cSrcweir 
718cdf0e10cSrcweir 	set the base-priority of the main-thread to
719cdf0e10cSrcweir 	oslThreadPriorityNormal (64) since 0 (lowest) is
720cdf0e10cSrcweir 	the system default. This behaviour collides with
721cdf0e10cSrcweir 	our enum-priority definition (highest..normal..lowest).
722cdf0e10cSrcweir 	A  normaluser will expect the main-thread of an app.
723cdf0e10cSrcweir 	to have the "normal" priority.
724cdf0e10cSrcweir 
725cdf0e10cSrcweir *****************************************************************************/
osl_thread_priority_init_Impl(void)726cdf0e10cSrcweir static void osl_thread_priority_init_Impl (void)
727cdf0e10cSrcweir {
728cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
729cdf0e10cSrcweir     struct sched_param param;
730cdf0e10cSrcweir     int policy=0;
731cdf0e10cSrcweir     int nRet=0;
732cdf0e10cSrcweir 
733cdf0e10cSrcweir /* @@@ see TODO: calling thread may not be main thread @@@ */
734cdf0e10cSrcweir 
735cdf0e10cSrcweir     if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
736cdf0e10cSrcweir     {
737cdf0e10cSrcweir         OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet));
738cdf0e10cSrcweir         return;
739cdf0e10cSrcweir     }
740cdf0e10cSrcweir 
741cdf0e10cSrcweir #if defined (SOLARIS)
742cdf0e10cSrcweir     if ( policy >= _SCHED_NEXT)
743cdf0e10cSrcweir     {
744cdf0e10cSrcweir         /* mfe: pthread_getschedparam on Solaris has a possible Bug */
745cdf0e10cSrcweir         /*      one gets 959917873 as the policy                    */
746cdf0e10cSrcweir         /*      so set the policy to a default one                  */
747cdf0e10cSrcweir         policy=SCHED_OTHER;
748cdf0e10cSrcweir     }
749cdf0e10cSrcweir #endif /* SOLARIS */
750cdf0e10cSrcweir 
751cdf0e10cSrcweir     if ((nRet = sched_get_priority_min(policy) ) != -1)
752cdf0e10cSrcweir     {
753cdf0e10cSrcweir         OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet);
754cdf0e10cSrcweir         g_thread.m_priority.m_Lowest=nRet;
755cdf0e10cSrcweir     }
756cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
757cdf0e10cSrcweir     else
758cdf0e10cSrcweir     {
759cdf0e10cSrcweir         fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
760cdf0e10cSrcweir     }
761cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
762cdf0e10cSrcweir 
763cdf0e10cSrcweir     if ((nRet = sched_get_priority_max(policy) ) != -1)
764cdf0e10cSrcweir     {
765cdf0e10cSrcweir         OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet);
766cdf0e10cSrcweir         g_thread.m_priority.m_Highest=nRet;
767cdf0e10cSrcweir     }
768cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
769cdf0e10cSrcweir     else
770cdf0e10cSrcweir     {
771cdf0e10cSrcweir         fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
772cdf0e10cSrcweir     }
773cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
774cdf0e10cSrcweir 
775cdf0e10cSrcweir     g_thread.m_priority.m_Normal =
776cdf0e10cSrcweir 		(g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2;
777cdf0e10cSrcweir     g_thread.m_priority.m_Below_Normal =
778cdf0e10cSrcweir 		(g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal)  / 2;
779cdf0e10cSrcweir     g_thread.m_priority.m_Above_Normal =
780cdf0e10cSrcweir 		(g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2;
781cdf0e10cSrcweir 
782cdf0e10cSrcweir /* @@@ set prio of calling (not main) thread (?) @@@ */
783cdf0e10cSrcweir 
784cdf0e10cSrcweir     param.sched_priority= g_thread.m_priority.m_Normal;
785cdf0e10cSrcweir 
786cdf0e10cSrcweir     if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
787cdf0e10cSrcweir     {
788cdf0e10cSrcweir         OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet));
789cdf0e10cSrcweir         OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority);
790cdf0e10cSrcweir     }
791cdf0e10cSrcweir 
792cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
793cdf0e10cSrcweir }
794cdf0e10cSrcweir 
795cdf0e10cSrcweir /*****************************************************************************/
796cdf0e10cSrcweir /* osl_setThreadPriority */
797cdf0e10cSrcweir /*
798cdf0e10cSrcweir 	Impl-Notes: contrary to solaris-docu, which claims
799cdf0e10cSrcweir 	valid priority-levels from 0 .. INT_MAX, only the
800cdf0e10cSrcweir 	range 0..127 is accepted. (0 lowest, 127 highest)
801cdf0e10cSrcweir */
802cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadPriority(oslThread Thread,oslThreadPriority Priority)803cdf0e10cSrcweir void SAL_CALL osl_setThreadPriority (
804cdf0e10cSrcweir 	oslThread         Thread,
805cdf0e10cSrcweir 	oslThreadPriority Priority)
806cdf0e10cSrcweir {
807cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
808cdf0e10cSrcweir 
809cdf0e10cSrcweir 	struct sched_param Param;
810cdf0e10cSrcweir 	int policy;
811cdf0e10cSrcweir     int nRet;
812cdf0e10cSrcweir 
813cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
816cdf0e10cSrcweir 
817cdf0e10cSrcweir 	OSL_ASSERT(pImpl);
818cdf0e10cSrcweir 	if (!pImpl)
819cdf0e10cSrcweir 		return; /* EINVAL */
820cdf0e10cSrcweir 
821cdf0e10cSrcweir #ifdef NO_PTHREAD_PRIORITY
822cdf0e10cSrcweir     (void) Priority; /* unused */
823cdf0e10cSrcweir #else /* NO_PTHREAD_PRIORITY */
824cdf0e10cSrcweir 
825cdf0e10cSrcweir     if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
826cdf0e10cSrcweir 		return; /* ESRCH */
827cdf0e10cSrcweir 
828cdf0e10cSrcweir #if defined (SOLARIS)
829cdf0e10cSrcweir     if ( policy >= _SCHED_NEXT)
830cdf0e10cSrcweir     {
831cdf0e10cSrcweir         /* mfe: pthread_getschedparam on Solaris has a possible Bug */
832cdf0e10cSrcweir         /*      one gets 959917873 as the policy                   */
833cdf0e10cSrcweir         /*      so set the policy to a default one                 */
834cdf0e10cSrcweir         policy=SCHED_OTHER;
835cdf0e10cSrcweir     }
836cdf0e10cSrcweir #endif /* SOLARIS */
837cdf0e10cSrcweir 
838cdf0e10cSrcweir 	pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
839cdf0e10cSrcweir 
840cdf0e10cSrcweir     switch(Priority)
841cdf0e10cSrcweir     {
842cdf0e10cSrcweir         case osl_Thread_PriorityHighest:
843cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Highest;
844cdf0e10cSrcweir             break;
845cdf0e10cSrcweir 
846cdf0e10cSrcweir         case osl_Thread_PriorityAboveNormal:
847cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Above_Normal;
848cdf0e10cSrcweir             break;
849cdf0e10cSrcweir 
850cdf0e10cSrcweir         case osl_Thread_PriorityNormal:
851cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Normal;
852cdf0e10cSrcweir             break;
853cdf0e10cSrcweir 
854cdf0e10cSrcweir         case osl_Thread_PriorityBelowNormal:
855cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Below_Normal;
856cdf0e10cSrcweir             break;
857cdf0e10cSrcweir 
858cdf0e10cSrcweir         case osl_Thread_PriorityLowest:
859cdf0e10cSrcweir             Param.sched_priority= g_thread.m_priority.m_Lowest;
860cdf0e10cSrcweir             break;
861cdf0e10cSrcweir 
862cdf0e10cSrcweir         case osl_Thread_PriorityUnknown:
863cdf0e10cSrcweir             OSL_ASSERT(sal_False);		/* only fools try this...*/
864cdf0e10cSrcweir 
865cdf0e10cSrcweir             /* let release-version behave friendly */
866cdf0e10cSrcweir             return;
867cdf0e10cSrcweir 
868cdf0e10cSrcweir         default:
869cdf0e10cSrcweir             /* enum expanded, but forgotten here...*/
870cdf0e10cSrcweir             OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
871cdf0e10cSrcweir 
872cdf0e10cSrcweir             /* let release-version behave friendly */
873cdf0e10cSrcweir             return;
874cdf0e10cSrcweir     }
875cdf0e10cSrcweir 
876cdf0e10cSrcweir     if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
877cdf0e10cSrcweir     {
878cdf0e10cSrcweir         OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet));
879cdf0e10cSrcweir     }
880cdf0e10cSrcweir 
881cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
882cdf0e10cSrcweir }
883cdf0e10cSrcweir 
884cdf0e10cSrcweir /*****************************************************************************/
885cdf0e10cSrcweir /* osl_getThreadPriority */
886cdf0e10cSrcweir /*****************************************************************************/
osl_getThreadPriority(const oslThread Thread)887cdf0e10cSrcweir oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
888cdf0e10cSrcweir {
889cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
890cdf0e10cSrcweir 
891cdf0e10cSrcweir 	struct sched_param Param;
892cdf0e10cSrcweir 	int Policy;
893cdf0e10cSrcweir 
894cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
895cdf0e10cSrcweir 
896cdf0e10cSrcweir 	oslThreadPriority Priority = osl_Thread_PriorityNormal;
897cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)Thread;
898cdf0e10cSrcweir 
899cdf0e10cSrcweir 	OSL_ASSERT(pImpl);
900cdf0e10cSrcweir 	if (!pImpl)
901cdf0e10cSrcweir 		return osl_Thread_PriorityUnknown; /* EINVAL */
902cdf0e10cSrcweir 
903cdf0e10cSrcweir #ifndef NO_PTHREAD_PRIORITY
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 	if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0)
906cdf0e10cSrcweir 		return osl_Thread_PriorityUnknown; /* ESRCH */
907cdf0e10cSrcweir 
908cdf0e10cSrcweir 	pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
909cdf0e10cSrcweir 
910cdf0e10cSrcweir 	/* map pthread priority to enum */
911cdf0e10cSrcweir 	if (Param.sched_priority==g_thread.m_priority.m_Highest)
912cdf0e10cSrcweir 	{
913cdf0e10cSrcweir 		/* 127 - highest */
914cdf0e10cSrcweir 		Priority= osl_Thread_PriorityHighest;
915cdf0e10cSrcweir 	}
916cdf0e10cSrcweir 	else if (Param.sched_priority > g_thread.m_priority.m_Normal)
917cdf0e10cSrcweir 	{
918cdf0e10cSrcweir 		/* 65..126 - above normal */
919cdf0e10cSrcweir 		Priority= osl_Thread_PriorityAboveNormal;
920cdf0e10cSrcweir 	}
921cdf0e10cSrcweir 	else if (Param.sched_priority == g_thread.m_priority.m_Normal)
922cdf0e10cSrcweir 	{
923cdf0e10cSrcweir 		/* normal */
924cdf0e10cSrcweir 		Priority= osl_Thread_PriorityNormal;
925cdf0e10cSrcweir 	}
926cdf0e10cSrcweir 	else if (Param.sched_priority > g_thread.m_priority.m_Lowest)
927cdf0e10cSrcweir 	{
928cdf0e10cSrcweir 		/* 63..1 -below normal */
929cdf0e10cSrcweir 		Priority= osl_Thread_PriorityBelowNormal;
930cdf0e10cSrcweir 	}
931cdf0e10cSrcweir 	else if (Param.sched_priority == g_thread.m_priority.m_Lowest)
932cdf0e10cSrcweir 	{
933cdf0e10cSrcweir 		/* 0 - lowest */
934cdf0e10cSrcweir 		Priority= osl_Thread_PriorityLowest;
935cdf0e10cSrcweir 	}
936cdf0e10cSrcweir 	else
937cdf0e10cSrcweir 	{
938cdf0e10cSrcweir 		/* unknown */
939cdf0e10cSrcweir 		Priority= osl_Thread_PriorityUnknown;
940cdf0e10cSrcweir 	}
941cdf0e10cSrcweir 
942cdf0e10cSrcweir #endif /* NO_PTHREAD_PRIORITY */
943cdf0e10cSrcweir 
944cdf0e10cSrcweir 	return Priority;
945cdf0e10cSrcweir }
946cdf0e10cSrcweir 
947cdf0e10cSrcweir /*****************************************************************************/
948cdf0e10cSrcweir /* osl_createThreadKey */
949cdf0e10cSrcweir /*****************************************************************************/
osl_createThreadKey(oslThreadKeyCallbackFunction pCallback)950cdf0e10cSrcweir oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
951cdf0e10cSrcweir {
952cdf0e10cSrcweir 	pthread_key_t key;
953cdf0e10cSrcweir 
954cdf0e10cSrcweir 	if (pthread_key_create(&key, pCallback) != 0)
955cdf0e10cSrcweir 		key = 0;
956cdf0e10cSrcweir 
957cdf0e10cSrcweir 	return ((oslThreadKey)key);
958cdf0e10cSrcweir }
959cdf0e10cSrcweir 
960cdf0e10cSrcweir /*****************************************************************************/
961cdf0e10cSrcweir /* osl_destroyThreadKey */
962cdf0e10cSrcweir /*****************************************************************************/
osl_destroyThreadKey(oslThreadKey Key)963cdf0e10cSrcweir void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
964cdf0e10cSrcweir {
965cdf0e10cSrcweir 	pthread_key_delete((pthread_key_t)Key);
966cdf0e10cSrcweir }
967cdf0e10cSrcweir 
968cdf0e10cSrcweir /*****************************************************************************/
969cdf0e10cSrcweir /* osl_getThreadKeyData */
970cdf0e10cSrcweir /*****************************************************************************/
osl_getThreadKeyData(oslThreadKey Key)971cdf0e10cSrcweir void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
972cdf0e10cSrcweir {
973cdf0e10cSrcweir 	return (pthread_getspecific((pthread_key_t)Key));
974cdf0e10cSrcweir }
975cdf0e10cSrcweir 
976cdf0e10cSrcweir /*****************************************************************************/
977cdf0e10cSrcweir /* osl_setThreadKeyData */
978cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadKeyData(oslThreadKey Key,void * pData)979cdf0e10cSrcweir sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
980cdf0e10cSrcweir {
981cdf0e10cSrcweir 	return (pthread_setspecific((pthread_key_t)Key, pData) == 0);
982cdf0e10cSrcweir }
983cdf0e10cSrcweir 
984cdf0e10cSrcweir /*****************************************************************************/
985cdf0e10cSrcweir /* Thread Local Text Encoding */
986cdf0e10cSrcweir /*****************************************************************************/
osl_thread_textencoding_init_Impl(void)987cdf0e10cSrcweir static void osl_thread_textencoding_init_Impl (void)
988cdf0e10cSrcweir {
989cdf0e10cSrcweir 	rtl_TextEncoding defaultEncoding;
990cdf0e10cSrcweir 	const char *     pszEncoding;
991cdf0e10cSrcweir 
992cdf0e10cSrcweir 	/* create thread specific data key */
993cdf0e10cSrcweir 	pthread_key_create (&(g_thread.m_textencoding.m_key), NULL);
994cdf0e10cSrcweir 
995cdf0e10cSrcweir 	/* determine default text encoding */
996cdf0e10cSrcweir 	pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
997cdf0e10cSrcweir 	if (pszEncoding)
998cdf0e10cSrcweir 		defaultEncoding = atoi(pszEncoding);
999cdf0e10cSrcweir 	else
1000cdf0e10cSrcweir 		defaultEncoding = osl_getTextEncodingFromLocale(NULL);
1001cdf0e10cSrcweir 
1002cdf0e10cSrcweir 	OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir 	/*
1005cdf0e10cSrcweir 	Tools string functions call abort() on an unknown encoding so ASCII
1006cdf0e10cSrcweir 	is a meaningfull fallback regardless wether the assertion makes sense.
1007cdf0e10cSrcweir 	*/
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir 	if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding )
1010cdf0e10cSrcweir 		defaultEncoding = RTL_TEXTENCODING_ASCII_US;
1011cdf0e10cSrcweir 
1012cdf0e10cSrcweir 	g_thread.m_textencoding.m_default = defaultEncoding;
1013cdf0e10cSrcweir }
1014cdf0e10cSrcweir 
1015cdf0e10cSrcweir /*****************************************************************************/
1016cdf0e10cSrcweir /* osl_getThreadTextEncoding */
1017cdf0e10cSrcweir /*****************************************************************************/
osl_getThreadTextEncoding()1018cdf0e10cSrcweir rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding()
1019cdf0e10cSrcweir {
1020cdf0e10cSrcweir     rtl_TextEncoding threadEncoding;
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir 	pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
1023cdf0e10cSrcweir 
1024cdf0e10cSrcweir     /* check for thread specific encoding, use default if not set */
1025cdf0e10cSrcweir 	threadEncoding = SAL_INT_CAST(
1026cdf0e10cSrcweir         rtl_TextEncoding,
1027cdf0e10cSrcweir         (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key));
1028cdf0e10cSrcweir 	if (0 == threadEncoding)
1029cdf0e10cSrcweir 		threadEncoding = g_thread.m_textencoding.m_default;
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir     return threadEncoding;
1032cdf0e10cSrcweir }
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir /*****************************************************************************/
1035cdf0e10cSrcweir /* osl_setThreadTextEncoding */
1036cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadTextEncoding(rtl_TextEncoding Encoding)1037cdf0e10cSrcweir rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
1038cdf0e10cSrcweir {
1039cdf0e10cSrcweir     rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir     /* save encoding in thread local storage */
1042cdf0e10cSrcweir     pthread_setspecific (
1043cdf0e10cSrcweir         g_thread.m_textencoding.m_key,
1044cdf0e10cSrcweir         (void*) SAL_INT_CAST(sal_uIntPtr, Encoding));
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir     return oldThreadEncoding;
1047cdf0e10cSrcweir }
1048