modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/threads.c (about)

     1  /*
     2  ** 2012 July 21
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  ******************************************************************************
    12  **
    13  ** This file presents a simple cross-platform threading interface for
    14  ** use internally by SQLite.
    15  **
    16  ** A "thread" can be created using sqlite3ThreadCreate().  This thread
    17  ** runs independently of its creator until it is joined using
    18  ** sqlite3ThreadJoin(), at which point it terminates.
    19  **
    20  ** Threads do not have to be real.  It could be that the work of the
    21  ** "thread" is done by the main thread at either the sqlite3ThreadCreate()
    22  ** or sqlite3ThreadJoin() call.  This is, in fact, what happens in
    23  ** single threaded systems.  Nothing in SQLite requires multiple threads.
    24  ** This interface exists so that applications that want to take advantage
    25  ** of multiple cores can do so, while also allowing applications to stay
    26  ** single-threaded if desired.
    27  */
    28  #include "sqliteInt.h"
    29  #if SQLITE_OS_WIN
    30  #  include "os_win.h"
    31  #endif
    32  
    33  #if SQLITE_MAX_WORKER_THREADS>0
    34  
    35  /********************************* Unix Pthreads ****************************/
    36  #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
    37  
    38  #define SQLITE_THREADS_IMPLEMENTED 1  /* Prevent the single-thread code below */
    39  #include <pthread.h>
    40  
    41  /* A running thread */
    42  struct SQLiteThread {
    43    pthread_t tid;                 /* Thread ID */
    44    int done;                      /* Set to true when thread finishes */
    45    void *pOut;                    /* Result returned by the thread */
    46    void *(*xTask)(void*);         /* The thread routine */
    47    void *pIn;                     /* Argument to the thread */
    48  };
    49  
    50  /* Create a new thread */
    51  int sqlite3ThreadCreate(
    52    SQLiteThread **ppThread,  /* OUT: Write the thread object here */
    53    void *(*xTask)(void*),    /* Routine to run in a separate thread */
    54    void *pIn                 /* Argument passed into xTask() */
    55  ){
    56    SQLiteThread *p;
    57    int rc;
    58  
    59    assert( ppThread!=0 );
    60    assert( xTask!=0 );
    61    /* This routine is never used in single-threaded mode */
    62    assert( sqlite3GlobalConfig.bCoreMutex!=0 );
    63  
    64    *ppThread = 0;
    65    p = sqlite3Malloc(sizeof(*p));
    66    if( p==0 ) return SQLITE_NOMEM_BKPT;
    67    memset(p, 0, sizeof(*p));
    68    p->xTask = xTask;
    69    p->pIn = pIn;
    70    /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a 
    71    ** function that returns SQLITE_ERROR when passed the argument 200, that
    72    ** forces worker threads to run sequentially and deterministically 
    73    ** for testing purposes. */
    74    if( sqlite3FaultSim(200) ){
    75      rc = 1;
    76    }else{    
    77      rc = pthread_create(&p->tid, 0, xTask, pIn);
    78    }
    79    if( rc ){
    80      p->done = 1;
    81      p->pOut = xTask(pIn);
    82    }
    83    *ppThread = p;
    84    return SQLITE_OK;
    85  }
    86  
    87  /* Get the results of the thread */
    88  int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
    89    int rc;
    90  
    91    assert( ppOut!=0 );
    92    if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
    93    if( p->done ){
    94      *ppOut = p->pOut;
    95      rc = SQLITE_OK;
    96    }else{
    97      rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK;
    98    }
    99    sqlite3_free(p);
   100    return rc;
   101  }
   102  
   103  #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
   104  /******************************** End Unix Pthreads *************************/
   105  
   106  
   107  /********************************* Win32 Threads ****************************/
   108  #if SQLITE_OS_WIN_THREADS
   109  
   110  #define SQLITE_THREADS_IMPLEMENTED 1  /* Prevent the single-thread code below */
   111  #include <process.h>
   112  
   113  /* A running thread */
   114  struct SQLiteThread {
   115    void *tid;               /* The thread handle */
   116    unsigned id;             /* The thread identifier */
   117    void *(*xTask)(void*);   /* The routine to run as a thread */
   118    void *pIn;               /* Argument to xTask */
   119    void *pResult;           /* Result of xTask */
   120  };
   121  
   122  /* Thread procedure Win32 compatibility shim */
   123  static unsigned __stdcall sqlite3ThreadProc(
   124    void *pArg  /* IN: Pointer to the SQLiteThread structure */
   125  ){
   126    SQLiteThread *p = (SQLiteThread *)pArg;
   127  
   128    assert( p!=0 );
   129  #if 0
   130    /*
   131    ** This assert appears to trigger spuriously on certain
   132    ** versions of Windows, possibly due to _beginthreadex()
   133    ** and/or CreateThread() not fully setting their thread
   134    ** ID parameter before starting the thread.
   135    */
   136    assert( p->id==GetCurrentThreadId() );
   137  #endif
   138    assert( p->xTask!=0 );
   139    p->pResult = p->xTask(p->pIn);
   140  
   141    _endthreadex(0);
   142    return 0; /* NOT REACHED */
   143  }
   144  
   145  /* Create a new thread */
   146  int sqlite3ThreadCreate(
   147    SQLiteThread **ppThread,  /* OUT: Write the thread object here */
   148    void *(*xTask)(void*),    /* Routine to run in a separate thread */
   149    void *pIn                 /* Argument passed into xTask() */
   150  ){
   151    SQLiteThread *p;
   152  
   153    assert( ppThread!=0 );
   154    assert( xTask!=0 );
   155    *ppThread = 0;
   156    p = sqlite3Malloc(sizeof(*p));
   157    if( p==0 ) return SQLITE_NOMEM_BKPT;
   158    /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a 
   159    ** function that returns SQLITE_ERROR when passed the argument 200, that
   160    ** forces worker threads to run sequentially and deterministically 
   161    ** (via the sqlite3FaultSim() term of the conditional) for testing
   162    ** purposes. */
   163    if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){
   164      memset(p, 0, sizeof(*p));
   165    }else{
   166      p->xTask = xTask;
   167      p->pIn = pIn;
   168      p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
   169      if( p->tid==0 ){
   170        memset(p, 0, sizeof(*p));
   171      }
   172    }
   173    if( p->xTask==0 ){
   174      p->id = GetCurrentThreadId();
   175      p->pResult = xTask(pIn);
   176    }
   177    *ppThread = p;
   178    return SQLITE_OK;
   179  }
   180  
   181  DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */
   182  
   183  /* Get the results of the thread */
   184  int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
   185    DWORD rc;
   186    BOOL bRc;
   187  
   188    assert( ppOut!=0 );
   189    if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
   190    if( p->xTask==0 ){
   191      /* assert( p->id==GetCurrentThreadId() ); */
   192      rc = WAIT_OBJECT_0;
   193      assert( p->tid==0 );
   194    }else{
   195      assert( p->id!=0 && p->id!=GetCurrentThreadId() );
   196      rc = sqlite3Win32Wait((HANDLE)p->tid);
   197      assert( rc!=WAIT_IO_COMPLETION );
   198      bRc = CloseHandle((HANDLE)p->tid);
   199      assert( bRc );
   200    }
   201    if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
   202    sqlite3_free(p);
   203    return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
   204  }
   205  
   206  #endif /* SQLITE_OS_WIN_THREADS */
   207  /******************************** End Win32 Threads *************************/
   208  
   209  
   210  /********************************* Single-Threaded **************************/
   211  #ifndef SQLITE_THREADS_IMPLEMENTED
   212  /*
   213  ** This implementation does not actually create a new thread.  It does the
   214  ** work of the thread in the main thread, when either the thread is created
   215  ** or when it is joined
   216  */
   217  
   218  /* A running thread */
   219  struct SQLiteThread {
   220    void *(*xTask)(void*);   /* The routine to run as a thread */
   221    void *pIn;               /* Argument to xTask */
   222    void *pResult;           /* Result of xTask */
   223  };
   224  
   225  /* Create a new thread */
   226  int sqlite3ThreadCreate(
   227    SQLiteThread **ppThread,  /* OUT: Write the thread object here */
   228    void *(*xTask)(void*),    /* Routine to run in a separate thread */
   229    void *pIn                 /* Argument passed into xTask() */
   230  ){
   231    SQLiteThread *p;
   232  
   233    assert( ppThread!=0 );
   234    assert( xTask!=0 );
   235    *ppThread = 0;
   236    p = sqlite3Malloc(sizeof(*p));
   237    if( p==0 ) return SQLITE_NOMEM_BKPT;
   238    if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
   239      p->xTask = xTask;
   240      p->pIn = pIn;
   241    }else{
   242      p->xTask = 0;
   243      p->pResult = xTask(pIn);
   244    }
   245    *ppThread = p;
   246    return SQLITE_OK;
   247  }
   248  
   249  /* Get the results of the thread */
   250  int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
   251  
   252    assert( ppOut!=0 );
   253    if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
   254    if( p->xTask ){
   255      *ppOut = p->xTask(p->pIn);
   256    }else{
   257      *ppOut = p->pResult;
   258    }
   259    sqlite3_free(p);
   260  
   261  #if defined(SQLITE_TEST)
   262    {
   263      void *pTstAlloc = sqlite3Malloc(10);
   264      if (!pTstAlloc) return SQLITE_NOMEM_BKPT;
   265      sqlite3_free(pTstAlloc);
   266    }
   267  #endif
   268  
   269    return SQLITE_OK;
   270  }
   271  
   272  #endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
   273  /****************************** End Single-Threaded *************************/
   274  #endif /* SQLITE_MAX_WORKER_THREADS>0 */