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 30 #if SQLITE_MAX_WORKER_THREADS>0 31 32 /********************************* Unix Pthreads ****************************/ 33 #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 34 35 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ 36 #include <pthread.h> 37 38 /* A running thread */ 39 struct SQLiteThread { 40 pthread_t tid; /* Thread ID */ 41 int done; /* Set to true when thread finishes */ 42 void *pOut; /* Result returned by the thread */ 43 void *(*xTask)(void*); /* The thread routine */ 44 void *pIn; /* Argument to the thread */ 45 }; 46 47 /* Create a new thread */ 48 int sqlite3ThreadCreate( 49 SQLiteThread **ppThread, /* OUT: Write the thread object here */ 50 void *(*xTask)(void*), /* Routine to run in a separate thread */ 51 void *pIn /* Argument passed into xTask() */ 52 ){ 53 SQLiteThread *p; 54 55 assert( ppThread!=0 ); 56 assert( xTask!=0 ); 57 *ppThread = 0; 58 p = sqlite3Malloc(sizeof(*p)); 59 if( p==0 ) return SQLITE_NOMEM; 60 memset(p, 0, sizeof(*p)); 61 p->xTask = xTask; 62 p->pIn = pIn; 63 if( sqlite3GlobalConfig.bCoreMutex==0 64 || pthread_create(&p->tid, 0, xTask, pIn)!=0 65 ){ 66 p->done = 1; 67 p->pOut = xTask(pIn); 68 } 69 *ppThread = p; 70 return SQLITE_OK; 71 } 72 73 /* Get the results of the thread */ 74 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ 75 int rc; 76 77 assert( ppOut!=0 ); 78 if( p==0 ) return SQLITE_NOMEM; 79 if( p->done ){ 80 *ppOut = p->pOut; 81 rc = SQLITE_OK; 82 }else{ 83 rc = pthread_join(p->tid, ppOut); 84 } 85 sqlite3_free(p); 86 return rc ? SQLITE_ERROR : SQLITE_OK; 87 } 88 89 #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ 90 /******************************** End Unix Pthreads *************************/ 91 92 93 /********************************* Win32 Threads ****************************/ 94 #if SQLITE_OS_WIN && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0 95 96 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ 97 #include <process.h> 98 99 /* A running thread */ 100 struct SQLiteThread { 101 uintptr_t tid; /* The thread handle */ 102 void *(*xTask)(void*); /* The routine to run as a thread */ 103 void *pIn; /* Argument to xTask */ 104 void *pResult; /* Result of xTask */ 105 }; 106 107 /* Thread procedure Win32 compatibility shim */ 108 static void sqlite3ThreadProc( 109 void *pArg /* IN: Pointer to the SQLiteThread structure */ 110 ){ 111 SQLiteThread *p = (SQLiteThread *)pArg; 112 113 assert( p!=0 ); 114 assert( p->xTask!=0 ); 115 p->pResult = p->xTask(p->pIn); 116 _endthread(); 117 } 118 119 /* Create a new thread */ 120 int sqlite3ThreadCreate( 121 SQLiteThread **ppThread, /* OUT: Write the thread object here */ 122 void *(*xTask)(void*), /* Routine to run in a separate thread */ 123 void *pIn /* Argument passed into xTask() */ 124 ){ 125 SQLiteThread *p; 126 127 assert( ppThread!=0 ); 128 assert( xTask!=0 ); 129 *ppThread = 0; 130 p = sqlite3Malloc(sizeof(*p)); 131 if( p==0 ) return SQLITE_NOMEM; 132 if( sqlite3GlobalConfig.bCoreMutex==0 ){ 133 memset(p, 0, sizeof(*p)); 134 }else{ 135 p->xTask = xTask; 136 p->pIn = pIn; 137 p->tid = _beginthread(sqlite3ThreadProc, 0, p); 138 if( p->tid==(uintptr_t)-1 ){ 139 memset(p, 0, sizeof(*p)); 140 } 141 } 142 if( p->xTask==0 ){ 143 p->pResult = xTask(pIn); 144 } 145 *ppThread = p; 146 return SQLITE_OK; 147 } 148 149 /* Get the results of the thread */ 150 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ 151 DWORD rc; 152 153 assert( ppOut!=0 ); 154 if( p==0 ) return SQLITE_NOMEM; 155 if( p->xTask==0 ){ 156 rc = WAIT_OBJECT_0; 157 }else{ 158 rc = sqlite3Win32Wait((HANDLE)p->tid); 159 assert( rc!=WAIT_IO_COMPLETION ); 160 } 161 if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; 162 sqlite3_free(p); 163 return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; 164 } 165 166 #endif /* SQLITE_OS_WIN && !SQLITE_OS_WINRT */ 167 /******************************** End Win32 Threads *************************/ 168 169 170 /********************************* Single-Threaded **************************/ 171 #ifndef SQLITE_THREADS_IMPLEMENTED 172 /* 173 ** This implementation does not actually create a new thread. It does the 174 ** work of the thread in the main thread, when either the thread is created 175 ** or when it is joined 176 */ 177 178 /* A running thread */ 179 struct SQLiteThread { 180 void *(*xTask)(void*); /* The routine to run as a thread */ 181 void *pIn; /* Argument to xTask */ 182 void *pResult; /* Result of xTask */ 183 }; 184 185 /* Create a new thread */ 186 int sqlite3ThreadCreate( 187 SQLiteThread **ppThread, /* OUT: Write the thread object here */ 188 void *(*xTask)(void*), /* Routine to run in a separate thread */ 189 void *pIn /* Argument passed into xTask() */ 190 ){ 191 SQLiteThread *p; 192 193 assert( ppThread!=0 ); 194 assert( xTask!=0 ); 195 *ppThread = 0; 196 p = sqlite3Malloc(sizeof(*p)); 197 if( p==0 ) return SQLITE_NOMEM; 198 if( (SQLITE_PTR_TO_INT(p)/17)&1 ){ 199 p->xTask = xTask; 200 p->pIn = pIn; 201 }else{ 202 p->xTask = 0; 203 p->pResult = xTask(pIn); 204 } 205 *ppThread = p; 206 return SQLITE_OK; 207 } 208 209 /* Get the results of the thread */ 210 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ 211 assert( ppOut!=0 ); 212 if( p==0 ) return SQLITE_NOMEM; 213 if( p->xTask ){ 214 *ppOut = p->xTask(p->pIn); 215 }else{ 216 *ppOut = p->pResult; 217 } 218 sqlite3_free(p); 219 return SQLITE_OK; 220 } 221 222 #endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ 223 /****************************** End Single-Threaded *************************/ 224 #endif /* SQLITE_MAX_WORKER_THREADS>0 */ 225