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; 67 memset(p, 0, sizeof(*p)); 68 p->xTask = xTask; 69 p->pIn = pIn; 70 if( sqlite3FaultSim(200) ){ 71 rc = 1; 72 }else{ 73 rc = pthread_create(&p->tid, 0, xTask, pIn); 74 } 75 if( rc ){ 76 p->done = 1; 77 p->pOut = xTask(pIn); 78 } 79 *ppThread = p; 80 return SQLITE_OK; 81 } 82 83 /* Get the results of the thread */ 84 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ 85 int rc; 86 87 assert( ppOut!=0 ); 88 if( NEVER(p==0) ) return SQLITE_NOMEM; 89 if( p->done ){ 90 *ppOut = p->pOut; 91 rc = SQLITE_OK; 92 }else{ 93 rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK; 94 } 95 sqlite3_free(p); 96 return rc; 97 } 98 99 #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ 100 /******************************** End Unix Pthreads *************************/ 101 102 103 /********************************* Win32 Threads ****************************/ 104 #if SQLITE_OS_WIN_THREADS 105 106 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ 107 #include <process.h> 108 109 /* A running thread */ 110 struct SQLiteThread { 111 void *tid; /* The thread handle */ 112 unsigned id; /* The thread identifier */ 113 void *(*xTask)(void*); /* The routine to run as a thread */ 114 void *pIn; /* Argument to xTask */ 115 void *pResult; /* Result of xTask */ 116 }; 117 118 /* Thread procedure Win32 compatibility shim */ 119 static unsigned __stdcall sqlite3ThreadProc( 120 void *pArg /* IN: Pointer to the SQLiteThread structure */ 121 ){ 122 SQLiteThread *p = (SQLiteThread *)pArg; 123 124 assert( p!=0 ); 125 #if 0 126 /* 127 ** This assert appears to trigger spuriously on certain 128 ** versions of Windows, possibly due to _beginthreadex() 129 ** and/or CreateThread() not fully setting their thread 130 ** ID parameter before starting the thread. 131 */ 132 assert( p->id==GetCurrentThreadId() ); 133 #endif 134 assert( p->xTask!=0 ); 135 p->pResult = p->xTask(p->pIn); 136 137 _endthreadex(0); 138 return 0; /* NOT REACHED */ 139 } 140 141 /* Create a new thread */ 142 int sqlite3ThreadCreate( 143 SQLiteThread **ppThread, /* OUT: Write the thread object here */ 144 void *(*xTask)(void*), /* Routine to run in a separate thread */ 145 void *pIn /* Argument passed into xTask() */ 146 ){ 147 SQLiteThread *p; 148 149 assert( ppThread!=0 ); 150 assert( xTask!=0 ); 151 *ppThread = 0; 152 p = sqlite3Malloc(sizeof(*p)); 153 if( p==0 ) return SQLITE_NOMEM; 154 if( sqlite3GlobalConfig.bCoreMutex==0 ){ 155 memset(p, 0, sizeof(*p)); 156 }else{ 157 p->xTask = xTask; 158 p->pIn = pIn; 159 p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id); 160 if( p->tid==0 ){ 161 memset(p, 0, sizeof(*p)); 162 } 163 } 164 if( p->xTask==0 ){ 165 p->id = GetCurrentThreadId(); 166 p->pResult = xTask(pIn); 167 } 168 *ppThread = p; 169 return SQLITE_OK; 170 } 171 172 DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */ 173 174 /* Get the results of the thread */ 175 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ 176 DWORD rc; 177 BOOL bRc; 178 179 assert( ppOut!=0 ); 180 if( NEVER(p==0) ) return SQLITE_NOMEM; 181 if( p->xTask==0 ){ 182 assert( p->id==GetCurrentThreadId() ); 183 rc = WAIT_OBJECT_0; 184 assert( p->tid==0 ); 185 }else{ 186 assert( p->id!=0 && p->id!=GetCurrentThreadId() ); 187 rc = sqlite3Win32Wait((HANDLE)p->tid); 188 assert( rc!=WAIT_IO_COMPLETION ); 189 bRc = CloseHandle((HANDLE)p->tid); 190 assert( bRc ); 191 } 192 if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; 193 sqlite3_free(p); 194 return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; 195 } 196 197 #endif /* SQLITE_OS_WIN_THREADS */ 198 /******************************** End Win32 Threads *************************/ 199 200 201 /********************************* Single-Threaded **************************/ 202 #ifndef SQLITE_THREADS_IMPLEMENTED 203 /* 204 ** This implementation does not actually create a new thread. It does the 205 ** work of the thread in the main thread, when either the thread is created 206 ** or when it is joined 207 */ 208 209 /* A running thread */ 210 struct SQLiteThread { 211 void *(*xTask)(void*); /* The routine to run as a thread */ 212 void *pIn; /* Argument to xTask */ 213 void *pResult; /* Result of xTask */ 214 }; 215 216 /* Create a new thread */ 217 int sqlite3ThreadCreate( 218 SQLiteThread **ppThread, /* OUT: Write the thread object here */ 219 void *(*xTask)(void*), /* Routine to run in a separate thread */ 220 void *pIn /* Argument passed into xTask() */ 221 ){ 222 SQLiteThread *p; 223 224 assert( ppThread!=0 ); 225 assert( xTask!=0 ); 226 *ppThread = 0; 227 p = sqlite3Malloc(sizeof(*p)); 228 if( p==0 ) return SQLITE_NOMEM; 229 if( (SQLITE_PTR_TO_INT(p)/17)&1 ){ 230 p->xTask = xTask; 231 p->pIn = pIn; 232 }else{ 233 p->xTask = 0; 234 p->pResult = xTask(pIn); 235 } 236 *ppThread = p; 237 return SQLITE_OK; 238 } 239 240 /* Get the results of the thread */ 241 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ 242 243 assert( ppOut!=0 ); 244 if( NEVER(p==0) ) return SQLITE_NOMEM; 245 if( p->xTask ){ 246 *ppOut = p->xTask(p->pIn); 247 }else{ 248 *ppOut = p->pResult; 249 } 250 sqlite3_free(p); 251 252 #if defined(SQLITE_TEST) 253 { 254 void *pTstAlloc = sqlite3Malloc(10); 255 if (!pTstAlloc) return SQLITE_NOMEM; 256 sqlite3_free(pTstAlloc); 257 } 258 #endif 259 260 return SQLITE_OK; 261 } 262 263 #endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ 264 /****************************** End Single-Threaded *************************/ 265 #endif /* SQLITE_MAX_WORKER_THREADS>0 */ 266