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 |