LTP GCOV extension - code coverage report
Current view: directory - port - cpl_multiproc.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 132
Code covered: 68.9 % Executed lines: 91

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_multiproc.cpp 19918 2010-06-25 21:39:33Z ilucena $
       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 19918 2010-06-25 21:39:33Z ilucena $");
      44                 : 
      45                 : #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
      46                 : #  define MUTEX_NONE
      47                 : #endif
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                           CPLMutexHolder()                           */
      51                 : /************************************************************************/
      52                 : 
      53                 : CPLMutexHolder::CPLMutexHolder( void **phMutex, double dfWaitInSeconds,
      54                 :                                 const char *pszFileIn, 
      55        12216627 :                                 int nLineIn )
      56                 : 
      57                 : {
      58                 : #ifndef MUTEX_NONE
      59        12216627 :     pszFile = pszFileIn;
      60        12216627 :     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        12216627 :     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        12216627 :         hMutex = *phMutex;
      87                 :     }
      88                 : #endif /* ndef MUTEX_NONE */
      89        12216627 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          ~CPLMutexHolder()                           */
      93                 : /************************************************************************/
      94                 : 
      95        12216627 : CPLMutexHolder::~CPLMutexHolder()
      96                 : 
      97                 : {
      98                 : #ifndef MUTEX_NONE
      99        12216627 :     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        12216627 :         CPLReleaseMutex( hMutex );
     107                 :     }
     108                 : #endif /* ndef MUTEX_NONE */
     109        12216627 : }
     110                 : 
     111                 : 
     112                 : /************************************************************************/
     113                 : /*                      CPLCreateOrAcquireMutex()                       */
     114                 : /************************************************************************/
     115                 : 
     116                 : #ifndef CPL_MULTIPROC_PTHREAD
     117                 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
     118                 : 
     119                 : {
     120                 :     int bSuccess = FALSE;
     121                 : 
     122                 : #ifndef MUTEX_NONE
     123                 :     static void *hCOAMutex = NULL;
     124                 : 
     125                 :     /*
     126                 :     ** ironically, creation of this initial mutex is not threadsafe
     127                 :     ** even though we use it to ensure that creation of other mutexes
     128                 :     ** is threadsafe. 
     129                 :     */
     130                 :     if( hCOAMutex == NULL )
     131                 :     {
     132                 :         hCOAMutex = CPLCreateMutex();
     133                 :         if (hCOAMutex == NULL)
     134                 :         {
     135                 :             *phMutex = NULL;
     136                 :             return FALSE;
     137                 :         }
     138                 :     }
     139                 :     else
     140                 :     {
     141                 :         CPLAcquireMutex( hCOAMutex, dfWaitInSeconds );
     142                 :     }
     143                 : 
     144                 :     if( *phMutex == NULL )
     145                 :     {
     146                 :         *phMutex = CPLCreateMutex();
     147                 :         bSuccess = *phMutex != NULL;
     148                 :         CPLReleaseMutex( hCOAMutex );
     149                 :     }
     150                 :     else
     151                 :     {
     152                 :         CPLReleaseMutex( hCOAMutex );
     153                 : 
     154                 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
     155                 :     }
     156                 : #endif /* ndef MUTEX_NONE */
     157                 : 
     158                 :     return bSuccess;
     159                 : }
     160                 : #endif
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                        CPLCleanupTLSList()                           */
     164                 : /*                                                                      */
     165                 : /*      Free resources associated with a TLS vector (implementation     */
     166                 : /*      independent).                                                   */
     167                 : /************************************************************************/
     168                 : 
     169             720 : static void CPLCleanupTLSList( void **papTLSList )
     170                 : 
     171                 : {
     172                 :     int i;
     173                 : 
     174                 : //    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
     175                 :     
     176             720 :     if( papTLSList == NULL )
     177               0 :         return;
     178                 : 
     179           23760 :     for( i = 0; i < CTLS_MAX; i++ )
     180                 :     {
     181           23040 :         if( papTLSList[i] != NULL && papTLSList[i+CTLS_MAX] != NULL )
     182                 :         {
     183            2113 :             CPLFree( papTLSList[i] );
     184                 :         }
     185                 :     }
     186                 : 
     187             720 :     CPLFree( papTLSList );
     188                 : }
     189                 : 
     190                 : #ifdef CPL_MULTIPROC_STUB
     191                 : /************************************************************************/
     192                 : /* ==================================================================== */
     193                 : /*                        CPL_MULTIPROC_STUB                            */
     194                 : /*                                                                      */
     195                 : /*      Stub implementation.  Mutexes don't provide exclusion, file     */
     196                 : /*      locking is achieved with extra "lock files", and thread         */
     197                 : /*      creation doesn't work.  The PID is always just one.             */
     198                 : /* ==================================================================== */
     199                 : /************************************************************************/
     200                 : 
     201                 : /************************************************************************/
     202                 : /*                        CPLGetThreadingModel()                        */
     203                 : /************************************************************************/
     204                 : 
     205                 : const char *CPLGetThreadingModel()
     206                 : 
     207                 : {
     208                 :     return "stub";
     209                 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                           CPLCreateMutex()                           */
     213                 : /************************************************************************/
     214                 : 
     215                 : void *CPLCreateMutex()
     216                 : 
     217                 : {
     218                 : #ifndef MUTEX_NONE
     219                 :     unsigned char *pabyMutex = (unsigned char *) CPLMalloc( 4 );
     220                 : 
     221                 :     pabyMutex[0] = 1;
     222                 :     pabyMutex[1] = 'r';
     223                 :     pabyMutex[2] = 'e';
     224                 :     pabyMutex[3] = 'd';
     225                 : 
     226                 :     return (void *) pabyMutex;
     227                 : #else
     228                 :     return (void *) 0xdeadbeef;
     229                 : #endif 
     230                 : }
     231                 : 
     232                 : /************************************************************************/
     233                 : /*                          CPLAcquireMutex()                           */
     234                 : /************************************************************************/
     235                 : 
     236                 : int CPLAcquireMutex( void *hMutex, double dfWaitInSeconds )
     237                 : 
     238                 : {
     239                 : #ifndef MUTEX_NONE
     240                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     241                 : 
     242                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     243                 :                && pabyMutex[3] == 'd' );
     244                 : 
     245                 :     pabyMutex[0] += 1;
     246                 : 
     247                 :     return TRUE;
     248                 : #else
     249                 :     return TRUE;
     250                 : #endif
     251                 : }
     252                 : 
     253                 : /************************************************************************/
     254                 : /*                          CPLReleaseMutex()                           */
     255                 : /************************************************************************/
     256                 : 
     257                 : void CPLReleaseMutex( void *hMutex )
     258                 : 
     259                 : {
     260                 : #ifndef MUTEX_NONE
     261                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     262                 : 
     263                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     264                 :                && pabyMutex[3] == 'd' );
     265                 : 
     266                 :     if( pabyMutex[0] < 1 )
     267                 :         CPLDebug( "CPLMultiProc", 
     268                 :                   "CPLReleaseMutex() called on mutex with %d as ref count!",
     269                 :                   pabyMutex[0] );
     270                 : 
     271                 :     pabyMutex[0] -= 1;
     272                 : #endif
     273                 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                          CPLDestroyMutex()                           */
     277                 : /************************************************************************/
     278                 : 
     279                 : void CPLDestroyMutex( void *hMutex )
     280                 : 
     281                 : {
     282                 : #ifndef MUTEX_NONE
     283                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     284                 : 
     285                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     286                 :                && pabyMutex[3] == 'd' );
     287                 : 
     288                 :     CPLFree( pabyMutex );
     289                 : #endif
     290                 : }
     291                 : 
     292                 : /************************************************************************/
     293                 : /*                            CPLLockFile()                             */
     294                 : /*                                                                      */
     295                 : /*      Lock a file.  This implementation has a terrible race           */
     296                 : /*      condition.  If we don't succeed in opening the lock file, we    */
     297                 : /*      assume we can create one and own the target file, but other     */
     298                 : /*      processes might easily try creating the target file at the      */
     299                 : /*      same time, overlapping us.  Death!  Mayhem!  The traditional    */
     300                 : /*      solution is to use open() with _O_CREAT|_O_EXCL but this        */
     301                 : /*      function and these arguments aren't trivially portable.         */
     302                 : /*      Also, this still leaves a race condition on NFS drivers         */
     303                 : /*      (apparently).                                                   */
     304                 : /************************************************************************/
     305                 : 
     306                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     307                 : 
     308                 : {
     309                 :     FILE      *fpLock;
     310                 :     char      *pszLockFilename;
     311                 :     
     312                 : /* -------------------------------------------------------------------- */
     313                 : /*      We use a lock file with a name derived from the file we want    */
     314                 : /*      to lock to represent the file being locked.  Note that for      */
     315                 : /*      the stub implementation the target file does not even need      */
     316                 : /*      to exist to be locked.                                          */
     317                 : /* -------------------------------------------------------------------- */
     318                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     319                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     320                 : 
     321                 :     fpLock = fopen( pszLockFilename, "r" );
     322                 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     323                 :     {
     324                 :         fclose( fpLock );
     325                 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
     326                 :         dfWaitInSeconds -= 0.5;
     327                 : 
     328                 :         fpLock = fopen( pszLockFilename, "r" );
     329                 :     }
     330                 :         
     331                 :     if( fpLock != NULL )
     332                 :     {
     333                 :         fclose( fpLock );
     334                 :         CPLFree( pszLockFilename );
     335                 :         return NULL;
     336                 :     }
     337                 : 
     338                 :     fpLock = fopen( pszLockFilename, "w" );
     339                 : 
     340                 :     if( fpLock == NULL )
     341                 :     {
     342                 :         CPLFree( pszLockFilename );
     343                 :         return NULL;
     344                 :     }
     345                 : 
     346                 :     fwrite( "held\n", 1, 5, fpLock );
     347                 :     fclose( fpLock );
     348                 : 
     349                 :     return pszLockFilename;
     350                 : }
     351                 : 
     352                 : /************************************************************************/
     353                 : /*                           CPLUnlockFile()                            */
     354                 : /************************************************************************/
     355                 : 
     356                 : void CPLUnlockFile( void *hLock )
     357                 : 
     358                 : {
     359                 :     char *pszLockFilename = (char *) hLock;
     360                 : 
     361                 :     if( hLock == NULL )
     362                 :         return;
     363                 :     
     364                 :     VSIUnlink( pszLockFilename );
     365                 :     
     366                 :     CPLFree( pszLockFilename );
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                             CPLGetPID()                              */
     371                 : /************************************************************************/
     372                 : 
     373                 : GIntBig CPLGetPID()
     374                 : 
     375                 : {
     376                 :     return 1;
     377                 : }
     378                 : 
     379                 : /************************************************************************/
     380                 : /*                          CPLCreateThread();                          */
     381                 : /************************************************************************/
     382                 : 
     383                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pArg )
     384                 : 
     385                 : {
     386                 :     CPLDebug( "CPLCreateThread", "Fails to dummy implementation" );
     387                 : 
     388                 :     return -1;
     389                 : }
     390                 : 
     391                 : /************************************************************************/
     392                 : /*                              CPLSleep()                              */
     393                 : /************************************************************************/
     394                 : 
     395                 : void CPLSleep( double dfWaitInSeconds )
     396                 : 
     397                 : {
     398                 :     time_t  ltime;
     399                 :     time_t  ttime;
     400                 : 
     401                 :     time( &ltime );
     402                 :     ttime = ltime + (int) (dfWaitInSeconds+0.5);
     403                 : 
     404                 :     for( ; ltime < ttime; time(&ltime) )
     405                 :     {
     406                 :         /* currently we just busy wait.  Perhaps we could at least block on 
     407                 :            io? */
     408                 :     }
     409                 : }
     410                 : 
     411                 : /************************************************************************/
     412                 : /*                           CPLGetTLSList()                            */
     413                 : /************************************************************************/
     414                 : 
     415                 : static void **papTLSList = NULL;
     416                 : 
     417                 : static void **CPLGetTLSList()
     418                 : 
     419                 : {
     420                 :     if( papTLSList == NULL )
     421                 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
     422                 : 
     423                 :     return papTLSList;
     424                 : }
     425                 : 
     426                 : /************************************************************************/
     427                 : /*                           CPLCleanupTLS()                            */
     428                 : /************************************************************************/
     429                 : 
     430                 : void CPLCleanupTLS()
     431                 : 
     432                 : {
     433                 :     CPLCleanupTLSList( papTLSList );
     434                 :     papTLSList = NULL;
     435                 : }
     436                 : 
     437                 : #endif /* def CPL_MULTIPROC_STUB */
     438                 : 
     439                 : #if defined(CPL_MULTIPROC_WIN32)
     440                 : 
     441                 : 
     442                 :   /************************************************************************/
     443                 :   /* ==================================================================== */
     444                 :   /*                        CPL_MULTIPROC_WIN32                           */
     445                 :   /*                                                                      */
     446                 :   /*    WIN32 Implementation of multiprocessing functions.                */
     447                 :   /* ==================================================================== */
     448                 :   /************************************************************************/
     449                 : 
     450                 : #include <windows.h>
     451                 : 
     452                 : /* windows.h header must be included above following lines. */
     453                 : #if defined(WIN32CE)
     454                 : #  include "cpl_win32ce_api.h"
     455                 : #  define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
     456                 : #endif
     457                 : 
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                        CPLGetThreadingModel()                        */
     461                 : /************************************************************************/
     462                 : 
     463                 : const char *CPLGetThreadingModel()
     464                 : 
     465                 : {
     466                 :     return "win32";
     467                 : }
     468                 : 
     469                 : /************************************************************************/
     470                 : /*                           CPLCreateMutex()                           */
     471                 : /************************************************************************/
     472                 : 
     473                 : void *CPLCreateMutex()
     474                 : 
     475                 : {
     476                 :     HANDLE hMutex;
     477                 : 
     478                 :     hMutex = CreateMutex( NULL, TRUE, NULL );
     479                 : 
     480                 :     return (void *) hMutex;
     481                 : }
     482                 : 
     483                 : /************************************************************************/
     484                 : /*                          CPLAcquireMutex()                           */
     485                 : /************************************************************************/
     486                 : 
     487                 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
     488                 : 
     489                 : {
     490                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     491                 :     DWORD  hr;
     492                 : 
     493                 :     hr = WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
     494                 :     
     495                 :     return hr != WAIT_TIMEOUT;
     496                 : }
     497                 : 
     498                 : /************************************************************************/
     499                 : /*                          CPLReleaseMutex()                           */
     500                 : /************************************************************************/
     501                 : 
     502                 : void CPLReleaseMutex( void *hMutexIn )
     503                 : 
     504                 : {
     505                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     506                 : 
     507                 :     ReleaseMutex( hMutex );
     508                 : }
     509                 : 
     510                 : /************************************************************************/
     511                 : /*                          CPLDestroyMutex()                           */
     512                 : /************************************************************************/
     513                 : 
     514                 : void CPLDestroyMutex( void *hMutexIn )
     515                 : 
     516                 : {
     517                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     518                 : 
     519                 :     CloseHandle( hMutex );
     520                 : }
     521                 : 
     522                 : /************************************************************************/
     523                 : /*                            CPLLockFile()                             */
     524                 : /************************************************************************/
     525                 : 
     526                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     527                 : 
     528                 : {
     529                 :     char      *pszLockFilename;
     530                 :     HANDLE    hLockFile;
     531                 :     
     532                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     533                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     534                 : 
     535                 :     hLockFile = 
     536                 :         CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW, 
     537                 :                     FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
     538                 : 
     539                 :     while( GetLastError() == ERROR_ALREADY_EXISTS
     540                 :            && dfWaitInSeconds > 0.0 )
     541                 :     {
     542                 :         CloseHandle( hLockFile );
     543                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     544                 :         dfWaitInSeconds -= 0.125;
     545                 : 
     546                 :         hLockFile = 
     547                 :             CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, 
     548                 :                         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, 
     549                 :                         NULL );
     550                 :     }
     551                 : 
     552                 :     CPLFree( pszLockFilename );
     553                 : 
     554                 :     if( hLockFile == INVALID_HANDLE_VALUE )
     555                 :         return NULL;
     556                 : 
     557                 :     if( GetLastError() == ERROR_ALREADY_EXISTS )
     558                 :     {
     559                 :         CloseHandle( hLockFile );
     560                 :         return NULL;
     561                 :     }
     562                 : 
     563                 :     return (void *) hLockFile;
     564                 : }
     565                 : 
     566                 : /************************************************************************/
     567                 : /*                           CPLUnlockFile()                            */
     568                 : /************************************************************************/
     569                 : 
     570                 : void CPLUnlockFile( void *hLock )
     571                 : 
     572                 : {
     573                 :     HANDLE    hLockFile = (HANDLE) hLock;
     574                 : 
     575                 :     CloseHandle( hLockFile );
     576                 : }
     577                 : 
     578                 : /************************************************************************/
     579                 : /*                             CPLGetPID()                              */
     580                 : /************************************************************************/
     581                 : 
     582                 : GIntBig CPLGetPID()
     583                 : 
     584                 : {
     585                 :     return (GIntBig) GetCurrentThreadId();
     586                 : }
     587                 : 
     588                 : /************************************************************************/
     589                 : /*                       CPLStdCallThreadJacket()                       */
     590                 : /************************************************************************/
     591                 : 
     592                 : typedef struct {
     593                 :     void *pAppData;
     594                 :     CPLThreadFunc pfnMain;
     595                 : } CPLStdCallThreadInfo;
     596                 : 
     597                 : static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
     598                 : 
     599                 : {
     600                 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
     601                 : 
     602                 :     psInfo->pfnMain( psInfo->pAppData );
     603                 : 
     604                 :     CPLFree( psInfo );
     605                 :     
     606                 :     CPLCleanupTLS();
     607                 : 
     608                 :     return 0;
     609                 : }
     610                 : 
     611                 : /************************************************************************/
     612                 : /*                          CPLCreateThread()                           */
     613                 : /*                                                                      */
     614                 : /*      The WIN32 CreateThread() call requires an entry point that      */
     615                 : /*      has __stdcall conventions, so we provide a jacket function      */
     616                 : /*      to supply that.                                                 */
     617                 : /************************************************************************/
     618                 : 
     619                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     620                 : 
     621                 : {
     622                 :     HANDLE hThread;
     623                 :     DWORD  nThreadId;
     624                 :     CPLStdCallThreadInfo *psInfo;
     625                 : 
     626                 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     627                 :     psInfo->pAppData = pThreadArg;
     628                 :     psInfo->pfnMain = pfnMain;
     629                 : 
     630                 :     hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
     631                 :                             0, &nThreadId );
     632                 : 
     633                 :     if( hThread == NULL )
     634                 :         return -1;
     635                 : 
     636                 :     CloseHandle( hThread );
     637                 : 
     638                 :     return nThreadId;
     639                 : }
     640                 : 
     641                 : /************************************************************************/
     642                 : /*                              CPLSleep()                              */
     643                 : /************************************************************************/
     644                 : 
     645                 : void CPLSleep( double dfWaitInSeconds )
     646                 : 
     647                 : {
     648                 :     Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
     649                 : }
     650                 : 
     651                 : static int           bTLSKeySetup = FALSE;
     652                 : static DWORD         nTLSKey;
     653                 : 
     654                 : /************************************************************************/
     655                 : /*                           CPLGetTLSList()                            */
     656                 : /************************************************************************/
     657                 : 
     658                 : static void **CPLGetTLSList()
     659                 : 
     660                 : {
     661                 :     void **papTLSList;
     662                 : 
     663                 :     if( !bTLSKeySetup )
     664                 :     {
     665                 :         nTLSKey = TlsAlloc();
     666                 :         if( nTLSKey == TLS_OUT_OF_INDEXES )
     667                 :         {
     668                 :             CPLError( CE_Fatal, CPLE_AppDefined, 
     669                 :                       "TlsAlloc() failed!" );
     670                 :         }
     671                 :         bTLSKeySetup = TRUE;
     672                 :     }
     673                 : 
     674                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
     675                 :     if( papTLSList == NULL )
     676                 :     {
     677                 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
     678                 :         if( TlsSetValue( nTLSKey, papTLSList ) == 0 )
     679                 :         {
     680                 :             CPLError( CE_Fatal, CPLE_AppDefined, 
     681                 :                       "TlsSetValue() failed!" );
     682                 :         }
     683                 :     }
     684                 : 
     685                 :     return papTLSList;
     686                 : }
     687                 : 
     688                 : /************************************************************************/
     689                 : /*                           CPLCleanupTLS()                            */
     690                 : /************************************************************************/
     691                 : 
     692                 : void CPLCleanupTLS()
     693                 : 
     694                 : {
     695                 :     void **papTLSList;
     696                 : 
     697                 :     if( !bTLSKeySetup )
     698                 :         return;
     699                 : 
     700                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
     701                 :     if( papTLSList == NULL )
     702                 :         return;
     703                 : 
     704                 :     TlsSetValue( nTLSKey, NULL );
     705                 : 
     706                 :     CPLCleanupTLSList( papTLSList );
     707                 : }
     708                 : 
     709                 : #endif /* def CPL_MULTIPROC_WIN32 */
     710                 : 
     711                 : #ifdef CPL_MULTIPROC_PTHREAD
     712                 : #include <pthread.h>
     713                 : #include <time.h>
     714                 : 
     715                 :   /************************************************************************/
     716                 :   /* ==================================================================== */
     717                 :   /*                        CPL_MULTIPROC_PTHREAD                         */
     718                 :   /*                                                                      */
     719                 :   /*    PTHREAD Implementation of multiprocessing functions.              */
     720                 :   /* ==================================================================== */
     721                 :   /************************************************************************/
     722                 : 
     723                 : /************************************************************************/
     724                 : /*                      CPLCreateOrAcquireMutex()                       */
     725                 : /************************************************************************/
     726                 : 
     727        12216627 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
     728                 : 
     729                 : {
     730        12216627 :     int bSuccess = FALSE;
     731                 :     static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
     732                 : 
     733        12216627 :     pthread_mutex_lock(&global_mutex);
     734        12216627 :     if( *phMutex == NULL )
     735                 :     {
     736            3016 :         *phMutex = CPLCreateMutex();
     737            3016 :         bSuccess = *phMutex != NULL;
     738            3016 :         pthread_mutex_unlock(&global_mutex);
     739                 :     }
     740                 :     else
     741                 :     {
     742        12213611 :         pthread_mutex_unlock(&global_mutex);
     743                 : 
     744        12213611 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
     745                 :     }
     746                 : 
     747        12216627 :     return bSuccess;
     748                 : }
     749                 : 
     750                 : /************************************************************************/
     751                 : /*                        CPLGetThreadingModel()                        */
     752                 : /************************************************************************/
     753                 : 
     754               0 : const char *CPLGetThreadingModel()
     755                 : 
     756                 : {
     757               0 :     return "pthread";
     758                 : }
     759                 : 
     760                 : /************************************************************************/
     761                 : /*                           CPLCreateMutex()                           */
     762                 : /************************************************************************/
     763                 : 
     764            3144 : void *CPLCreateMutex()
     765                 : 
     766                 : {
     767                 :     pthread_mutex_t *hMutex;
     768                 : 
     769            3144 :     hMutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
     770            3144 :     if (hMutex == NULL)
     771               0 :         return NULL;
     772                 : 
     773                 : #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
     774                 :     {
     775                 :         pthread_mutexattr_t  attr;
     776            3144 :         pthread_mutexattr_init( &attr );
     777            3144 :         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
     778            3144 :         pthread_mutex_init( hMutex, &attr );
     779                 :     }
     780                 : /* BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define. */
     781                 : /* But they have #define MUTEX_TYPE_COUNTING_FAST PTHREAD_MUTEX_RECURSIVE */
     782                 : #elif defined(MUTEX_TYPE_COUNTING_FAST)
     783                 :     {
     784                 :         pthread_mutexattr_t  attr;
     785                 :         pthread_mutexattr_init( &attr );
     786                 :         pthread_mutexattr_settype( &attr, MUTEX_TYPE_COUNTING_FAST );
     787                 :         pthread_mutex_init( hMutex, &attr );
     788                 :     }
     789                 : #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
     790                 :     pthread_mutex_t tmp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
     791                 :     *hMutex = tmp_mutex;
     792                 : #else
     793                 : #error "Recursive mutexes apparently unsupported, configure --without-threads" 
     794                 : #endif
     795                 : 
     796                 :     // mutexes are implicitly acquired when created.
     797            3144 :     CPLAcquireMutex( hMutex, 0.0 );
     798                 : 
     799            3144 :     return (void *) hMutex;
     800                 : }
     801                 : 
     802                 : /************************************************************************/
     803                 : /*                          CPLAcquireMutex()                           */
     804                 : /************************************************************************/
     805                 : 
     806        12225296 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
     807                 : 
     808                 : {
     809                 :     int err;
     810                 : 
     811                 :     /* we need to add timeout support */
     812        12225296 :     err =  pthread_mutex_lock( (pthread_mutex_t *) hMutexIn );
     813                 :     
     814        12225296 :     if( err != 0 )
     815                 :     {
     816               0 :         if( err == EDEADLK )
     817               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d/EDEADLK", err );
     818                 :         else
     819               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d", err );
     820                 : 
     821               0 :         return FALSE;
     822                 :     }
     823                 : 
     824        12225296 :     return TRUE;
     825                 : }
     826                 : 
     827                 : /************************************************************************/
     828                 : /*                          CPLReleaseMutex()                           */
     829                 : /************************************************************************/
     830                 : 
     831        12225172 : void CPLReleaseMutex( void *hMutexIn )
     832                 : 
     833                 : {
     834        12225172 :     pthread_mutex_unlock( (pthread_mutex_t *) hMutexIn );
     835        12225172 : }
     836                 : 
     837                 : /************************************************************************/
     838                 : /*                          CPLDestroyMutex()                           */
     839                 : /************************************************************************/
     840                 : 
     841             421 : void CPLDestroyMutex( void *hMutexIn )
     842                 : 
     843                 : {
     844             421 :     pthread_mutex_destroy( (pthread_mutex_t *) hMutexIn );
     845             421 :     free( hMutexIn );
     846             421 : }
     847                 : 
     848                 : /************************************************************************/
     849                 : /*                            CPLLockFile()                             */
     850                 : /*                                                                      */
     851                 : /*      This is really a stub implementation, see first                 */
     852                 : /*      CPLLockFile() for caveats.                                      */
     853                 : /************************************************************************/
     854                 : 
     855               0 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     856                 : 
     857                 : {
     858                 :     FILE      *fpLock;
     859                 :     char      *pszLockFilename;
     860                 :     
     861                 : /* -------------------------------------------------------------------- */
     862                 : /*      We use a lock file with a name derived from the file we want    */
     863                 : /*      to lock to represent the file being locked.  Note that for      */
     864                 : /*      the stub implementation the target file does not even need      */
     865                 : /*      to exist to be locked.                                          */
     866                 : /* -------------------------------------------------------------------- */
     867               0 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     868               0 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     869                 : 
     870               0 :     fpLock = fopen( pszLockFilename, "r" );
     871               0 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     872                 :     {
     873               0 :         fclose( fpLock );
     874               0 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
     875               0 :         dfWaitInSeconds -= 0.5;
     876                 : 
     877               0 :         fpLock = fopen( pszLockFilename, "r" );
     878                 :     }
     879                 :         
     880               0 :     if( fpLock != NULL )
     881                 :     {
     882               0 :         fclose( fpLock );
     883               0 :         CPLFree( pszLockFilename );
     884               0 :         return NULL;
     885                 :     }
     886                 : 
     887               0 :     fpLock = fopen( pszLockFilename, "w" );
     888                 : 
     889               0 :     if( fpLock == NULL )
     890                 :     {
     891               0 :         CPLFree( pszLockFilename );
     892               0 :         return NULL;
     893                 :     }
     894                 : 
     895               0 :     fwrite( "held\n", 1, 5, fpLock );
     896               0 :     fclose( fpLock );
     897                 : 
     898               0 :     return pszLockFilename;
     899                 : }
     900                 : 
     901                 : /************************************************************************/
     902                 : /*                           CPLUnlockFile()                            */
     903                 : /************************************************************************/
     904                 : 
     905               0 : void CPLUnlockFile( void *hLock )
     906                 : 
     907                 : {
     908               0 :     char *pszLockFilename = (char *) hLock;
     909                 : 
     910               0 :     if( hLock == NULL )
     911               0 :         return;
     912                 :     
     913               0 :     VSIUnlink( pszLockFilename );
     914                 :     
     915               0 :     CPLFree( pszLockFilename );
     916                 : }
     917                 : 
     918                 : /************************************************************************/
     919                 : /*                             CPLGetPID()                              */
     920                 : /************************************************************************/
     921                 : 
     922           23974 : GIntBig CPLGetPID()
     923                 : 
     924                 : {
     925           23974 :     return (GIntBig) pthread_self();
     926                 : }
     927                 : 
     928                 : /************************************************************************/
     929                 : /*                       CPLStdCallThreadJacket()                       */
     930                 : /************************************************************************/
     931                 : 
     932                 : typedef struct {
     933                 :     void *pAppData;
     934                 :     CPLThreadFunc pfnMain;
     935                 :     pthread_t hThread;
     936                 : } CPLStdCallThreadInfo;
     937                 : 
     938               1 : static void *CPLStdCallThreadJacket( void *pData )
     939                 : 
     940                 : {
     941               1 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
     942                 : 
     943               1 :     psInfo->pfnMain( psInfo->pAppData );
     944                 : 
     945               1 :     CPLFree( psInfo );
     946                 :     
     947               1 :     return NULL;
     948                 : }
     949                 : 
     950                 : /************************************************************************/
     951                 : /*                          CPLCreateThread()                           */
     952                 : /*                                                                      */
     953                 : /*      The WIN32 CreateThread() call requires an entry point that      */
     954                 : /*      has __stdcall conventions, so we provide a jacket function      */
     955                 : /*      to supply that.                                                 */
     956                 : /************************************************************************/
     957                 : 
     958               1 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     959                 : 
     960                 : {
     961                 : 
     962                 :     CPLStdCallThreadInfo *psInfo;
     963                 :     pthread_attr_t hThreadAttr;
     964                 : 
     965               1 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     966               1 :     psInfo->pAppData = pThreadArg;
     967               1 :     psInfo->pfnMain = pfnMain;
     968                 : 
     969               1 :     pthread_attr_init( &hThreadAttr );
     970               1 :     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
     971               1 :     if( pthread_create( &(psInfo->hThread), &hThreadAttr, 
     972                 :                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
     973                 :     {
     974               0 :         CPLFree( psInfo );
     975               0 :         return -1;
     976                 :     }
     977                 : 
     978               1 :     return 1; /* can we return the actual thread pid? */
     979                 : }
     980                 : 
     981                 : /************************************************************************/
     982                 : /*                              CPLSleep()                              */
     983                 : /************************************************************************/
     984                 : 
     985               1 : void CPLSleep( double dfWaitInSeconds )
     986                 : 
     987                 : {
     988                 :     struct timespec sRequest, sRemain;
     989                 : 
     990               1 :     sRequest.tv_sec = (int) floor(dfWaitInSeconds);
     991               1 :     sRequest.tv_nsec = (int) ((dfWaitInSeconds - sRequest.tv_sec)*1000000000);
     992               1 :     nanosleep( &sRequest, &sRemain );
     993               1 : }
     994                 : 
     995                 : static pthread_key_t  oTLSKey;
     996                 : static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
     997                 : 
     998                 : /************************************************************************/
     999                 : /*                             CPLMake_key()                            */
    1000                 : /************************************************************************/
    1001                 : 
    1002             448 : static void CPLMake_key()
    1003                 : 
    1004                 : {
    1005             448 :     if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
    1006                 :     {
    1007               0 :         CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
    1008                 :     }
    1009             448 : }
    1010                 : 
    1011                 : /************************************************************************/
    1012                 : /*                             CPLCleanupTLS()                          */
    1013                 : /************************************************************************/
    1014                 : 
    1015             736 : void CPLCleanupTLS()
    1016                 : 
    1017                 : {
    1018                 :     void **papTLSList;
    1019                 : 
    1020             736 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1021             736 :     if( papTLSList == NULL )
    1022              17 :         return;
    1023                 : 
    1024             719 :     pthread_setspecific( oTLSKey, NULL );
    1025                 : 
    1026             719 :     CPLCleanupTLSList( papTLSList );
    1027                 : }
    1028                 : 
    1029                 : /************************************************************************/
    1030                 : /*                           CPLGetTLSList()                            */
    1031                 : /************************************************************************/
    1032                 : 
    1033         5439928 : static void **CPLGetTLSList()
    1034                 : 
    1035                 : {
    1036                 :     void **papTLSList;
    1037                 : 
    1038         5439928 :     if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
    1039                 :     {
    1040                 :         CPLError( CE_Fatal, CPLE_AppDefined,
    1041               0 :             "pthread_once() failed!" );
    1042                 :     }
    1043                 : 
    1044         5439928 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1045         5439928 :     if( papTLSList == NULL )
    1046                 :     {
    1047             736 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
    1048             736 :         if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
    1049                 :         {
    1050                 :             CPLError( CE_Fatal, CPLE_AppDefined,
    1051               0 :                 "pthread_setspecific() failed!" );
    1052                 :         }
    1053                 :     }
    1054                 : 
    1055         5439928 :     return papTLSList;
    1056                 : }
    1057                 : 
    1058                 : #endif /* def CPL_MULTIPROC_PTHREAD */
    1059                 : 
    1060                 : /************************************************************************/
    1061                 : /*                             CPLGetTLS()                              */
    1062                 : /************************************************************************/
    1063                 : 
    1064         5436250 : void *CPLGetTLS( int nIndex )
    1065                 : 
    1066                 : {
    1067         5436250 :     void** papTLSList = CPLGetTLSList();
    1068                 : 
    1069         5436250 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1070                 : 
    1071         5436250 :     return papTLSList[nIndex];
    1072                 : }
    1073                 : 
    1074                 : /************************************************************************/
    1075                 : /*                             CPLSetTLS()                              */
    1076                 : /************************************************************************/
    1077                 : 
    1078            3678 : void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
    1079                 : 
    1080                 : {
    1081            3678 :     void **papTLSList = CPLGetTLSList();
    1082                 : 
    1083            3678 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1084                 : 
    1085            3678 :     papTLSList[nIndex] = pData;
    1086            3678 :     papTLSList[CTLS_MAX + nIndex] = (void *) (long) bFreeOnExit;
    1087            3678 : }

Generated by: LTP GCOV extension version 1.5