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