LCOV - code coverage report
Current view: top level - sal/osl/unx - thread.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 223 269 82.9 %
Date: 2012-08-25 Functions: 27 32 84.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 68 105 64.8 %

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

Generated by: LCOV version 1.10