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