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