xref: /aoo42x/main/sal/osl/unx/thread.c (revision 18a2cb5f)
1647f063dSAndrew Rist /**************************************************************
2*18a2cb5fSmseidel  *
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
10*18a2cb5fSmseidel  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*18a2cb5fSmseidel  *
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.
19*18a2cb5fSmseidel  *
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 @@@ */
73*18a2cb5fSmseidel 	short				m_Flags;
74*18a2cb5fSmseidel 	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 {
198*18a2cb5fSmseidel 	pthread_t thread;
199*18a2cb5fSmseidel 	int attached;
200*18a2cb5fSmseidel 	int destroyed;
201cdf0e10cSrcweir 	Thread_Impl* pImpl= (Thread_Impl*)pData;
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 	pthread_mutex_lock (&(pImpl->m_Lock));
204cdf0e10cSrcweir 
205*18a2cb5fSmseidel 	thread = pImpl->m_hThread;
206*18a2cb5fSmseidel 	attached = (pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) != 0;
207*18a2cb5fSmseidel 	destroyed = (pImpl->m_Flags & THREADIMPL_FLAGS_DESTROYED) != 0;
208*18a2cb5fSmseidel 	pImpl->m_Flags &= ~(THREADIMPL_FLAGS_ACTIVE | THREADIMPL_FLAGS_ATTACHED);
209cdf0e10cSrcweir 
210cdf0e10cSrcweir 	pthread_mutex_unlock (&(pImpl->m_Lock));
211cdf0e10cSrcweir 
212*18a2cb5fSmseidel 	/* release oslThreadIdentifier @@@ see TODO @@@ */
213*18a2cb5fSmseidel 	removeThreadId (thread);
214cdf0e10cSrcweir 
215*18a2cb5fSmseidel 	if (attached)
216*18a2cb5fSmseidel 	{
217*18a2cb5fSmseidel 		pthread_detach (thread);
218*18a2cb5fSmseidel 	}
219cdf0e10cSrcweir 
220*18a2cb5fSmseidel 	if (destroyed)
221*18a2cb5fSmseidel 	{
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 
236*18a2cb5fSmseidel 	pthread_mutex_lock (&(pImpl->m_Lock));
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 	/* install cleanup handler */
239*18a2cb5fSmseidel 	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;
247*18a2cb5fSmseidel 	pthread_cond_signal (&(pImpl->m_Cond));
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 	/* Check if thread is started in SUSPENDED state */
250*18a2cb5fSmseidel 	while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
251*18a2cb5fSmseidel 	{
252*18a2cb5fSmseidel 		/* 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);
256*18a2cb5fSmseidel 	}
257cdf0e10cSrcweir 
258cdf0e10cSrcweir 	/* check for SUSPENDED to TERMINATE state change */
259cdf0e10cSrcweir 	terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
260cdf0e10cSrcweir 
261*18a2cb5fSmseidel 	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;
283*18a2cb5fSmseidel 	int nRet=0;
284cdf0e10cSrcweir 
285cdf0e10cSrcweir 	pImpl = osl_thread_construct_Impl();
286*18a2cb5fSmseidel 	if (!pImpl)
287*18a2cb5fSmseidel 		return (0); /* ENOMEM */
288cdf0e10cSrcweir 
289cdf0e10cSrcweir 	pImpl->m_WorkerFunction = pWorker;
290cdf0e10cSrcweir 	pImpl->m_pData = pThreadData;
291cdf0e10cSrcweir 	pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP;
292cdf0e10cSrcweir 
293*18a2cb5fSmseidel 	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*18a2cb5fSmseidel 		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));
314*18a2cb5fSmseidel 		pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
315cdf0e10cSrcweir 		pthread_cleanup_pop (0);
316*18a2cb5fSmseidel 	}
317cdf0e10cSrcweir 
318*18a2cb5fSmseidel 	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 {
330*18a2cb5fSmseidel 	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 {
343*18a2cb5fSmseidel 	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 {
355*18a2cb5fSmseidel 	if (Thread != NULL) {
356*18a2cb5fSmseidel 		Thread_Impl * impl = (Thread_Impl *) Thread;
357*18a2cb5fSmseidel 		int active;
358*18a2cb5fSmseidel 		pthread_mutex_lock(&impl->m_Lock);
359*18a2cb5fSmseidel 		active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0;
360*18a2cb5fSmseidel 		impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED;
361*18a2cb5fSmseidel 		pthread_mutex_unlock(&impl->m_Lock);
362*18a2cb5fSmseidel 		if (!active) {
363*18a2cb5fSmseidel 			osl_thread_destruct_Impl(&impl);
364*18a2cb5fSmseidel 		}
365*18a2cb5fSmseidel 	}
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)
382*18a2cb5fSmseidel 	{
383cdf0e10cSrcweir 		/* clear SUSPENDED flag */
384cdf0e10cSrcweir 		pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
385cdf0e10cSrcweir 		pthread_cond_signal (&(pImpl->m_Cond));
386*18a2cb5fSmseidel 	}
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 {
396*18a2cb5fSmseidel 	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))
407*18a2cb5fSmseidel 	{
408cdf0e10cSrcweir 		/* self suspend */
409*18a2cb5fSmseidel 		while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
410*18a2cb5fSmseidel 		{
411*18a2cb5fSmseidel 			/* 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);
415*18a2cb5fSmseidel 		}
416*18a2cb5fSmseidel 	}
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 {
444*18a2cb5fSmseidel 	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 
460*18a2cb5fSmseidel 	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)
494*18a2cb5fSmseidel 	{
495cdf0e10cSrcweir 		/* clear SUSPENDED flag */
496cdf0e10cSrcweir 		pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
497cdf0e10cSrcweir 		pthread_cond_signal (&(pImpl->m_Cond));
498*18a2cb5fSmseidel 	}
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)
525*18a2cb5fSmseidel 	{
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);
530*18a2cb5fSmseidel 	}
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
560*18a2cb5fSmseidel 	it blocks (sleep, blocking I/O) OR calls sched_yield().
561cdf0e10cSrcweir */
562cdf0e10cSrcweir /*****************************************************************************/
osl_yieldThread()563cdf0e10cSrcweir void SAL_CALL osl_yieldThread()
564cdf0e10cSrcweir {
565*18a2cb5fSmseidel 	sched_yield();
566cdf0e10cSrcweir }
567cdf0e10cSrcweir 
osl_setThreadName(char const * name)568cdf0e10cSrcweir void SAL_CALL osl_setThreadName(char const * name) {
569cdf0e10cSrcweir #if defined LINUX
570*18a2cb5fSmseidel 	if (prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0) != 0) {
571*18a2cb5fSmseidel 		OSL_TRACE(
572*18a2cb5fSmseidel 			"%s prctl(PR_SET_NAME) failed with errno %d", OSL_LOG_PREFIX,
573*18a2cb5fSmseidel 			errno);
574*18a2cb5fSmseidel 	}
575cdf0e10cSrcweir #else
576*18a2cb5fSmseidel 	(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 
647*18a2cb5fSmseidel 		if ( LastIdent == 0 )
648*18a2cb5fSmseidel 			LastIdent = 1;
649cdf0e10cSrcweir 
650*18a2cb5fSmseidel 		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 /*****************************************************************************
714*18a2cb5fSmseidel 	@@@ 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).
721*18a2cb5fSmseidel 	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
728*18a2cb5fSmseidel 	struct sched_param param;
729*18a2cb5fSmseidel 	int policy=0;
730*18a2cb5fSmseidel 	int nRet=0;
731cdf0e10cSrcweir 
732cdf0e10cSrcweir /* @@@ see TODO: calling thread may not be main thread @@@ */
733cdf0e10cSrcweir 
734*18a2cb5fSmseidel 	if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
735*18a2cb5fSmseidel 	{
736*18a2cb5fSmseidel 		OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet));
737*18a2cb5fSmseidel 		return;
738*18a2cb5fSmseidel 	}
739cdf0e10cSrcweir 
740cdf0e10cSrcweir #if defined (SOLARIS)
741*18a2cb5fSmseidel 	if ( policy >= _SCHED_NEXT)
742*18a2cb5fSmseidel 	{
743*18a2cb5fSmseidel 		/* mfe: pthread_getschedparam on Solaris has a possible Bug */
744*18a2cb5fSmseidel 		/*      one gets 959917873 as the policy                    */
745*18a2cb5fSmseidel 		/*      so set the policy to a default one                  */
746*18a2cb5fSmseidel 		policy=SCHED_OTHER;
747*18a2cb5fSmseidel 	}
748cdf0e10cSrcweir #endif /* SOLARIS */
749cdf0e10cSrcweir 
750*18a2cb5fSmseidel 	if ((nRet = sched_get_priority_min(policy) ) != -1)
751*18a2cb5fSmseidel 	{
752*18a2cb5fSmseidel 		OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet);
753*18a2cb5fSmseidel 		g_thread.m_priority.m_Lowest=nRet;
754*18a2cb5fSmseidel 	}
755cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
756*18a2cb5fSmseidel 	else
757*18a2cb5fSmseidel 	{
758*18a2cb5fSmseidel 		fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
759*18a2cb5fSmseidel 	}
760cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
761cdf0e10cSrcweir 
762*18a2cb5fSmseidel 	if ((nRet = sched_get_priority_max(policy) ) != -1)
763*18a2cb5fSmseidel 	{
764*18a2cb5fSmseidel 		OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet);
765*18a2cb5fSmseidel 		g_thread.m_priority.m_Highest=nRet;
766*18a2cb5fSmseidel 	}
767cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
768*18a2cb5fSmseidel 	else
769*18a2cb5fSmseidel 	{
770*18a2cb5fSmseidel 		fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
771*18a2cb5fSmseidel 	}
772cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
773cdf0e10cSrcweir 
774*18a2cb5fSmseidel 	g_thread.m_priority.m_Normal =
775cdf0e10cSrcweir 		(g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2;
776*18a2cb5fSmseidel 	g_thread.m_priority.m_Below_Normal =
777*18a2cb5fSmseidel 		(g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2;
778*18a2cb5fSmseidel 	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 
783*18a2cb5fSmseidel 	param.sched_priority= g_thread.m_priority.m_Normal;
784cdf0e10cSrcweir 
785*18a2cb5fSmseidel 	if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
786*18a2cb5fSmseidel 	{
787*18a2cb5fSmseidel 		OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet));
788*18a2cb5fSmseidel 		OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority);
789*18a2cb5fSmseidel 	}
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;
810*18a2cb5fSmseidel 	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
821*18a2cb5fSmseidel 	(void) Priority; /* unused */
822cdf0e10cSrcweir #else /* NO_PTHREAD_PRIORITY */
823cdf0e10cSrcweir 
824*18a2cb5fSmseidel 	if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
825cdf0e10cSrcweir 		return; /* ESRCH */
826cdf0e10cSrcweir 
827cdf0e10cSrcweir #if defined (SOLARIS)
828*18a2cb5fSmseidel 	if ( policy >= _SCHED_NEXT)
829*18a2cb5fSmseidel 	{
830*18a2cb5fSmseidel 		/* mfe: pthread_getschedparam on Solaris has a possible Bug */
831*18a2cb5fSmseidel 		/*      one gets 959917873 as the policy                   */
832*18a2cb5fSmseidel 		/*      so set the policy to a default one                 */
833*18a2cb5fSmseidel 		policy=SCHED_OTHER;
834*18a2cb5fSmseidel 	}
835cdf0e10cSrcweir #endif /* SOLARIS */
836cdf0e10cSrcweir 
837cdf0e10cSrcweir 	pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
838cdf0e10cSrcweir 
839*18a2cb5fSmseidel 	switch(Priority)
840*18a2cb5fSmseidel 	{
841*18a2cb5fSmseidel 		case osl_Thread_PriorityHighest:
842*18a2cb5fSmseidel 			Param.sched_priority= g_thread.m_priority.m_Highest;
843*18a2cb5fSmseidel 			break;
844cdf0e10cSrcweir 
845*18a2cb5fSmseidel 		case osl_Thread_PriorityAboveNormal:
846*18a2cb5fSmseidel 			Param.sched_priority= g_thread.m_priority.m_Above_Normal;
847*18a2cb5fSmseidel 			break;
848cdf0e10cSrcweir 
849*18a2cb5fSmseidel 		case osl_Thread_PriorityNormal:
850*18a2cb5fSmseidel 			Param.sched_priority= g_thread.m_priority.m_Normal;
851*18a2cb5fSmseidel 			break;
852cdf0e10cSrcweir 
853*18a2cb5fSmseidel 		case osl_Thread_PriorityBelowNormal:
854*18a2cb5fSmseidel 			Param.sched_priority= g_thread.m_priority.m_Below_Normal;
855*18a2cb5fSmseidel 			break;
856cdf0e10cSrcweir 
857*18a2cb5fSmseidel 		case osl_Thread_PriorityLowest:
858*18a2cb5fSmseidel 			Param.sched_priority= g_thread.m_priority.m_Lowest;
859*18a2cb5fSmseidel 			break;
860cdf0e10cSrcweir 
861*18a2cb5fSmseidel 		case osl_Thread_PriorityUnknown:
862*18a2cb5fSmseidel 			OSL_ASSERT(sal_False);		/* only fools try this...*/
863cdf0e10cSrcweir 
864*18a2cb5fSmseidel 			/* let release-version behave friendly */
865*18a2cb5fSmseidel 			return;
866cdf0e10cSrcweir 
867*18a2cb5fSmseidel 		default:
868*18a2cb5fSmseidel 			/* enum expanded, but forgotten here...*/
869*18a2cb5fSmseidel 			OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
870cdf0e10cSrcweir 
871*18a2cb5fSmseidel 			/* let release-version behave friendly */
872*18a2cb5fSmseidel 			return;
873*18a2cb5fSmseidel 	}
874cdf0e10cSrcweir 
875*18a2cb5fSmseidel 	if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
876*18a2cb5fSmseidel 	{
877*18a2cb5fSmseidel 		OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet));
878*18a2cb5fSmseidel 	}
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
1005940681c7SMatthias 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 {
1019*18a2cb5fSmseidel 	rtl_TextEncoding threadEncoding;
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir 	pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
1022cdf0e10cSrcweir 
1023*18a2cb5fSmseidel 	/* check for thread specific encoding, use default if not set */
1024cdf0e10cSrcweir 	threadEncoding = SAL_INT_CAST(
1025*18a2cb5fSmseidel 		rtl_TextEncoding,
1026*18a2cb5fSmseidel 		(sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key));
1027cdf0e10cSrcweir 	if (0 == threadEncoding)
1028cdf0e10cSrcweir 		threadEncoding = g_thread.m_textencoding.m_default;
1029cdf0e10cSrcweir 
1030*18a2cb5fSmseidel 	return threadEncoding;
1031cdf0e10cSrcweir }
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir /*****************************************************************************/
1034cdf0e10cSrcweir /* osl_setThreadTextEncoding */
1035cdf0e10cSrcweir /*****************************************************************************/
osl_setThreadTextEncoding(rtl_TextEncoding Encoding)1036cdf0e10cSrcweir rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
1037cdf0e10cSrcweir {
1038*18a2cb5fSmseidel 	rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
1039cdf0e10cSrcweir 
1040*18a2cb5fSmseidel 	/* save encoding in thread local storage */
1041*18a2cb5fSmseidel 	pthread_setspecific (
1042*18a2cb5fSmseidel 		g_thread.m_textencoding.m_key,
1043*18a2cb5fSmseidel 		(void*) SAL_INT_CAST(sal_uIntPtr, Encoding));
1044cdf0e10cSrcweir 
1045*18a2cb5fSmseidel 	return oldThreadEncoding;
1046cdf0e10cSrcweir }
1047