1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
28 #include "unixerrnostring.hxx"
29 #include <thread_internal.hxx>
36 #if __FreeBSD_version <= 1201517
37 #include <pthread_np.h>
38 #define pthread_setname_np pthread_set_name_np
41 #include <config_options.h>
42 #include <o3tl/safeint.hxx>
43 #include <osl/thread.h>
44 #include <osl/nlsupport.h>
45 #include <rtl/textenc.h>
46 #include <sal/log.hxx>
47 #include <sal/macros.h>
50 #include <android/log.h>
51 #include <osl/detail/android-bootstrap.h>
54 #if defined LINUX && ! defined __FreeBSD_kernel__
55 #include <sys/syscall.h>
58 /****************************************************************************
61 * (1) 'osl_thread_priority_init_Impl()'
62 * - insane assumption that initializing caller is main thread
63 * - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?)
64 * - POSIX doesn't require defined prio's for SCHED_OTHER (!)
65 * - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?)
66 * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()'
67 * - cannot reliably be applied to 'alien' threads;
68 * - memory leak for 'alien' thread 'HashEntry's;
69 * - use 'reinterpret_cast<unsigned long>(pthread_t)' as identifier
71 * - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar
72 * (3) 'oslSigAlarmHandler()' (#71232#)
73 * - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates
74 * the process. So we initialize our signal handling module and do
75 * register a SIGALRM Handler which catches and ignores it]
76 * - should this still happen, 'signal.c' needs to be fixed instead.
78 ****************************************************************************/
80 #define THREADIMPL_FLAGS_TERMINATE 0x00001
81 #define THREADIMPL_FLAGS_STARTUP 0x00002
82 #define THREADIMPL_FLAGS_SUSPENDED 0x00004
83 #define THREADIMPL_FLAGS_ACTIVE 0x00008
84 #define THREADIMPL_FLAGS_ATTACHED 0x00010
85 #define THREADIMPL_FLAGS_DESTROYED 0x00020
89 typedef struct osl_thread_impl_st
92 oslThreadIdentifier m_Ident
; /* @@@ see TODO @@@ */
94 oslWorkerFunction m_WorkerFunction
;
96 pthread_mutex_t m_Lock
;
97 pthread_cond_t m_Cond
;
100 #if !defined NO_PTHREAD_PRIORITY
101 struct osl_thread_priority_st
109 #define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
114 #if !defined NO_PTHREAD_PRIORITY
118 struct osl_thread_global_st
120 pthread_once_t m_once
;
121 struct osl_thread_priority_st m_priority
;
126 static struct osl_thread_global_st g_thread
=
129 OSL_THREAD_PRIORITY_INITIALIZER
132 #endif // !defined NO_PTHREAD_PRIORITY
134 static Thread_Impl
* osl_thread_construct_Impl();
135 static void osl_thread_destruct_Impl (Thread_Impl
** ppImpl
);
137 static void* osl_thread_start_Impl (void * pData
);
138 static void osl_thread_cleanup_Impl (Thread_Impl
* pImpl
);
140 static oslThread
osl_thread_create_Impl (
141 oslWorkerFunction pWorker
, void * pThreadData
, short nFlags
);
143 /* @@@ see TODO @@@ */
144 static oslThreadIdentifier
insertThreadId (pthread_t hThread
);
145 static oslThreadIdentifier
lookupThreadId (pthread_t hThread
);
146 static void removeThreadId (pthread_t hThread
);
148 Thread_Impl
* osl_thread_construct_Impl()
150 Thread_Impl
* pImpl
= new Thread_Impl
;
151 memset (pImpl
, 0, sizeof(Thread_Impl
));
153 pthread_mutex_init (&(pImpl
->m_Lock
), PTHREAD_MUTEXATTR_DEFAULT
);
154 pthread_cond_init (&(pImpl
->m_Cond
), PTHREAD_CONDATTR_DEFAULT
);
158 static void osl_thread_destruct_Impl (Thread_Impl
** ppImpl
)
163 pthread_cond_destroy (&((*ppImpl
)->m_Cond
));
164 pthread_mutex_destroy (&((*ppImpl
)->m_Lock
));
171 static void osl_thread_cleanup_Impl (Thread_Impl
* pImpl
)
177 pthread_mutex_lock (&(pImpl
->m_Lock
));
179 thread
= pImpl
->m_hThread
;
180 attached
= (pImpl
->m_Flags
& THREADIMPL_FLAGS_ATTACHED
) != 0;
181 destroyed
= (pImpl
->m_Flags
& THREADIMPL_FLAGS_DESTROYED
) != 0;
182 pImpl
->m_Flags
&= ~(THREADIMPL_FLAGS_ACTIVE
| THREADIMPL_FLAGS_ATTACHED
);
184 pthread_mutex_unlock (&(pImpl
->m_Lock
));
186 /* release oslThreadIdentifier @@@ see TODO @@@ */
187 removeThreadId (thread
);
191 pthread_detach (thread
);
196 osl_thread_destruct_Impl (&pImpl
);
200 static void* osl_thread_start_Impl (void* pData
)
203 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(pData
);
207 pthread_mutex_lock (&(pImpl
->m_Lock
));
209 /* request oslThreadIdentifier @@@ see TODO @@@ */
210 pImpl
->m_Ident
= insertThreadId (pImpl
->m_hThread
);
212 /* signal change from STARTUP to ACTIVE state */
213 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_STARTUP
;
214 pImpl
->m_Flags
|= THREADIMPL_FLAGS_ACTIVE
;
215 pthread_cond_signal (&(pImpl
->m_Cond
));
217 /* Check if thread is started in SUSPENDED state */
218 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
220 /* wait until SUSPENDED flag is cleared */
221 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
224 /* check for SUSPENDED to TERMINATE state change */
225 terminate
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_TERMINATE
) > 0);
227 pthread_mutex_unlock (&(pImpl
->m_Lock
));
233 int res
= (*lo_get_javavm()).AttachCurrentThread(&env
, NULL
);
234 __android_log_print(ANDROID_LOG_INFO
, "LibreOffice", "New sal thread started and attached res=%d", res
);
236 /* call worker function */
237 pImpl
->m_WorkerFunction(pImpl
->m_pData
);
240 res
= (*lo_get_javavm()).DetachCurrentThread();
241 __android_log_print(ANDROID_LOG_INFO
, "LibreOffice", "Detached finished sal thread res=%d", res
);
245 osl_thread_cleanup_Impl (pImpl
);
249 static oslThread
osl_thread_create_Impl (
250 oslWorkerFunction pWorker
,
255 #if defined OPENBSD || defined MACOSX || (defined LINUX && !ENABLE_RUNTIME_OPTIMIZATIONS)
261 pImpl
= osl_thread_construct_Impl();
263 return nullptr; /* ENOMEM */
265 pImpl
->m_WorkerFunction
= pWorker
;
266 pImpl
->m_pData
= pThreadData
;
267 pImpl
->m_Flags
= nFlags
| THREADIMPL_FLAGS_STARTUP
;
269 pthread_mutex_lock (&(pImpl
->m_Lock
));
271 #if defined OPENBSD || defined MACOSX || (defined LINUX && !ENABLE_RUNTIME_OPTIMIZATIONS)
272 if (pthread_attr_init(&attr
) != 0)
277 #elif !ENABLE_RUNTIME_OPTIMIZATIONS
278 stacksize
= 12 * 1024 * 1024; // 8MB is not enough for ASAN on x86-64
280 stacksize
= 1 * 1024 * 1024; // macOS default for non-main threads (512kB) is not enough...
282 if (pthread_attr_setstacksize(&attr
, stacksize
) != 0) {
283 pthread_attr_destroy(&attr
);
288 if ((nRet
= pthread_create (
290 #if defined OPENBSD || defined MACOSX || (defined LINUX && !ENABLE_RUNTIME_OPTIMIZATIONS)
293 PTHREAD_ATTR_DEFAULT
,
295 osl_thread_start_Impl
,
296 static_cast<void*>(pImpl
))) != 0)
300 "pthread_create failed: " << UnixErrnoString(nRet
));
302 pthread_mutex_unlock (&(pImpl
->m_Lock
));
303 osl_thread_destruct_Impl (&pImpl
);
308 #if defined OPENBSD || defined MACOSX || (defined LINUX && !ENABLE_RUNTIME_OPTIMIZATIONS)
309 pthread_attr_destroy(&attr
);
312 /* wait for change from STARTUP to ACTIVE state */
313 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_STARTUP
)
315 /* wait until STARTUP flag is cleared */
316 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
319 pthread_mutex_unlock (&(pImpl
->m_Lock
));
321 return static_cast<oslThread
>(pImpl
);
324 oslThread
osl_createThread (
325 oslWorkerFunction pWorker
,
328 return osl_thread_create_Impl (
331 THREADIMPL_FLAGS_ATTACHED
);
334 oslThread
osl_createSuspendedThread (
335 oslWorkerFunction pWorker
,
338 return osl_thread_create_Impl (
341 THREADIMPL_FLAGS_ATTACHED
|
342 THREADIMPL_FLAGS_SUSPENDED
);
345 void SAL_CALL
osl_destroyThread(oslThread Thread
)
347 if (Thread
!= nullptr) {
348 Thread_Impl
* impl
= static_cast<Thread_Impl
*>(Thread
);
350 pthread_mutex_lock(&impl
->m_Lock
);
351 active
= (impl
->m_Flags
& THREADIMPL_FLAGS_ACTIVE
) != 0;
352 impl
->m_Flags
|= THREADIMPL_FLAGS_DESTROYED
;
353 pthread_mutex_unlock(&impl
->m_Lock
);
355 osl_thread_destruct_Impl(&impl
);
360 void SAL_CALL
osl_resumeThread(oslThread Thread
)
362 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
366 SAL_WARN("sal.osl", "invalid osl_resumeThread(nullptr) call");
370 pthread_mutex_lock (&(pImpl
->m_Lock
));
372 if (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
374 /* clear SUSPENDED flag */
375 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_SUSPENDED
;
376 pthread_cond_signal (&(pImpl
->m_Cond
));
379 pthread_mutex_unlock (&(pImpl
->m_Lock
));
382 void SAL_CALL
osl_suspendThread(oslThread Thread
)
384 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
388 SAL_WARN("sal.osl", "invalid osl_suspendThread(nullptr) call");
392 pthread_mutex_lock (&(pImpl
->m_Lock
));
394 pImpl
->m_Flags
|= THREADIMPL_FLAGS_SUSPENDED
;
396 if (pthread_equal (pthread_self(), pImpl
->m_hThread
))
399 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
401 /* wait until SUSPENDED flag is cleared */
402 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
406 pthread_mutex_unlock (&(pImpl
->m_Lock
));
409 sal_Bool SAL_CALL
osl_isThreadRunning(const oslThread Thread
)
412 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
417 pthread_mutex_lock (&(pImpl
->m_Lock
));
418 active
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_ACTIVE
) > 0);
419 pthread_mutex_unlock (&(pImpl
->m_Lock
));
424 void SAL_CALL
osl_joinWithThread(oslThread Thread
)
426 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
431 pthread_mutex_lock (&(pImpl
->m_Lock
));
433 pthread_t
const thread
= pImpl
->m_hThread
;
434 bool const attached
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_ATTACHED
) > 0);
436 /* check this only if *this* thread is still attached - if it's not,
437 then it could have terminated and another newly created thread could
438 have recycled the same id as m_hThread! */
439 if (attached
&& pthread_equal(pthread_self(), pImpl
->m_hThread
))
441 assert(false); /* Win32 implementation would deadlock here! */
443 pthread_mutex_unlock (&(pImpl
->m_Lock
));
444 return; /* EDEADLK */
447 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_ATTACHED
;
449 pthread_mutex_unlock (&(pImpl
->m_Lock
));
453 pthread_join (thread
, nullptr);
457 void SAL_CALL
osl_terminateThread(oslThread Thread
)
459 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
463 SAL_WARN("sal.osl", "invalid osl_terminateThread(nullptr) call");
467 pthread_mutex_lock (&(pImpl
->m_Lock
));
469 if (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
471 /* clear SUSPENDED flag */
472 pImpl
->m_Flags
&= ~THREADIMPL_FLAGS_SUSPENDED
;
473 pthread_cond_signal (&(pImpl
->m_Cond
));
476 pImpl
->m_Flags
|= THREADIMPL_FLAGS_TERMINATE
;
478 pthread_mutex_unlock (&(pImpl
->m_Lock
));
481 sal_Bool SAL_CALL
osl_scheduleThread(oslThread Thread
)
484 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
488 SAL_WARN("sal.osl", "invalid osl_scheduleThread(nullptr) call");
489 return false; /* EINVAL */
492 if (!(pthread_equal (pthread_self(), pImpl
->m_hThread
)))
494 SAL_WARN("sal.osl", "invalid osl_scheduleThread(non-self) call");
495 return false; /* EINVAL */
498 pthread_mutex_lock (&(pImpl
->m_Lock
));
500 while (pImpl
->m_Flags
& THREADIMPL_FLAGS_SUSPENDED
)
502 /* wait until SUSPENDED flag is cleared */
503 pthread_cond_wait (&(pImpl
->m_Cond
), &(pImpl
->m_Lock
));
506 terminate
= ((pImpl
->m_Flags
& THREADIMPL_FLAGS_TERMINATE
) > 0);
508 pthread_mutex_unlock(&(pImpl
->m_Lock
));
513 void SAL_CALL
osl_waitThread(const TimeValue
* pDelay
)
517 struct timespec delay
;
519 SET_TIMESPEC(delay
, pDelay
->Seconds
, pDelay
->Nanosec
);
521 SLEEP_TIMESPEC(delay
);
527 @attention Note that POSIX scheduling @em really requires threads to call this
528 function, since a thread only reschedules to other thread, when
529 it blocks (sleep, blocking I/O) OR calls sched_yield().
531 void SAL_CALL
osl_yieldThread()
536 void SAL_CALL
osl_setThreadName(char const * name
)
539 #if defined LINUX && ! defined __FreeBSD_kernel__
540 const int LINUX_THREAD_NAME_MAXLEN
= 15;
541 if ( strlen( name
) > LINUX_THREAD_NAME_MAXLEN
)
542 SAL_INFO( "sal.osl", "osl_setThreadName truncated thread name to "
543 << LINUX_THREAD_NAME_MAXLEN
<< " chars from name '"
545 char shortname
[ LINUX_THREAD_NAME_MAXLEN
+ 1 ];
546 shortname
[ LINUX_THREAD_NAME_MAXLEN
] = '\0';
547 strncpy( shortname
, name
, LINUX_THREAD_NAME_MAXLEN
);
548 int err
= pthread_setname_np( pthread_self(), shortname
);
550 SAL_WARN("sal.osl", "pthread_setname_np failed with errno " << err
);
551 #elif defined __FreeBSD__
552 pthread_setname_np( pthread_self(), name
);
553 #elif defined MACOSX || defined IOS
554 pthread_setname_np( name
);
560 /* osl_getThreadIdentifier @@@ see TODO @@@ */
567 oslThreadIdentifier Ident
;
573 static HashEntry
* HashTable
[31];
574 const int HashSize
= SAL_N_ELEMENTS(HashTable
);
576 static std::mutex HashLock
;
578 #if ! ((defined LINUX && !defined __FreeBSD_kernel__) || defined MACOSX || defined IOS)
579 static oslThreadIdentifier LastIdent
= 0;
584 std::size_t HASHID(pthread_t x
)
585 { return std::hash
<pthread_t
>()(x
) % HashSize
; }
589 static oslThreadIdentifier
lookupThreadId (pthread_t hThread
)
593 std::unique_lock
aGuard(HashLock
);
595 pEntry
= HashTable
[HASHID(hThread
)];
596 while (pEntry
!= nullptr)
598 if (pthread_equal(pEntry
->Handle
, hThread
))
600 return pEntry
->Ident
;
602 pEntry
= pEntry
->Next
;
608 static oslThreadIdentifier
insertThreadId (pthread_t hThread
)
610 HashEntry
*pEntry
, *pInsert
= nullptr;
612 std::unique_lock
aGuard(HashLock
);
614 pEntry
= HashTable
[HASHID(hThread
)];
616 while (pEntry
!= nullptr)
618 if (pthread_equal(pEntry
->Handle
, hThread
))
622 pEntry
= pEntry
->Next
;
625 if (pEntry
== nullptr)
627 pEntry
= static_cast<HashEntry
*>(calloc(1, sizeof(HashEntry
)));
629 pEntry
->Handle
= hThread
;
631 #if defined LINUX && ! defined __FreeBSD_kernel__
632 #if defined __GLIBC__ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 30))
633 // gettid returns a pid_t, which POSIX defines to be a signed integer type; assume that all
634 // valid pid_t values on Linux are positive (zero is filtered out in the generic code
636 pid_t
const tid
= gettid();
639 long const tid
= syscall(SYS_gettid
);
640 if (tid
< 0 || o3tl::make_unsigned(tid
) > std::numeric_limits
<sal_uInt32
>::max()) {
645 #elif defined MACOSX || defined IOS
646 // currently the value of pthread_threadid_np is the same then
647 // syscall(SYS_thread_selfid), which returns an int as the TID.
648 // may change, as the syscall interface was deprecated.
650 pthread_threadid_np(nullptr, &mac_tid
);
651 if (mac_tid
> SAL_MAX_UINT32
)
653 pEntry
->Ident
= mac_tid
;
658 pEntry
->Ident
= LastIdent
;
660 if (0 == pEntry
->Ident
)
664 pInsert
->Next
= pEntry
;
666 HashTable
[HASHID(hThread
)] = pEntry
;
669 return pEntry
->Ident
;
672 static void removeThreadId (pthread_t hThread
)
674 HashEntry
*pEntry
, *pRemove
= nullptr;
676 std::unique_lock
aGuard(HashLock
);
678 pEntry
= HashTable
[HASHID(hThread
)];
679 while (pEntry
!= nullptr)
681 if (pthread_equal(pEntry
->Handle
, hThread
))
685 pEntry
= pEntry
->Next
;
688 if (pEntry
!= nullptr)
691 pRemove
->Next
= pEntry
->Next
;
693 HashTable
[HASHID(hThread
)] = pEntry
->Next
;
699 oslThreadIdentifier SAL_CALL
osl_getThreadIdentifier(oslThread Thread
)
701 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
702 oslThreadIdentifier Ident
;
705 Ident
= pImpl
->m_Ident
;
709 pthread_t current
= pthread_self();
711 Ident
= lookupThreadId (current
);
713 /* @@@ see TODO: alien pthread_self() @@@ */
714 Ident
= insertThreadId (current
);
720 #ifndef NO_PTHREAD_PRIORITY
721 /*****************************************************************************
723 osl_thread_priority_init_Impl
725 set the base-priority of the main-thread to
726 oslThreadPriorityNormal (64) since 0 (lowest) is
727 the system default. This behaviour collides with
728 our enum-priority definition (highest..normal..lowest).
729 A normaluser will expect the main-thread of an app.
730 to have the "normal" priority.
732 *****************************************************************************/
733 static void osl_thread_priority_init_Impl()
735 struct sched_param param
;
739 /* @@@ see TODO: calling thread may not be main thread @@@ */
741 if ((nRet
= pthread_getschedparam(pthread_self(), &policy
, ¶m
)) != 0)
745 "pthread_getschedparam failed: " << UnixErrnoString(nRet
));
750 if ( policy
>= _SCHED_NEXT
)
752 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
753 /* one gets 959917873 as the policy */
754 /* so set the policy to a default one */
759 if ((nRet
= sched_get_priority_min(policy
) ) != -1)
762 "sal.osl", "Min Prioriy for policy " << policy
<< " == " << nRet
);
763 g_thread
.m_priority
.m_Lowest
=nRet
;
770 "sched_get_priority_min failed: " << UnixErrnoString(e
));
773 if ((nRet
= sched_get_priority_max(policy
) ) != -1)
776 "sal.osl", "Max Prioriy for policy " << policy
<< " == " << nRet
);
777 g_thread
.m_priority
.m_Highest
=nRet
;
784 "sched_get_priority_max failed: " << UnixErrnoString(e
));
787 g_thread
.m_priority
.m_Normal
=
788 (g_thread
.m_priority
.m_Lowest
+ g_thread
.m_priority
.m_Highest
) / 2;
789 g_thread
.m_priority
.m_Below_Normal
=
790 (g_thread
.m_priority
.m_Lowest
+ g_thread
.m_priority
.m_Normal
) / 2;
791 g_thread
.m_priority
.m_Above_Normal
=
792 (g_thread
.m_priority
.m_Normal
+ g_thread
.m_priority
.m_Highest
) / 2;
794 /* @@@ set prio of calling (not main) thread (?) @@@ */
796 param
.sched_priority
= g_thread
.m_priority
.m_Normal
;
798 if ((nRet
= pthread_setschedparam(pthread_self(), policy
, ¶m
)) != 0)
802 "pthread_setschedparam failed: " << UnixErrnoString(nRet
));
805 "Thread ID " << pthread_self() << ", Policy " << policy
806 << ", Priority " << param
.sched_priority
);
810 #endif /* NO_PTHREAD_PRIORITY */
813 Impl-Notes: contrary to solaris-docu, which claims
814 valid priority-levels from 0 .. INT_MAX, only the
815 range 0..127 is accepted. (0 lowest, 127 highest)
817 void SAL_CALL
osl_setThreadPriority (
819 oslThreadPriority Priority
)
821 #ifndef NO_PTHREAD_PRIORITY
823 struct sched_param Param
;
827 #endif /* NO_PTHREAD_PRIORITY */
829 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
833 SAL_WARN("sal.osl", "invalid osl_setThreadPriority(nullptr, ...) call");
837 #ifdef NO_PTHREAD_PRIORITY
838 (void) Priority
; /* unused */
839 #else /* NO_PTHREAD_PRIORITY */
841 if (pthread_getschedparam(pImpl
->m_hThread
, &policy
, &Param
) != 0)
845 if ( policy
>= _SCHED_NEXT
)
847 /* mfe: pthread_getschedparam on Solaris has a possible Bug */
848 /* one gets 959917873 as the policy */
849 /* so set the policy to a default one */
854 pthread_once (&(g_thread
.m_once
), osl_thread_priority_init_Impl
);
858 case osl_Thread_PriorityHighest
:
859 Param
.sched_priority
= g_thread
.m_priority
.m_Highest
;
862 case osl_Thread_PriorityAboveNormal
:
863 Param
.sched_priority
= g_thread
.m_priority
.m_Above_Normal
;
866 case osl_Thread_PriorityNormal
:
867 Param
.sched_priority
= g_thread
.m_priority
.m_Normal
;
870 case osl_Thread_PriorityBelowNormal
:
871 Param
.sched_priority
= g_thread
.m_priority
.m_Below_Normal
;
874 case osl_Thread_PriorityLowest
:
875 Param
.sched_priority
= g_thread
.m_priority
.m_Lowest
;
878 case osl_Thread_PriorityUnknown
:
881 "invalid osl_setThreadPriority(..., osl_Thread_PriorityUnknown)"
888 "invalid osl_setThreadPriority(..., " << Priority
<< ") call");
892 if ((nRet
= pthread_setschedparam(pImpl
->m_hThread
, policy
, &Param
)) != 0)
896 "pthread_setschedparam failed: " << UnixErrnoString(nRet
));
899 #endif /* NO_PTHREAD_PRIORITY */
902 oslThreadPriority SAL_CALL
osl_getThreadPriority(const oslThread Thread
)
904 #ifndef NO_PTHREAD_PRIORITY
906 struct sched_param Param
;
909 #endif /* NO_PTHREAD_PRIORITY */
911 oslThreadPriority Priority
= osl_Thread_PriorityNormal
;
912 Thread_Impl
* pImpl
= static_cast<Thread_Impl
*>(Thread
);
916 SAL_WARN("sal.osl", "invalid osl_getThreadPriority(nullptr) call");
917 return osl_Thread_PriorityUnknown
; /* EINVAL */
920 #ifndef NO_PTHREAD_PRIORITY
922 if (pthread_getschedparam(pImpl
->m_hThread
, &Policy
, &Param
) != 0)
923 return osl_Thread_PriorityUnknown
; /* ESRCH */
925 pthread_once (&(g_thread
.m_once
), osl_thread_priority_init_Impl
);
927 /* map pthread priority to enum */
928 if (Param
.sched_priority
==g_thread
.m_priority
.m_Highest
)
931 Priority
= osl_Thread_PriorityHighest
;
933 else if (Param
.sched_priority
> g_thread
.m_priority
.m_Normal
)
935 /* 65..126 - above normal */
936 Priority
= osl_Thread_PriorityAboveNormal
;
938 else if (Param
.sched_priority
== g_thread
.m_priority
.m_Normal
)
941 Priority
= osl_Thread_PriorityNormal
;
943 else if (Param
.sched_priority
> g_thread
.m_priority
.m_Lowest
)
945 /* 63..1 -below normal */
946 Priority
= osl_Thread_PriorityBelowNormal
;
948 else if (Param
.sched_priority
== g_thread
.m_priority
.m_Lowest
)
951 Priority
= osl_Thread_PriorityLowest
;
956 Priority
= osl_Thread_PriorityUnknown
;
959 #endif /* NO_PTHREAD_PRIORITY */
966 struct wrapper_pthread_key
969 oslThreadKeyCallbackFunction pfnCallback
;
974 oslThreadKey SAL_CALL
osl_createThreadKey( oslThreadKeyCallbackFunction pCallback
)
976 wrapper_pthread_key
*pKey
= static_cast<wrapper_pthread_key
*>(malloc(sizeof(wrapper_pthread_key
)));
980 pKey
->pfnCallback
= pCallback
;
982 if (pthread_key_create(&(pKey
->m_key
), pKey
->pfnCallback
) != 0)
989 return static_cast<oslThreadKey
>(pKey
);
992 void SAL_CALL
osl_destroyThreadKey(oslThreadKey Key
)
994 wrapper_pthread_key
*pKey
= static_cast<wrapper_pthread_key
*>(Key
);
997 pthread_key_delete(pKey
->m_key
);
1002 void* SAL_CALL
osl_getThreadKeyData(oslThreadKey Key
)
1004 wrapper_pthread_key
*pKey
= static_cast<wrapper_pthread_key
*>(Key
);
1005 return pKey
? pthread_getspecific(pKey
->m_key
) : nullptr;
1008 sal_Bool SAL_CALL
osl_setThreadKeyData(oslThreadKey Key
, void *pData
)
1011 void *pOldData
= nullptr;
1012 wrapper_pthread_key
*pKey
= static_cast<wrapper_pthread_key
*>(Key
);
1016 if (pKey
->pfnCallback
)
1017 pOldData
= pthread_getspecific(pKey
->m_key
);
1019 bRet
= (pthread_setspecific(pKey
->m_key
, pData
) == 0);
1021 if (bRet
&& pKey
->pfnCallback
&& pOldData
)
1022 pKey
->pfnCallback(pOldData
);
1027 rtl_TextEncoding
getThreadTextEncodingForInitialization()
1029 /* determine default text encoding */
1030 rtl_TextEncoding defaultEncoding
= osl_getTextEncodingFromLocale(nullptr);
1031 // Tools string functions call abort() on an unknown encoding so ASCII is a
1032 // meaningful fallback:
1033 if ( RTL_TEXTENCODING_DONTKNOW
== defaultEncoding
)
1035 SAL_WARN("sal.osl", "RTL_TEXTENCODING_DONTKNOW -> _ASCII_US");
1036 defaultEncoding
= RTL_TEXTENCODING_ASCII_US
;
1039 return defaultEncoding
;
1042 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */