| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2012 July 21 | 2 ** 2012 July 21 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| 11 ****************************************************************************** | 11 ****************************************************************************** |
| 12 ** | 12 ** |
| 13 ** This file presents a simple cross-platform threading interface for | 13 ** This file presents a simple cross-platform threading interface for |
| 14 ** use internally by SQLite. | 14 ** use internally by SQLite. |
| 15 ** | 15 ** |
| 16 ** A "thread" can be created using sqlite3ThreadCreate(). This thread | 16 ** A "thread" can be created using sqlite3ThreadCreate(). This thread |
| 17 ** runs independently of its creator until it is joined using | 17 ** runs independently of its creator until it is joined using |
| 18 ** sqlite3ThreadJoin(), at which point it terminates. | 18 ** sqlite3ThreadJoin(), at which point it terminates. |
| 19 ** | 19 ** |
| 20 ** Threads do not have to be real. It could be that the work of the | 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() | 21 ** "thread" is done by the main thread at either the sqlite3ThreadCreate() |
| 22 ** or sqlite3ThreadJoin() call. This is, in fact, what happens in | 22 ** or sqlite3ThreadJoin() call. This is, in fact, what happens in |
| 23 ** single threaded systems. Nothing in SQLite requires multiple threads. | 23 ** single threaded systems. Nothing in SQLite requires multiple threads. |
| 24 ** This interface exists so that applications that want to take advantage | 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 | 25 ** of multiple cores can do so, while also allowing applications to stay |
| 26 ** single-threaded if desired. | 26 ** single-threaded if desired. |
| 27 */ | 27 */ |
| 28 #include "sqliteInt.h" | 28 #include "sqliteInt.h" |
| 29 #if SQLITE_OS_WIN |
| 30 # include "os_win.h" |
| 31 #endif |
| 29 | 32 |
| 30 #if SQLITE_MAX_WORKER_THREADS>0 | 33 #if SQLITE_MAX_WORKER_THREADS>0 |
| 31 | 34 |
| 32 /********************************* Unix Pthreads ****************************/ | 35 /********************************* Unix Pthreads ****************************/ |
| 33 #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 | 36 #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 |
| 34 | 37 |
| 35 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ | 38 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ |
| 36 #include <pthread.h> | 39 #include <pthread.h> |
| 37 | 40 |
| 38 /* A running thread */ | 41 /* A running thread */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 57 assert( xTask!=0 ); | 60 assert( xTask!=0 ); |
| 58 /* This routine is never used in single-threaded mode */ | 61 /* This routine is never used in single-threaded mode */ |
| 59 assert( sqlite3GlobalConfig.bCoreMutex!=0 ); | 62 assert( sqlite3GlobalConfig.bCoreMutex!=0 ); |
| 60 | 63 |
| 61 *ppThread = 0; | 64 *ppThread = 0; |
| 62 p = sqlite3Malloc(sizeof(*p)); | 65 p = sqlite3Malloc(sizeof(*p)); |
| 63 if( p==0 ) return SQLITE_NOMEM; | 66 if( p==0 ) return SQLITE_NOMEM; |
| 64 memset(p, 0, sizeof(*p)); | 67 memset(p, 0, sizeof(*p)); |
| 65 p->xTask = xTask; | 68 p->xTask = xTask; |
| 66 p->pIn = pIn; | 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. */ |
| 67 if( sqlite3FaultSim(200) ){ | 74 if( sqlite3FaultSim(200) ){ |
| 68 rc = 1; | 75 rc = 1; |
| 69 }else{ | 76 }else{ |
| 70 rc = pthread_create(&p->tid, 0, xTask, pIn); | 77 rc = pthread_create(&p->tid, 0, xTask, pIn); |
| 71 } | 78 } |
| 72 if( rc ){ | 79 if( rc ){ |
| 73 p->done = 1; | 80 p->done = 1; |
| 74 p->pOut = xTask(pIn); | 81 p->pOut = xTask(pIn); |
| 75 } | 82 } |
| 76 *ppThread = p; | 83 *ppThread = p; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 91 } | 98 } |
| 92 sqlite3_free(p); | 99 sqlite3_free(p); |
| 93 return rc; | 100 return rc; |
| 94 } | 101 } |
| 95 | 102 |
| 96 #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ | 103 #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ |
| 97 /******************************** End Unix Pthreads *************************/ | 104 /******************************** End Unix Pthreads *************************/ |
| 98 | 105 |
| 99 | 106 |
| 100 /********************************* Win32 Threads ****************************/ | 107 /********************************* Win32 Threads ****************************/ |
| 101 #if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0 | 108 #if SQLITE_OS_WIN_THREADS |
| 102 | 109 |
| 103 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ | 110 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ |
| 104 #include <process.h> | 111 #include <process.h> |
| 105 | 112 |
| 106 /* A running thread */ | 113 /* A running thread */ |
| 107 struct SQLiteThread { | 114 struct SQLiteThread { |
| 108 void *tid; /* The thread handle */ | 115 void *tid; /* The thread handle */ |
| 109 unsigned id; /* The thread identifier */ | 116 unsigned id; /* The thread identifier */ |
| 110 void *(*xTask)(void*); /* The routine to run as a thread */ | 117 void *(*xTask)(void*); /* The routine to run as a thread */ |
| 111 void *pIn; /* Argument to xTask */ | 118 void *pIn; /* Argument to xTask */ |
| (...skipping 29 matching lines...) Expand all Loading... |
| 141 void *(*xTask)(void*), /* Routine to run in a separate thread */ | 148 void *(*xTask)(void*), /* Routine to run in a separate thread */ |
| 142 void *pIn /* Argument passed into xTask() */ | 149 void *pIn /* Argument passed into xTask() */ |
| 143 ){ | 150 ){ |
| 144 SQLiteThread *p; | 151 SQLiteThread *p; |
| 145 | 152 |
| 146 assert( ppThread!=0 ); | 153 assert( ppThread!=0 ); |
| 147 assert( xTask!=0 ); | 154 assert( xTask!=0 ); |
| 148 *ppThread = 0; | 155 *ppThread = 0; |
| 149 p = sqlite3Malloc(sizeof(*p)); | 156 p = sqlite3Malloc(sizeof(*p)); |
| 150 if( p==0 ) return SQLITE_NOMEM; | 157 if( p==0 ) return SQLITE_NOMEM; |
| 151 if( sqlite3GlobalConfig.bCoreMutex==0 ){ | 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) ){ |
| 152 memset(p, 0, sizeof(*p)); | 164 memset(p, 0, sizeof(*p)); |
| 153 }else{ | 165 }else{ |
| 154 p->xTask = xTask; | 166 p->xTask = xTask; |
| 155 p->pIn = pIn; | 167 p->pIn = pIn; |
| 156 p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id); | 168 p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id); |
| 157 if( p->tid==0 ){ | 169 if( p->tid==0 ){ |
| 158 memset(p, 0, sizeof(*p)); | 170 memset(p, 0, sizeof(*p)); |
| 159 } | 171 } |
| 160 } | 172 } |
| 161 if( p->xTask==0 ){ | 173 if( p->xTask==0 ){ |
| 162 p->id = GetCurrentThreadId(); | 174 p->id = GetCurrentThreadId(); |
| 163 p->pResult = xTask(pIn); | 175 p->pResult = xTask(pIn); |
| 164 } | 176 } |
| 165 *ppThread = p; | 177 *ppThread = p; |
| 166 return SQLITE_OK; | 178 return SQLITE_OK; |
| 167 } | 179 } |
| 168 | 180 |
| 169 DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */ | 181 DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */ |
| 170 | 182 |
| 171 /* Get the results of the thread */ | 183 /* Get the results of the thread */ |
| 172 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ | 184 int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ |
| 173 DWORD rc; | 185 DWORD rc; |
| 174 BOOL bRc; | 186 BOOL bRc; |
| 175 | 187 |
| 176 assert( ppOut!=0 ); | 188 assert( ppOut!=0 ); |
| 177 if( NEVER(p==0) ) return SQLITE_NOMEM; | 189 if( NEVER(p==0) ) return SQLITE_NOMEM; |
| 178 if( p->xTask==0 ){ | 190 if( p->xTask==0 ){ |
| 179 assert( p->id==GetCurrentThreadId() ); | 191 /* assert( p->id==GetCurrentThreadId() ); */ |
| 180 rc = WAIT_OBJECT_0; | 192 rc = WAIT_OBJECT_0; |
| 181 assert( p->tid==0 ); | 193 assert( p->tid==0 ); |
| 182 }else{ | 194 }else{ |
| 183 assert( p->id!=0 && p->id!=GetCurrentThreadId() ); | 195 assert( p->id!=0 && p->id!=GetCurrentThreadId() ); |
| 184 rc = sqlite3Win32Wait((HANDLE)p->tid); | 196 rc = sqlite3Win32Wait((HANDLE)p->tid); |
| 185 assert( rc!=WAIT_IO_COMPLETION ); | 197 assert( rc!=WAIT_IO_COMPLETION ); |
| 186 bRc = CloseHandle((HANDLE)p->tid); | 198 bRc = CloseHandle((HANDLE)p->tid); |
| 187 assert( bRc ); | 199 assert( bRc ); |
| 188 } | 200 } |
| 189 if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; | 201 if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; |
| 190 sqlite3_free(p); | 202 sqlite3_free(p); |
| 191 return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; | 203 return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; |
| 192 } | 204 } |
| 193 | 205 |
| 194 #endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */ | 206 #endif /* SQLITE_OS_WIN_THREADS */ |
| 195 /******************************** End Win32 Threads *************************/ | 207 /******************************** End Win32 Threads *************************/ |
| 196 | 208 |
| 197 | 209 |
| 198 /********************************* Single-Threaded **************************/ | 210 /********************************* Single-Threaded **************************/ |
| 199 #ifndef SQLITE_THREADS_IMPLEMENTED | 211 #ifndef SQLITE_THREADS_IMPLEMENTED |
| 200 /* | 212 /* |
| 201 ** This implementation does not actually create a new thread. It does the | 213 ** This implementation does not actually create a new thread. It does the |
| 202 ** work of the thread in the main thread, when either the thread is created | 214 ** work of the thread in the main thread, when either the thread is created |
| 203 ** or when it is joined | 215 ** or when it is joined |
| 204 */ | 216 */ |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 sqlite3_free(pTstAlloc); | 265 sqlite3_free(pTstAlloc); |
| 254 } | 266 } |
| 255 #endif | 267 #endif |
| 256 | 268 |
| 257 return SQLITE_OK; | 269 return SQLITE_OK; |
| 258 } | 270 } |
| 259 | 271 |
| 260 #endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ | 272 #endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ |
| 261 /****************************** End Single-Threaded *************************/ | 273 /****************************** End Single-Threaded *************************/ |
| 262 #endif /* SQLITE_MAX_WORKER_THREADS>0 */ | 274 #endif /* SQLITE_MAX_WORKER_THREADS>0 */ |
| OLD | NEW |