LCOV - code coverage report
Current view: directory - port - cpl_multiproc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 217 167 77.0 %
Date: 2013-03-30 Functions: 35 29 82.9 %

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_multiproc.cpp 25780 2013-03-22 19:36:58Z warmerdam $
       3                 :  *
       4                 :  * Project:  CPL - Common Portability Library
       5                 :  * Purpose:  CPL Multi-Threading, and process handling portability functions.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  **********************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  * 
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  * 
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #ifndef _GNU_SOURCE
      31                 : #define _GNU_SOURCE
      32                 : #endif
      33                 : 
      34                 : #include "cpl_multiproc.h"
      35                 : #include "cpl_conv.h"
      36                 : 
      37                 : #if !defined(WIN32CE)
      38                 : #  include <time.h>
      39                 : #else
      40                 : #  include <wce_time.h>
      41                 : #endif
      42                 : 
      43                 : CPL_CVSID("$Id: cpl_multiproc.cpp 25780 2013-03-22 19:36:58Z warmerdam $");
      44                 : 
      45                 : #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
      46                 : #  define MUTEX_NONE
      47                 : #endif
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                           CPLMutexHolder()                           */
      51                 : /************************************************************************/
      52                 : 
      53        16092990 : CPLMutexHolder::CPLMutexHolder( void **phMutex, double dfWaitInSeconds,
      54                 :                                 const char *pszFileIn, 
      55                 :                                 int nLineIn )
      56                 : 
      57                 : {
      58                 : #ifndef MUTEX_NONE
      59        16092990 :     pszFile = pszFileIn;
      60        16092990 :     nLine = nLineIn;
      61                 : 
      62                 : #ifdef DEBUG_MUTEX
      63                 :     /*
      64                 :      * XXX: There is no way to use CPLDebug() here because it works with
      65                 :      * mutexes itself so we will fall in infinite recursion. Good old
      66                 :      * fprintf() will do the job right.
      67                 :      */
      68                 :     fprintf( stderr,
      69                 :              "CPLMutexHolder: Request %p for pid %ld at %d/%s.\n", 
      70                 :              *phMutex, (long) CPLGetPID(), nLine, pszFile );
      71                 : #endif
      72                 : 
      73        16092990 :     if( !CPLCreateOrAcquireMutex( phMutex, dfWaitInSeconds ) )
      74                 :     {
      75               0 :         fprintf( stderr, "CPLMutexHolder: Failed to acquire mutex!\n" );
      76               0 :         hMutex = NULL;
      77                 :     }
      78                 :     else
      79                 :     {
      80                 : #ifdef DEBUG_MUTEX
      81                 :         fprintf( stderr,
      82                 :                  "CPLMutexHolder: Acquired %p for pid %ld at %d/%s.\n", 
      83                 :                  *phMutex, (long) CPLGetPID(), nLine, pszFile );
      84                 : #endif
      85                 : 
      86        16092990 :         hMutex = *phMutex;
      87                 :     }
      88                 : #endif /* ndef MUTEX_NONE */
      89        16092990 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          ~CPLMutexHolder()                           */
      93                 : /************************************************************************/
      94                 : 
      95        16092990 : CPLMutexHolder::~CPLMutexHolder()
      96                 : 
      97                 : {
      98                 : #ifndef MUTEX_NONE
      99        16092990 :     if( hMutex != NULL )
     100                 :     {
     101                 : #ifdef DEBUG_MUTEX
     102                 :         fprintf( stderr,
     103                 :                  "~CPLMutexHolder: Release %p for pid %ld at %d/%s.\n", 
     104                 :                  hMutex, (long) CPLGetPID(), nLine, pszFile );
     105                 : #endif
     106        16092990 :         CPLReleaseMutex( hMutex );
     107                 :     }
     108                 : #endif /* ndef MUTEX_NONE */
     109        16092990 : }
     110                 : 
     111                 : 
     112                 : /************************************************************************/
     113                 : /*                      CPLCreateOrAcquireMutex()                       */
     114                 : /************************************************************************/
     115                 : 
     116                 : #ifndef CPL_MULTIPROC_PTHREAD
     117                 : 
     118                 : #ifndef MUTEX_NONE
     119                 : static void *hCOAMutex = NULL;
     120                 : #endif
     121                 : 
     122                 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
     123                 : 
     124                 : {
     125                 :     int bSuccess = FALSE;
     126                 : 
     127                 : #ifndef MUTEX_NONE
     128                 : 
     129                 :     /*
     130                 :     ** ironically, creation of this initial mutex is not threadsafe
     131                 :     ** even though we use it to ensure that creation of other mutexes
     132                 :     ** is threadsafe. 
     133                 :     */
     134                 :     if( hCOAMutex == NULL )
     135                 :     {
     136                 :         hCOAMutex = CPLCreateMutex();
     137                 :         if (hCOAMutex == NULL)
     138                 :         {
     139                 :             *phMutex = NULL;
     140                 :             return FALSE;
     141                 :         }
     142                 :     }
     143                 :     else
     144                 :     {
     145                 :         CPLAcquireMutex( hCOAMutex, dfWaitInSeconds );
     146                 :     }
     147                 : 
     148                 :     if( *phMutex == NULL )
     149                 :     {
     150                 :         *phMutex = CPLCreateMutex();
     151                 :         bSuccess = *phMutex != NULL;
     152                 :         CPLReleaseMutex( hCOAMutex );
     153                 :     }
     154                 :     else
     155                 :     {
     156                 :         CPLReleaseMutex( hCOAMutex );
     157                 : 
     158                 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
     159                 :     }
     160                 : #endif /* ndef MUTEX_NONE */
     161                 : 
     162                 :     return bSuccess;
     163                 : }
     164                 : #endif
     165                 : 
     166                 : /************************************************************************/ 
     167                 : /*                      CPLCleanupMasterMutex()                         */ 
     168                 : /************************************************************************/ 
     169                 :  
     170             550 : void CPLCleanupMasterMutex() 
     171                 : { 
     172                 : #ifndef CPL_MULTIPROC_PTHREAD 
     173                 : #ifndef MUTEX_NONE 
     174                 :     if( hCOAMutex != NULL ) 
     175                 :     { 
     176                 :         CPLDestroyMutex( hCOAMutex ); 
     177                 :         hCOAMutex = NULL; 
     178                 :     } 
     179                 : #endif 
     180                 : #endif 
     181             550 : } 
     182                 : 
     183                 : /************************************************************************/
     184                 : /*                        CPLCleanupTLSList()                           */
     185                 : /*                                                                      */
     186                 : /*      Free resources associated with a TLS vector (implementation     */
     187                 : /*      independent).                                                   */
     188                 : /************************************************************************/
     189                 : 
     190            1143 : static void CPLCleanupTLSList( void **papTLSList )
     191                 : 
     192                 : {
     193                 :     int i;
     194                 : 
     195                 : //    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
     196                 :     
     197            1143 :     if( papTLSList == NULL )
     198               0 :         return;
     199                 : 
     200           37719 :     for( i = 0; i < CTLS_MAX; i++ )
     201                 :     {
     202           36576 :         if( papTLSList[i] != NULL && papTLSList[i+CTLS_MAX] != NULL )
     203                 :         {
     204            3128 :             CPLTLSFreeFunc pfnFree = (CPLTLSFreeFunc) papTLSList[i + CTLS_MAX];
     205            3128 :             pfnFree( papTLSList[i] );
     206            3128 :             papTLSList[i] = NULL;
     207                 :         }
     208                 :     }
     209                 : 
     210            1143 :     CPLFree( papTLSList );
     211                 : }
     212                 : 
     213                 : #if defined(CPL_MULTIPROC_STUB)
     214                 : /************************************************************************/
     215                 : /* ==================================================================== */
     216                 : /*                        CPL_MULTIPROC_STUB                            */
     217                 : /*                                                                      */
     218                 : /*      Stub implementation.  Mutexes don't provide exclusion, file     */
     219                 : /*      locking is achieved with extra "lock files", and thread         */
     220                 : /*      creation doesn't work.  The PID is always just one.             */
     221                 : /* ==================================================================== */
     222                 : /************************************************************************/
     223                 : 
     224                 : /************************************************************************/
     225                 : /*                             CPLGetNumCPUs()                          */
     226                 : /************************************************************************/
     227                 : 
     228                 : int CPLGetNumCPUs()
     229                 : {
     230                 :     return 1;
     231                 : }
     232                 : 
     233                 : /************************************************************************/
     234                 : /*                        CPLGetThreadingModel()                        */
     235                 : /************************************************************************/
     236                 : 
     237                 : const char *CPLGetThreadingModel()
     238                 : 
     239                 : {
     240                 :     return "stub";
     241                 : }
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                           CPLCreateMutex()                           */
     245                 : /************************************************************************/
     246                 : 
     247                 : void *CPLCreateMutex()
     248                 : 
     249                 : {
     250                 : #ifndef MUTEX_NONE
     251                 :     unsigned char *pabyMutex = (unsigned char *) malloc( 4 );
     252                 : 
     253                 :     pabyMutex[0] = 1;
     254                 :     pabyMutex[1] = 'r';
     255                 :     pabyMutex[2] = 'e';
     256                 :     pabyMutex[3] = 'd';
     257                 : 
     258                 :     return (void *) pabyMutex;
     259                 : #else
     260                 :     return (void *) 0xdeadbeef;
     261                 : #endif 
     262                 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                          CPLAcquireMutex()                           */
     266                 : /************************************************************************/
     267                 : 
     268                 : int CPLAcquireMutex( void *hMutex, double dfWaitInSeconds )
     269                 : 
     270                 : {
     271                 : #ifndef MUTEX_NONE
     272                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     273                 : 
     274                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     275                 :                && pabyMutex[3] == 'd' );
     276                 : 
     277                 :     pabyMutex[0] += 1;
     278                 : 
     279                 :     return TRUE;
     280                 : #else
     281                 :     return TRUE;
     282                 : #endif
     283                 : }
     284                 : 
     285                 : /************************************************************************/
     286                 : /*                          CPLReleaseMutex()                           */
     287                 : /************************************************************************/
     288                 : 
     289                 : void CPLReleaseMutex( void *hMutex )
     290                 : 
     291                 : {
     292                 : #ifndef MUTEX_NONE
     293                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     294                 : 
     295                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     296                 :                && pabyMutex[3] == 'd' );
     297                 : 
     298                 :     if( pabyMutex[0] < 1 )
     299                 :         CPLDebug( "CPLMultiProc", 
     300                 :                   "CPLReleaseMutex() called on mutex with %d as ref count!",
     301                 :                   pabyMutex[0] );
     302                 : 
     303                 :     pabyMutex[0] -= 1;
     304                 : #endif
     305                 : }
     306                 : 
     307                 : /************************************************************************/
     308                 : /*                          CPLDestroyMutex()                           */
     309                 : /************************************************************************/
     310                 : 
     311                 : void CPLDestroyMutex( void *hMutex )
     312                 : 
     313                 : {
     314                 : #ifndef MUTEX_NONE
     315                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     316                 : 
     317                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     318                 :                && pabyMutex[3] == 'd' );
     319                 : 
     320                 :     free( pabyMutex );
     321                 : #endif
     322                 : }
     323                 : 
     324                 : /************************************************************************/
     325                 : /*                            CPLCreateCond()                           */
     326                 : /************************************************************************/
     327                 : 
     328                 : void  *CPLCreateCond()
     329                 : {
     330                 :     return NULL;
     331                 : }
     332                 : 
     333                 : /************************************************************************/
     334                 : /*                            CPLCondWait()                             */
     335                 : /************************************************************************/
     336                 : 
     337                 : void  CPLCondWait( void *hCond, void* hMutex )
     338                 : {
     339                 : }
     340                 : 
     341                 : /************************************************************************/
     342                 : /*                            CPLCondSignal()                           */
     343                 : /************************************************************************/
     344                 : 
     345                 : void  CPLCondSignal( void *hCond )
     346                 : {
     347                 : }
     348                 : 
     349                 : /************************************************************************/
     350                 : /*                           CPLCondBroadcast()                         */
     351                 : /************************************************************************/
     352                 : 
     353                 : void  CPLCondBroadcast( void *hCond )
     354                 : {
     355                 : }
     356                 : 
     357                 : /************************************************************************/
     358                 : /*                            CPLDestroyCond()                          */
     359                 : /************************************************************************/
     360                 : 
     361                 : void  CPLDestroyCond( void *hCond )
     362                 : {
     363                 : }
     364                 : 
     365                 : /************************************************************************/
     366                 : /*                            CPLLockFile()                             */
     367                 : /*                                                                      */
     368                 : /*      Lock a file.  This implementation has a terrible race           */
     369                 : /*      condition.  If we don't succeed in opening the lock file, we    */
     370                 : /*      assume we can create one and own the target file, but other     */
     371                 : /*      processes might easily try creating the target file at the      */
     372                 : /*      same time, overlapping us.  Death!  Mayhem!  The traditional    */
     373                 : /*      solution is to use open() with _O_CREAT|_O_EXCL but this        */
     374                 : /*      function and these arguments aren't trivially portable.         */
     375                 : /*      Also, this still leaves a race condition on NFS drivers         */
     376                 : /*      (apparently).                                                   */
     377                 : /************************************************************************/
     378                 : 
     379                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     380                 : 
     381                 : {
     382                 :     FILE      *fpLock;
     383                 :     char      *pszLockFilename;
     384                 :     
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      We use a lock file with a name derived from the file we want    */
     387                 : /*      to lock to represent the file being locked.  Note that for      */
     388                 : /*      the stub implementation the target file does not even need      */
     389                 : /*      to exist to be locked.                                          */
     390                 : /* -------------------------------------------------------------------- */
     391                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     392                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     393                 : 
     394                 :     fpLock = fopen( pszLockFilename, "r" );
     395                 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     396                 :     {
     397                 :         fclose( fpLock );
     398                 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
     399                 :         dfWaitInSeconds -= 0.5;
     400                 : 
     401                 :         fpLock = fopen( pszLockFilename, "r" );
     402                 :     }
     403                 :         
     404                 :     if( fpLock != NULL )
     405                 :     {
     406                 :         fclose( fpLock );
     407                 :         CPLFree( pszLockFilename );
     408                 :         return NULL;
     409                 :     }
     410                 : 
     411                 :     fpLock = fopen( pszLockFilename, "w" );
     412                 : 
     413                 :     if( fpLock == NULL )
     414                 :     {
     415                 :         CPLFree( pszLockFilename );
     416                 :         return NULL;
     417                 :     }
     418                 : 
     419                 :     fwrite( "held\n", 1, 5, fpLock );
     420                 :     fclose( fpLock );
     421                 : 
     422                 :     return pszLockFilename;
     423                 : }
     424                 : 
     425                 : /************************************************************************/
     426                 : /*                           CPLUnlockFile()                            */
     427                 : /************************************************************************/
     428                 : 
     429                 : void CPLUnlockFile( void *hLock )
     430                 : 
     431                 : {
     432                 :     char *pszLockFilename = (char *) hLock;
     433                 : 
     434                 :     if( hLock == NULL )
     435                 :         return;
     436                 :     
     437                 :     VSIUnlink( pszLockFilename );
     438                 :     
     439                 :     CPLFree( pszLockFilename );
     440                 : }
     441                 : 
     442                 : /************************************************************************/
     443                 : /*                             CPLGetPID()                              */
     444                 : /************************************************************************/
     445                 : 
     446                 : GIntBig CPLGetPID()
     447                 : 
     448                 : {
     449                 :     return 1;
     450                 : }
     451                 : 
     452                 : /************************************************************************/
     453                 : /*                          CPLCreateThread();                          */
     454                 : /************************************************************************/
     455                 : 
     456                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pArg )
     457                 : 
     458                 : {
     459                 :     CPLDebug( "CPLCreateThread", "Fails to dummy implementation" );
     460                 : 
     461                 :     return -1;
     462                 : }
     463                 : 
     464                 : /************************************************************************/
     465                 : /*                      CPLCreateJoinableThread()                       */
     466                 : /************************************************************************/
     467                 : 
     468                 : void* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
     469                 : 
     470                 : {
     471                 :     CPLDebug( "CPLCreateJoinableThread", "Fails to dummy implementation" );
     472                 : 
     473                 :     return NULL;
     474                 : }
     475                 : 
     476                 : /************************************************************************/
     477                 : /*                          CPLJoinThread()                             */
     478                 : /************************************************************************/
     479                 : 
     480                 : void CPLJoinThread(void* hJoinableThread)
     481                 : {
     482                 : }
     483                 : 
     484                 : /************************************************************************/
     485                 : /*                              CPLSleep()                              */
     486                 : /************************************************************************/
     487                 : 
     488                 : void CPLSleep( double dfWaitInSeconds )
     489                 : 
     490                 : {
     491                 :     time_t  ltime;
     492                 :     time_t  ttime;
     493                 : 
     494                 :     time( &ltime );
     495                 :     ttime = ltime + (int) (dfWaitInSeconds+0.5);
     496                 : 
     497                 :     for( ; ltime < ttime; time(&ltime) )
     498                 :     {
     499                 :         /* currently we just busy wait.  Perhaps we could at least block on 
     500                 :            io? */
     501                 :     }
     502                 : }
     503                 : 
     504                 : /************************************************************************/
     505                 : /*                           CPLGetTLSList()                            */
     506                 : /************************************************************************/
     507                 : 
     508                 : static void **papTLSList = NULL;
     509                 : 
     510                 : static void **CPLGetTLSList()
     511                 : 
     512                 : {
     513                 :     if( papTLSList == NULL )
     514                 :     {
     515                 :         papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
     516                 :         if( papTLSList == NULL )
     517                 :             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
     518                 :     }
     519                 : 
     520                 :     return papTLSList;
     521                 : }
     522                 : 
     523                 : /************************************************************************/
     524                 : /*                           CPLCleanupTLS()                            */
     525                 : /************************************************************************/
     526                 : 
     527                 : void CPLCleanupTLS()
     528                 : 
     529                 : {
     530                 :     CPLCleanupTLSList( papTLSList );
     531                 :     papTLSList = NULL;
     532                 : }
     533                 : 
     534                 : /* endif CPL_MULTIPROC_STUB */
     535                 : 
     536                 : #elif defined(CPL_MULTIPROC_WIN32)
     537                 : 
     538                 : 
     539                 :   /************************************************************************/
     540                 :   /* ==================================================================== */
     541                 :   /*                        CPL_MULTIPROC_WIN32                           */
     542                 :   /*                                                                      */
     543                 :   /*    WIN32 Implementation of multiprocessing functions.                */
     544                 :   /* ==================================================================== */
     545                 :   /************************************************************************/
     546                 : 
     547                 : /* InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x403 */
     548                 : #define _WIN32_WINNT 0x0500
     549                 : 
     550                 : #include <windows.h>
     551                 : 
     552                 : /* windows.h header must be included above following lines. */
     553                 : #if defined(WIN32CE)
     554                 : #  include "cpl_win32ce_api.h"
     555                 : #  define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
     556                 : #endif
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                             CPLGetNumCPUs()                          */
     560                 : /************************************************************************/
     561                 : 
     562                 : int CPLGetNumCPUs()
     563                 : {
     564                 :     SYSTEM_INFO info;
     565                 :     GetSystemInfo(&info);
     566                 :     DWORD dwNum = info.dwNumberOfProcessors;
     567                 :     if( dwNum < 1 )
     568                 :         return 1;
     569                 :     return (int)dwNum;
     570                 : }
     571                 : 
     572                 : /************************************************************************/
     573                 : /*                        CPLGetThreadingModel()                        */
     574                 : /************************************************************************/
     575                 : 
     576                 : const char *CPLGetThreadingModel()
     577                 : 
     578                 : {
     579                 :     return "win32";
     580                 : }
     581                 : 
     582                 : /************************************************************************/
     583                 : /*                           CPLCreateMutex()                           */
     584                 : /************************************************************************/
     585                 : 
     586                 : void *CPLCreateMutex()
     587                 : 
     588                 : {
     589                 : #ifdef USE_WIN32_MUTEX
     590                 :     HANDLE hMutex;
     591                 : 
     592                 :     hMutex = CreateMutex( NULL, TRUE, NULL );
     593                 : 
     594                 :     return (void *) hMutex;
     595                 : #else
     596                 :     CRITICAL_SECTION *pcs;
     597                 : 
     598                 :   /* Do not use CPLMalloc() since its debugging infrastructure */
     599                 :   /* can call the CPL*Mutex functions... */
     600                 :     pcs = (CRITICAL_SECTION *)malloc(sizeof(*pcs));
     601                 :     if( pcs )
     602                 :     {
     603                 :       InitializeCriticalSectionAndSpinCount(pcs, 4000);
     604                 :       EnterCriticalSection(pcs);
     605                 :     }
     606                 : 
     607                 :     return (void *) pcs;
     608                 : #endif
     609                 : }
     610                 : 
     611                 : /************************************************************************/
     612                 : /*                          CPLAcquireMutex()                           */
     613                 : /************************************************************************/
     614                 : 
     615                 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
     616                 : 
     617                 : {
     618                 : #ifdef USE_WIN32_MUTEX
     619                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     620                 :     DWORD  hr;
     621                 : 
     622                 :     hr = WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
     623                 :     
     624                 :     return hr != WAIT_TIMEOUT;
     625                 : #else
     626                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     627                 :     BOOL ret;
     628                 : 
     629                 :     while( (ret = TryEnterCriticalSection(pcs)) == 0 && dfWaitInSeconds > 0.0 )
     630                 :     {
     631                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     632                 :         dfWaitInSeconds -= 0.125;
     633                 :     }
     634                 :     
     635                 :     return ret;
     636                 : #endif
     637                 : }
     638                 : 
     639                 : /************************************************************************/
     640                 : /*                          CPLReleaseMutex()                           */
     641                 : /************************************************************************/
     642                 : 
     643                 : void CPLReleaseMutex( void *hMutexIn )
     644                 : 
     645                 : {
     646                 : #ifdef USE_WIN32_MUTEX
     647                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     648                 : 
     649                 :     ReleaseMutex( hMutex );
     650                 : #else
     651                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     652                 : 
     653                 :     LeaveCriticalSection(pcs);
     654                 : #endif
     655                 : }
     656                 : 
     657                 : /************************************************************************/
     658                 : /*                          CPLDestroyMutex()                           */
     659                 : /************************************************************************/
     660                 : 
     661                 : void CPLDestroyMutex( void *hMutexIn )
     662                 : 
     663                 : {
     664                 : #ifdef USE_WIN32_MUTEX
     665                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     666                 : 
     667                 :     CloseHandle( hMutex );
     668                 : #else
     669                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     670                 : 
     671                 :     DeleteCriticalSection( pcs );
     672                 :     free( pcs );
     673                 : #endif
     674                 : }
     675                 : 
     676                 : /************************************************************************/
     677                 : /*                            CPLCreateCond()                           */
     678                 : /************************************************************************/
     679                 : 
     680                 : struct _WaiterItem
     681                 : {
     682                 :     HANDLE hEvent;
     683                 :     struct _WaiterItem* psNext;
     684                 : };
     685                 : typedef struct _WaiterItem WaiterItem;
     686                 : 
     687                 : typedef struct
     688                 : {
     689                 :     void        *hInternalMutex;
     690                 :     WaiterItem  *psWaiterList;
     691                 : } Win32Cond;
     692                 : 
     693                 : void  *CPLCreateCond()
     694                 : {
     695                 :     Win32Cond* psCond = (Win32Cond*) malloc(sizeof(Win32Cond));
     696                 :     if (psCond == NULL)
     697                 :         return NULL;
     698                 :     psCond->hInternalMutex = CPLCreateMutex();
     699                 :     if (psCond->hInternalMutex == NULL)
     700                 :     {
     701                 :         free(psCond);
     702                 :         return NULL;
     703                 :     }
     704                 :     CPLReleaseMutex(psCond->hInternalMutex);
     705                 :     psCond->psWaiterList = NULL;
     706                 :     return psCond;
     707                 : }
     708                 : 
     709                 : /************************************************************************/
     710                 : /*                            CPLCondWait()                             */
     711                 : /************************************************************************/
     712                 : 
     713                 : static void CPLTLSFreeEvent(void* pData)
     714                 : {
     715                 :     CloseHandle((HANDLE)pData);
     716                 : }
     717                 : 
     718                 : void  CPLCondWait( void *hCond, void* hClientMutex )
     719                 : {
     720                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     721                 : 
     722                 :     HANDLE hEvent = (HANDLE) CPLGetTLS(CTLS_WIN32_COND);
     723                 :     if (hEvent == NULL)
     724                 :     {
     725                 :         hEvent = CreateEvent(NULL, /* security attributes */
     726                 :                              0,    /* manual reset = no */
     727                 :                              0,    /* initial state = unsignaled */
     728                 :                              NULL  /* no name */);
     729                 :         CPLAssert(hEvent != NULL);
     730                 : 
     731                 :         CPLSetTLSWithFreeFunc(CTLS_WIN32_COND, hEvent, CPLTLSFreeEvent);
     732                 :     }
     733                 : 
     734                 :     /* Insert the waiter into the waiter list of the condition */
     735                 :     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
     736                 : 
     737                 :     WaiterItem* psItem = (WaiterItem*)malloc(sizeof(WaiterItem));
     738                 :     CPLAssert(psItem != NULL);
     739                 : 
     740                 :     psItem->hEvent = hEvent;
     741                 :     psItem->psNext = psCond->psWaiterList;
     742                 : 
     743                 :     psCond->psWaiterList = psItem;
     744                 : 
     745                 :     CPLReleaseMutex(psCond->hInternalMutex);
     746                 : 
     747                 :     /* Release the client mutex before waiting for the event being signaled */
     748                 :     CPLReleaseMutex(hClientMutex);
     749                 : 
     750                 :     DWORD nRet = WaitForSingleObject(hEvent, INFINITE);
     751                 :     CPLAssert (nRet != WAIT_FAILED);
     752                 : 
     753                 :     /* Reacquire the client mutex */
     754                 :     CPLAcquireMutex(hClientMutex, 1000.0);
     755                 : }
     756                 : 
     757                 : /************************************************************************/
     758                 : /*                            CPLCondSignal()                           */
     759                 : /************************************************************************/
     760                 : 
     761                 : void  CPLCondSignal( void *hCond )
     762                 : {
     763                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     764                 : 
     765                 :     /* Signal the first registered event, and remove it from the list */
     766                 :     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
     767                 : 
     768                 :     WaiterItem* psIter = psCond->psWaiterList;
     769                 :     if (psIter != NULL)
     770                 :     {
     771                 :         SetEvent(psIter->hEvent);
     772                 :         psCond->psWaiterList = psIter->psNext;
     773                 :         free(psIter);
     774                 :     }
     775                 : 
     776                 :     CPLReleaseMutex(psCond->hInternalMutex);
     777                 : }
     778                 : 
     779                 : /************************************************************************/
     780                 : /*                           CPLCondBroadcast()                         */
     781                 : /************************************************************************/
     782                 : 
     783                 : void  CPLCondBroadcast( void *hCond )
     784                 : {
     785                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     786                 : 
     787                 :     /* Signal all the registered events, and remove them from the list */
     788                 :     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
     789                 : 
     790                 :     WaiterItem* psIter = psCond->psWaiterList;
     791                 :     while (psIter != NULL)
     792                 :     {
     793                 :         WaiterItem* psNext = psIter->psNext;
     794                 :         SetEvent(psIter->hEvent);
     795                 :         free(psIter);
     796                 :         psIter = psNext;
     797                 :     }
     798                 :     psCond->psWaiterList = NULL;
     799                 : 
     800                 :     CPLReleaseMutex(psCond->hInternalMutex);
     801                 : }
     802                 : 
     803                 : /************************************************************************/
     804                 : /*                            CPLDestroyCond()                          */
     805                 : /************************************************************************/
     806                 : 
     807                 : void  CPLDestroyCond( void *hCond )
     808                 : {
     809                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     810                 :     CPLDestroyMutex(psCond->hInternalMutex);
     811                 :     psCond->hInternalMutex = NULL;
     812                 :     CPLAssert(psCond->psWaiterList == NULL);
     813                 :     free(psCond);
     814                 : }
     815                 : 
     816                 : /************************************************************************/
     817                 : /*                            CPLLockFile()                             */
     818                 : /************************************************************************/
     819                 : 
     820                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     821                 : 
     822                 : {
     823                 :     char      *pszLockFilename;
     824                 :     HANDLE    hLockFile;
     825                 :     
     826                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     827                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     828                 : 
     829                 :     hLockFile = 
     830                 :         CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW, 
     831                 :                     FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
     832                 : 
     833                 :     while( GetLastError() == ERROR_ALREADY_EXISTS
     834                 :            && dfWaitInSeconds > 0.0 )
     835                 :     {
     836                 :         CloseHandle( hLockFile );
     837                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     838                 :         dfWaitInSeconds -= 0.125;
     839                 : 
     840                 :         hLockFile = 
     841                 :             CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, 
     842                 :                         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, 
     843                 :                         NULL );
     844                 :     }
     845                 : 
     846                 :     CPLFree( pszLockFilename );
     847                 : 
     848                 :     if( hLockFile == INVALID_HANDLE_VALUE )
     849                 :         return NULL;
     850                 : 
     851                 :     if( GetLastError() == ERROR_ALREADY_EXISTS )
     852                 :     {
     853                 :         CloseHandle( hLockFile );
     854                 :         return NULL;
     855                 :     }
     856                 : 
     857                 :     return (void *) hLockFile;
     858                 : }
     859                 : 
     860                 : /************************************************************************/
     861                 : /*                           CPLUnlockFile()                            */
     862                 : /************************************************************************/
     863                 : 
     864                 : void CPLUnlockFile( void *hLock )
     865                 : 
     866                 : {
     867                 :     HANDLE    hLockFile = (HANDLE) hLock;
     868                 : 
     869                 :     CloseHandle( hLockFile );
     870                 : }
     871                 : 
     872                 : /************************************************************************/
     873                 : /*                             CPLGetPID()                              */
     874                 : /************************************************************************/
     875                 : 
     876                 : GIntBig CPLGetPID()
     877                 : 
     878                 : {
     879                 :     return (GIntBig) GetCurrentThreadId();
     880                 : }
     881                 : 
     882                 : /************************************************************************/
     883                 : /*                       CPLStdCallThreadJacket()                       */
     884                 : /************************************************************************/
     885                 : 
     886                 : typedef struct {
     887                 :     void *pAppData;
     888                 :     CPLThreadFunc pfnMain;
     889                 :     HANDLE hThread;
     890                 : } CPLStdCallThreadInfo;
     891                 : 
     892                 : static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
     893                 : 
     894                 : {
     895                 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
     896                 : 
     897                 :     psInfo->pfnMain( psInfo->pAppData );
     898                 : 
     899                 :     if (psInfo->hThread == NULL)
     900                 :         CPLFree( psInfo ); /* Only for detached threads */
     901                 : 
     902                 :     CPLCleanupTLS();
     903                 : 
     904                 :     return 0;
     905                 : }
     906                 : 
     907                 : /************************************************************************/
     908                 : /*                          CPLCreateThread()                           */
     909                 : /*                                                                      */
     910                 : /*      The WIN32 CreateThread() call requires an entry point that      */
     911                 : /*      has __stdcall conventions, so we provide a jacket function      */
     912                 : /*      to supply that.                                                 */
     913                 : /************************************************************************/
     914                 : 
     915                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     916                 : 
     917                 : {
     918                 :     HANDLE hThread;
     919                 :     DWORD  nThreadId;
     920                 :     CPLStdCallThreadInfo *psInfo;
     921                 : 
     922                 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     923                 :     psInfo->pAppData = pThreadArg;
     924                 :     psInfo->pfnMain = pfnMain;
     925                 :     psInfo->hThread = NULL;
     926                 : 
     927                 :     hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
     928                 :                             0, &nThreadId );
     929                 : 
     930                 :     if( hThread == NULL )
     931                 :         return -1;
     932                 : 
     933                 :     CloseHandle( hThread );
     934                 : 
     935                 :     return nThreadId;
     936                 : }
     937                 : 
     938                 : /************************************************************************/
     939                 : /*                      CPLCreateJoinableThread()                       */
     940                 : /************************************************************************/
     941                 : 
     942                 : void* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
     943                 : 
     944                 : {
     945                 :     HANDLE hThread;
     946                 :     DWORD  nThreadId;
     947                 :     CPLStdCallThreadInfo *psInfo;
     948                 : 
     949                 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     950                 :     psInfo->pAppData = pThreadArg;
     951                 :     psInfo->pfnMain = pfnMain;
     952                 : 
     953                 :     hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
     954                 :                             0, &nThreadId );
     955                 : 
     956                 :     if( hThread == NULL )
     957                 :         return NULL;
     958                 :         
     959                 :     psInfo->hThread = hThread;
     960                 :     return psInfo;
     961                 : }
     962                 : 
     963                 : /************************************************************************/
     964                 : /*                          CPLJoinThread()                             */
     965                 : /************************************************************************/
     966                 : 
     967                 : void CPLJoinThread(void* hJoinableThread)
     968                 : {
     969                 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) hJoinableThread;
     970                 :     
     971                 :     WaitForSingleObject(psInfo->hThread, INFINITE);
     972                 :     CloseHandle( psInfo->hThread );
     973                 :     CPLFree( psInfo );
     974                 : }
     975                 : 
     976                 : /************************************************************************/
     977                 : /*                              CPLSleep()                              */
     978                 : /************************************************************************/
     979                 : 
     980                 : void CPLSleep( double dfWaitInSeconds )
     981                 : 
     982                 : {
     983                 :     Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
     984                 : }
     985                 : 
     986                 : static int           bTLSKeySetup = FALSE;
     987                 : static DWORD         nTLSKey;
     988                 : 
     989                 : /************************************************************************/
     990                 : /*                           CPLGetTLSList()                            */
     991                 : /************************************************************************/
     992                 : 
     993                 : static void **CPLGetTLSList()
     994                 : 
     995                 : {
     996                 :     void **papTLSList;
     997                 : 
     998                 :     if( !bTLSKeySetup )
     999                 :     {
    1000                 :         nTLSKey = TlsAlloc();
    1001                 :         if( nTLSKey == TLS_OUT_OF_INDEXES )
    1002                 :         {
    1003                 :             CPLEmergencyError( "CPLGetTLSList(): TlsAlloc() failed!" );
    1004                 :         }
    1005                 :         bTLSKeySetup = TRUE;
    1006                 :     }
    1007                 : 
    1008                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
    1009                 :     if( papTLSList == NULL )
    1010                 :     {
    1011                 :         papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
    1012                 :         if( papTLSList == NULL )
    1013                 :             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
    1014                 :         if( TlsSetValue( nTLSKey, papTLSList ) == 0 )
    1015                 :         {
    1016                 :             CPLEmergencyError( "CPLGetTLSList(): TlsSetValue() failed!" );
    1017                 :         }
    1018                 :     }
    1019                 : 
    1020                 :     return papTLSList;
    1021                 : }
    1022                 : 
    1023                 : /************************************************************************/
    1024                 : /*                           CPLCleanupTLS()                            */
    1025                 : /************************************************************************/
    1026                 : 
    1027                 : void CPLCleanupTLS()
    1028                 : 
    1029                 : {
    1030                 :     void **papTLSList;
    1031                 : 
    1032                 :     if( !bTLSKeySetup )
    1033                 :         return;
    1034                 : 
    1035                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
    1036                 :     if( papTLSList == NULL )
    1037                 :         return;
    1038                 : 
    1039                 :     TlsSetValue( nTLSKey, NULL );
    1040                 : 
    1041                 :     CPLCleanupTLSList( papTLSList );
    1042                 : }
    1043                 : 
    1044                 : /* endif CPL_MULTIPROC_WIN32 */
    1045                 : 
    1046                 : #elif defined(CPL_MULTIPROC_PTHREAD)
    1047                 : 
    1048                 : #include <pthread.h>
    1049                 : #include <time.h>
    1050                 : #include <unistd.h>
    1051                 : 
    1052                 :   /************************************************************************/
    1053                 :   /* ==================================================================== */
    1054                 :   /*                        CPL_MULTIPROC_PTHREAD                         */
    1055                 :   /*                                                                      */
    1056                 :   /*    PTHREAD Implementation of multiprocessing functions.              */
    1057                 :   /* ==================================================================== */
    1058                 :   /************************************************************************/
    1059                 : 
    1060                 : /************************************************************************/
    1061                 : /*                             CPLGetNumCPUs()                          */
    1062                 : /************************************************************************/
    1063                 : 
    1064              48 : int CPLGetNumCPUs()
    1065                 : {
    1066                 : #ifdef _SC_NPROCESSORS_ONLN
    1067              48 :     return (int)sysconf(_SC_NPROCESSORS_ONLN);
    1068                 : #else
    1069                 :     return 1;
    1070                 : #endif
    1071                 : }
    1072                 : 
    1073                 : /************************************************************************/
    1074                 : /*                      CPLCreateOrAcquireMutex()                       */
    1075                 : /************************************************************************/
    1076                 : 
    1077                 : static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
    1078                 : static void *CPLCreateMutexInternal(int bAlreadyInGlobalLock);
    1079                 : 
    1080        16092990 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
    1081                 : 
    1082                 : {
    1083        16092990 :     int bSuccess = FALSE;
    1084                 : 
    1085        16092990 :     pthread_mutex_lock(&global_mutex);
    1086        16092990 :     if( *phMutex == NULL )
    1087                 :     {
    1088            8491 :         *phMutex = CPLCreateMutexInternal(TRUE);
    1089            8491 :         bSuccess = *phMutex != NULL;
    1090            8491 :         pthread_mutex_unlock(&global_mutex);
    1091                 :     }
    1092                 :     else
    1093                 :     {
    1094        16084499 :         pthread_mutex_unlock(&global_mutex);
    1095                 : 
    1096        16084499 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
    1097                 :     }
    1098                 : 
    1099        16092990 :     return bSuccess;
    1100                 : }
    1101                 : 
    1102                 : /************************************************************************/
    1103                 : /*                        CPLGetThreadingModel()                        */
    1104                 : /************************************************************************/
    1105                 : 
    1106               0 : const char *CPLGetThreadingModel()
    1107                 : 
    1108                 : {
    1109               0 :     return "pthread";
    1110                 : }
    1111                 : 
    1112                 : /************************************************************************/
    1113                 : /*                           CPLCreateMutex()                           */
    1114                 : /************************************************************************/
    1115                 : 
    1116                 : typedef struct _MutexLinkedElt MutexLinkedElt;
    1117                 : struct _MutexLinkedElt
    1118                 : {
    1119                 :     pthread_mutex_t   sMutex;
    1120                 :     _MutexLinkedElt  *psPrev;
    1121                 :     _MutexLinkedElt  *psNext;
    1122                 : };
    1123                 : static MutexLinkedElt* psMutexList = NULL;
    1124                 : 
    1125            9440 : static void CPLInitMutex(MutexLinkedElt* psItem)
    1126                 : {
    1127                 : #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
    1128                 :     {
    1129                 :         pthread_mutexattr_t  attr;
    1130            9440 :         pthread_mutexattr_init( &attr );
    1131            9440 :         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
    1132            9440 :         pthread_mutex_init( &(psItem->sMutex), &attr );
    1133                 :     }
    1134                 : /* BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define. */
    1135                 : /* But they have #define MUTEX_TYPE_COUNTING_FAST   PTHREAD_MUTEX_RECURSIVE */
    1136                 : #elif defined(MUTEX_TYPE_COUNTING_FAST)
    1137                 :     {
    1138                 :         pthread_mutexattr_t  attr;
    1139                 :         pthread_mutexattr_init( &attr );
    1140                 :         pthread_mutexattr_settype( &attr, MUTEX_TYPE_COUNTING_FAST );
    1141                 :         pthread_mutex_init( &(psItem->sMutex), &attr );
    1142                 :     }
    1143                 : #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
    1144                 :     pthread_mutex_t tmp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
    1145                 :     psItem->sMutex = tmp_mutex;
    1146                 : #else
    1147                 : #error "Recursive mutexes apparently unsupported, configure --without-threads" 
    1148                 : #endif
    1149            9440 : }
    1150                 : 
    1151            9440 : static void *CPLCreateMutexInternal(int bAlreadyInGlobalLock)
    1152                 : {
    1153            9440 :     MutexLinkedElt* psItem = (MutexLinkedElt *) malloc(sizeof(MutexLinkedElt));
    1154            9440 :     if (psItem == NULL)
    1155               0 :         return NULL;
    1156                 : 
    1157            9440 :     if( !bAlreadyInGlobalLock )
    1158             949 :         pthread_mutex_lock(&global_mutex);
    1159            9440 :     psItem->psPrev = NULL;
    1160            9440 :     psItem->psNext = psMutexList;
    1161            9440 :     if( psMutexList )
    1162            8683 :         psMutexList->psPrev = psItem;
    1163            9440 :     psMutexList = psItem;
    1164            9440 :     if( !bAlreadyInGlobalLock )
    1165             949 :         pthread_mutex_unlock(&global_mutex);
    1166                 : 
    1167            9440 :     CPLInitMutex(psItem);
    1168                 : 
    1169                 :     // mutexes are implicitly acquired when created.
    1170            9440 :     CPLAcquireMutex( &(psItem->sMutex), 0.0 );
    1171                 : 
    1172            9440 :     return psItem;
    1173                 : }
    1174                 : 
    1175             949 : void *CPLCreateMutex()
    1176                 : {
    1177             949 :     return CPLCreateMutexInternal(FALSE);
    1178                 : }
    1179                 : 
    1180                 : /************************************************************************/
    1181                 : /*                          CPLAcquireMutex()                           */
    1182                 : /************************************************************************/
    1183                 : 
    1184        16130223 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
    1185                 : 
    1186                 : {
    1187                 :     int err;
    1188                 : 
    1189                 :     /* we need to add timeout support */
    1190        16130223 :     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
    1191        16130223 :     err =  pthread_mutex_lock( &(psItem->sMutex) );
    1192                 :     
    1193        16130224 :     if( err != 0 )
    1194                 :     {
    1195               0 :         if( err == EDEADLK )
    1196               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d/EDEADLK", err );
    1197                 :         else
    1198               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d", err );
    1199                 : 
    1200               0 :         return FALSE;
    1201                 :     }
    1202                 : 
    1203        16130224 :     return TRUE;
    1204                 : }
    1205                 : 
    1206                 : /************************************************************************/
    1207                 : /*                          CPLReleaseMutex()                           */
    1208                 : /************************************************************************/
    1209                 : 
    1210        16130224 : void CPLReleaseMutex( void *hMutexIn )
    1211                 : 
    1212                 : {
    1213        16130224 :     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
    1214        16130224 :     pthread_mutex_unlock( &(psItem->sMutex) );
    1215        16130224 : }
    1216                 : 
    1217                 : /************************************************************************/
    1218                 : /*                          CPLDestroyMutex()                           */
    1219                 : /************************************************************************/
    1220                 : 
    1221            8085 : void CPLDestroyMutex( void *hMutexIn )
    1222                 : 
    1223                 : {
    1224            8085 :     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
    1225            8085 :     pthread_mutex_destroy( &(psItem->sMutex) );
    1226            8085 :     pthread_mutex_lock(&global_mutex);
    1227            8085 :     if( psItem->psPrev )
    1228            5144 :         psItem->psPrev->psNext = psItem->psNext;
    1229            8085 :     if( psItem->psNext )
    1230            6677 :         psItem->psNext->psPrev = psItem->psPrev;
    1231            8085 :     if( psItem == psMutexList )
    1232            2941 :         psMutexList = psItem->psNext;
    1233            8085 :     pthread_mutex_unlock(&global_mutex);
    1234            8085 :     free( hMutexIn );
    1235            8085 : }
    1236                 : 
    1237                 : /************************************************************************/
    1238                 : /*                          CPLReinitAllMutex()                         */
    1239                 : /************************************************************************/
    1240                 : 
    1241                 : /* Used by gdalclientserver.cpp just after forking, to avoid */
    1242                 : /* deadlocks while mixing threads with fork */
    1243                 : void CPLReinitAllMutex();
    1244               0 : void CPLReinitAllMutex()
    1245                 : {
    1246               0 :     MutexLinkedElt* psItem = psMutexList;
    1247               0 :     while(psItem != NULL )
    1248                 :     {
    1249               0 :         CPLInitMutex(psItem);
    1250               0 :         psItem = psItem->psNext;
    1251                 :     }
    1252               0 :     pthread_mutex_t tmp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
    1253               0 :     global_mutex = tmp_global_mutex;
    1254               0 : }
    1255                 : 
    1256                 : /************************************************************************/
    1257                 : /*                            CPLCreateCond()                           */
    1258                 : /************************************************************************/
    1259                 : 
    1260             126 : void  *CPLCreateCond()
    1261                 : {
    1262             126 :     pthread_cond_t* pCond = (pthread_cond_t* )malloc(sizeof(pthread_cond_t));
    1263             126 :     if (pCond)
    1264             126 :         pthread_cond_init(pCond, NULL);
    1265             126 :     return pCond;
    1266                 : }
    1267                 : 
    1268                 : /************************************************************************/
    1269                 : /*                            CPLCondWait()                             */
    1270                 : /************************************************************************/
    1271                 : 
    1272            1500 : void  CPLCondWait( void *hCond, void* hMutex )
    1273                 : {
    1274            1500 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1275            1500 :     pthread_mutex_t * pMutex = (pthread_mutex_t *)hMutex;
    1276            1500 :     pthread_cond_wait(pCond,  pMutex);
    1277            1500 : }
    1278                 : 
    1279                 : /************************************************************************/
    1280                 : /*                            CPLCondSignal()                           */
    1281                 : /************************************************************************/
    1282                 : 
    1283            3529 : void  CPLCondSignal( void *hCond )
    1284                 : {
    1285            3529 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1286            3529 :     pthread_cond_signal(pCond);
    1287            3529 : }
    1288                 : 
    1289                 : /************************************************************************/
    1290                 : /*                           CPLCondBroadcast()                         */
    1291                 : /************************************************************************/
    1292                 : 
    1293               0 : void  CPLCondBroadcast( void *hCond )
    1294                 : {
    1295               0 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1296               0 :     pthread_cond_broadcast(pCond);
    1297               0 : }
    1298                 : 
    1299                 : /************************************************************************/
    1300                 : /*                            CPLDestroyCond()                          */
    1301                 : /************************************************************************/
    1302                 : 
    1303             126 : void  CPLDestroyCond( void *hCond )
    1304                 : {
    1305             126 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1306             126 :     pthread_cond_destroy(pCond);
    1307             126 :     free(hCond);
    1308             126 : }
    1309                 : 
    1310                 : /************************************************************************/
    1311                 : /*                            CPLLockFile()                             */
    1312                 : /*                                                                      */
    1313                 : /*      This is really a stub implementation, see first                 */
    1314                 : /*      CPLLockFile() for caveats.                                      */
    1315                 : /************************************************************************/
    1316                 : 
    1317               2 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
    1318                 : 
    1319                 : {
    1320                 :     FILE      *fpLock;
    1321                 :     char      *pszLockFilename;
    1322                 :     
    1323                 : /* -------------------------------------------------------------------- */
    1324                 : /*      We use a lock file with a name derived from the file we want    */
    1325                 : /*      to lock to represent the file being locked.  Note that for      */
    1326                 : /*      the stub implementation the target file does not even need      */
    1327                 : /*      to exist to be locked.                                          */
    1328                 : /* -------------------------------------------------------------------- */
    1329               2 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
    1330               2 :     sprintf( pszLockFilename, "%s.lock", pszPath );
    1331                 : 
    1332               2 :     fpLock = fopen( pszLockFilename, "r" );
    1333               4 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
    1334                 :     {
    1335               0 :         fclose( fpLock );
    1336               0 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
    1337               0 :         dfWaitInSeconds -= 0.5;
    1338                 : 
    1339               0 :         fpLock = fopen( pszLockFilename, "r" );
    1340                 :     }
    1341                 :         
    1342               2 :     if( fpLock != NULL )
    1343                 :     {
    1344               0 :         fclose( fpLock );
    1345               0 :         CPLFree( pszLockFilename );
    1346               0 :         return NULL;
    1347                 :     }
    1348                 : 
    1349               2 :     fpLock = fopen( pszLockFilename, "w" );
    1350                 : 
    1351               2 :     if( fpLock == NULL )
    1352                 :     {
    1353               0 :         CPLFree( pszLockFilename );
    1354               0 :         return NULL;
    1355                 :     }
    1356                 : 
    1357               2 :     fwrite( "held\n", 1, 5, fpLock );
    1358               2 :     fclose( fpLock );
    1359                 : 
    1360               2 :     return pszLockFilename;
    1361                 : }
    1362                 : 
    1363                 : /************************************************************************/
    1364                 : /*                           CPLUnlockFile()                            */
    1365                 : /************************************************************************/
    1366                 : 
    1367               2 : void CPLUnlockFile( void *hLock )
    1368                 : 
    1369                 : {
    1370               2 :     char *pszLockFilename = (char *) hLock;
    1371                 : 
    1372               2 :     if( hLock == NULL )
    1373               0 :         return;
    1374                 :     
    1375               2 :     VSIUnlink( pszLockFilename );
    1376                 :     
    1377               2 :     CPLFree( pszLockFilename );
    1378                 : }
    1379                 : 
    1380                 : /************************************************************************/
    1381                 : /*                             CPLGetPID()                              */
    1382                 : /************************************************************************/
    1383                 : 
    1384           36292 : GIntBig CPLGetPID()
    1385                 : 
    1386                 : {
    1387           36292 :     return (GIntBig) pthread_self();
    1388                 : }
    1389                 : 
    1390                 : /************************************************************************/
    1391                 : /*                       CPLStdCallThreadJacket()                       */
    1392                 : /************************************************************************/
    1393                 : 
    1394                 : typedef struct {
    1395                 :     void *pAppData;
    1396                 :     CPLThreadFunc pfnMain;
    1397                 :     pthread_t hThread;
    1398                 :     int bJoinable;
    1399                 : } CPLStdCallThreadInfo;
    1400                 : 
    1401             200 : static void *CPLStdCallThreadJacket( void *pData )
    1402                 : 
    1403                 : {
    1404             200 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
    1405                 : 
    1406             200 :     psInfo->pfnMain( psInfo->pAppData );
    1407                 : 
    1408             200 :     if (!psInfo->bJoinable)
    1409               0 :         CPLFree( psInfo );
    1410                 : 
    1411             200 :     return NULL;
    1412                 : }
    1413                 : 
    1414                 : /************************************************************************/
    1415                 : /*                          CPLCreateThread()                           */
    1416                 : /*                                                                      */
    1417                 : /*      The WIN32 CreateThread() call requires an entry point that      */
    1418                 : /*      has __stdcall conventions, so we provide a jacket function      */
    1419                 : /*      to supply that.                                                 */
    1420                 : /************************************************************************/
    1421                 : 
    1422               0 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
    1423                 : 
    1424                 : {
    1425                 : 
    1426                 :     CPLStdCallThreadInfo *psInfo;
    1427                 :     pthread_attr_t hThreadAttr;
    1428                 : 
    1429               0 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
    1430               0 :     psInfo->pAppData = pThreadArg;
    1431               0 :     psInfo->pfnMain = pfnMain;
    1432               0 :     psInfo->bJoinable = FALSE;
    1433                 : 
    1434               0 :     pthread_attr_init( &hThreadAttr );
    1435               0 :     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
    1436               0 :     if( pthread_create( &(psInfo->hThread), &hThreadAttr, 
    1437                 :                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
    1438                 :     {
    1439               0 :         CPLFree( psInfo );
    1440               0 :         return -1;
    1441                 :     }
    1442                 : 
    1443               0 :     return 1; /* can we return the actual thread pid? */
    1444                 : }
    1445                 : 
    1446                 : /************************************************************************/
    1447                 : /*                      CPLCreateJoinableThread()                       */
    1448                 : /************************************************************************/
    1449                 : 
    1450             200 : void* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
    1451                 : 
    1452                 : {
    1453                 :     CPLStdCallThreadInfo *psInfo;
    1454                 :     pthread_attr_t hThreadAttr;
    1455                 : 
    1456             200 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
    1457             200 :     psInfo->pAppData = pThreadArg;
    1458             200 :     psInfo->pfnMain = pfnMain;
    1459             200 :     psInfo->bJoinable = TRUE;
    1460                 : 
    1461             200 :     pthread_attr_init( &hThreadAttr );
    1462             200 :     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_JOINABLE );
    1463             200 :     if( pthread_create( &(psInfo->hThread), &hThreadAttr,
    1464                 :                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
    1465                 :     {
    1466               0 :         CPLFree( psInfo );
    1467               0 :         return NULL;
    1468                 :     }
    1469                 : 
    1470             200 :     return psInfo;
    1471                 : }
    1472                 : 
    1473                 : /************************************************************************/
    1474                 : /*                          CPLJoinThread()                             */
    1475                 : /************************************************************************/
    1476                 : 
    1477             200 : void CPLJoinThread(void* hJoinableThread)
    1478                 : {
    1479             200 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo*) hJoinableThread;
    1480                 : 
    1481                 :     void* status;
    1482             200 :     pthread_join( psInfo->hThread, &status);
    1483                 : 
    1484             200 :     CPLFree(psInfo);
    1485             200 : }
    1486                 : 
    1487                 : /************************************************************************/
    1488                 : /*                              CPLSleep()                              */
    1489                 : /************************************************************************/
    1490                 : 
    1491               9 : void CPLSleep( double dfWaitInSeconds )
    1492                 : 
    1493                 : {
    1494                 :     struct timespec sRequest, sRemain;
    1495                 : 
    1496               9 :     sRequest.tv_sec = (int) floor(dfWaitInSeconds);
    1497               9 :     sRequest.tv_nsec = (int) ((dfWaitInSeconds - sRequest.tv_sec)*1000000000);
    1498               9 :     nanosleep( &sRequest, &sRemain );
    1499               9 : }
    1500                 : 
    1501                 : static pthread_key_t  oTLSKey;
    1502                 : static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
    1503                 : 
    1504                 : /************************************************************************/
    1505                 : /*                             CPLMake_key()                            */
    1506                 : /************************************************************************/
    1507                 : 
    1508             758 : static void CPLMake_key()
    1509                 : 
    1510                 : {
    1511             758 :     if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
    1512                 :     {
    1513               0 :         CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
    1514                 :     }
    1515             758 : }
    1516                 : 
    1517                 : /************************************************************************/
    1518                 : /*                             CPLCleanupTLS()                          */
    1519                 : /************************************************************************/
    1520                 : 
    1521            1074 : void CPLCleanupTLS()
    1522                 : 
    1523                 : {
    1524                 :     void **papTLSList;
    1525                 : 
    1526            1074 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1527            1074 :     if( papTLSList == NULL )
    1528              22 :         return;
    1529                 : 
    1530            1052 :     pthread_setspecific( oTLSKey, NULL );
    1531                 : 
    1532            1052 :     CPLCleanupTLSList( papTLSList );
    1533                 : }
    1534                 : 
    1535                 : /************************************************************************/
    1536                 : /*                           CPLGetTLSList()                            */
    1537                 : /************************************************************************/
    1538                 : 
    1539        38499073 : static void **CPLGetTLSList()
    1540                 : 
    1541                 : {
    1542                 :     void **papTLSList;
    1543                 : 
    1544        38499073 :     if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
    1545                 :     {
    1546               0 :         CPLEmergencyError( "CPLGetTLSList(): pthread_once() failed!" );
    1547                 :     }
    1548                 : 
    1549        38499073 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1550        38499073 :     if( papTLSList == NULL )
    1551                 :     {
    1552            1197 :         papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
    1553            1197 :         if( papTLSList == NULL )
    1554               0 :             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
    1555            1197 :         if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
    1556                 :         {
    1557                 :             CPLEmergencyError( 
    1558               0 :                 "CPLGetTLSList(): pthread_setspecific() failed!" );
    1559                 :         }
    1560                 :     }
    1561                 : 
    1562        38499072 :     return papTLSList;
    1563                 : }
    1564                 : 
    1565                 : #endif /* def CPL_MULTIPROC_PTHREAD */
    1566                 : 
    1567                 : /************************************************************************/
    1568                 : /*                             CPLGetTLS()                              */
    1569                 : /************************************************************************/
    1570                 : 
    1571        38487648 : void *CPLGetTLS( int nIndex )
    1572                 : 
    1573                 : {
    1574        38487648 :     void** papTLSList = CPLGetTLSList();
    1575                 : 
    1576        38487648 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1577                 : 
    1578        38487647 :     return papTLSList[nIndex];
    1579                 : }
    1580                 : 
    1581                 : /************************************************************************/
    1582                 : /*                             CPLSetTLS()                              */
    1583                 : /************************************************************************/
    1584                 : 
    1585            8983 : void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
    1586                 : 
    1587                 : {
    1588            8983 :     CPLSetTLSWithFreeFunc(nIndex, pData, (bFreeOnExit) ? CPLFree : NULL);
    1589            8983 : }
    1590                 : 
    1591                 : /************************************************************************/
    1592                 : /*                      CPLSetTLSWithFreeFunc()                         */
    1593                 : /************************************************************************/
    1594                 : 
    1595                 : /* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
    1596                 : /* use or fetch any TLS data, or a terminating thread will hang ! */
    1597           11425 : void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
    1598                 : 
    1599                 : {
    1600           11425 :     void **papTLSList = CPLGetTLSList();
    1601                 : 
    1602           11425 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1603                 : 
    1604           11425 :     papTLSList[nIndex] = pData;
    1605           11425 :     papTLSList[CTLS_MAX + nIndex] = (void*) pfnFree;
    1606           11425 : }

Generated by: LCOV version 1.7