LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sal/osl/unx - thread.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 223 269 82.9 %
Date: 2013-07-09 Functions: 27 32 84.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10