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

Generated by: LCOV version 1.10