Bug Summary

File:sal/osl/unx/thread.c
Location:line 229, column 5
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

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