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