Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: f128d69fc2355512e1014ad63c90f9e198123319 [file] [log] [blame]
drhf51446a2012-07-21 19:40:421/*
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"
mistachkinb13160f2015-01-07 18:11:2929#if SQLITE_OS_WIN
30# include "os_win.h"
31#endif
drhf51446a2012-07-21 19:40:4232
danb3f56fd2014-03-31 19:57:3433#if SQLITE_MAX_WORKER_THREADS>0
34
drhf51446a2012-07-21 19:40:4235/********************************* Unix Pthreads ****************************/
drh3c863632014-03-25 14:12:1636#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
drhf51446a2012-07-21 19:40:4237
38#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
39#include <pthread.h>
40
41/* A running thread */
42struct SQLiteThread {
drh3de4df22014-04-24 12:28:2843 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 */
drhf51446a2012-07-21 19:40:4248};
49
50/* Create a new thread */
51int 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;
drhb92284d2014-07-29 18:46:3057 int rc;
drhf51446a2012-07-21 19:40:4258
mistachkinda0e4712012-07-21 22:49:0859 assert( ppThread!=0 );
60 assert( xTask!=0 );
drhcb6effa2014-05-20 19:11:5061 /* This routine is never used in single-threaded mode */
62 assert( sqlite3GlobalConfig.bCoreMutex!=0 );
63
mistachkinda0e4712012-07-21 22:49:0864 *ppThread = 0;
65 p = sqlite3Malloc(sizeof(*p));
mistachkinfad30392016-02-13 23:43:4666 if( p==0 ) return SQLITE_NOMEM_BKPT;
drh6ddecb72012-08-21 17:36:4467 memset(p, 0, sizeof(*p));
drh3de4df22014-04-24 12:28:2868 p->xTask = xTask;
69 p->pIn = pIn;
drh2ea31b12015-09-25 23:40:0170 /* 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. */
drhb92284d2014-07-29 18:46:3074 if( sqlite3FaultSim(200) ){
75 rc = 1;
76 }else{
77 rc = pthread_create(&p->tid, 0, xTask, pIn);
78 }
79 if( rc ){
drh6ddecb72012-08-21 17:36:4480 p->done = 1;
81 p->pOut = xTask(pIn);
drhf51446a2012-07-21 19:40:4282 }
mistachkinda0e4712012-07-21 22:49:0883 *ppThread = p;
drhf51446a2012-07-21 19:40:4284 return SQLITE_OK;
85}
86
87/* Get the results of the thread */
88int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
89 int rc;
mistachkinda0e4712012-07-21 22:49:0890
91 assert( ppOut!=0 );
mistachkinfad30392016-02-13 23:43:4692 if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
drh6ddecb72012-08-21 17:36:4493 if( p->done ){
94 *ppOut = p->pOut;
95 rc = SQLITE_OK;
96 }else{
drhcb6effa2014-05-20 19:11:5097 rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK;
drh6ddecb72012-08-21 17:36:4498 }
drhf51446a2012-07-21 19:40:4299 sqlite3_free(p);
drhcb6effa2014-05-20 19:11:50100 return rc;
drhf51446a2012-07-21 19:40:42101}
102
103#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
104/******************************** End Unix Pthreads *************************/
105
106
mistachkinda0e4712012-07-21 22:49:08107/********************************* Win32 Threads ****************************/
mistachkin89ea0d32015-01-19 20:05:53108#if SQLITE_OS_WIN_THREADS
mistachkinda0e4712012-07-21 22:49:08109
110#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
111#include <process.h>
112
113/* A running thread */
114struct SQLiteThread {
drhab993382014-10-10 18:09:52115 void *tid; /* The thread handle */
mistachkinb1ac2bc2014-07-29 16:37:53116 unsigned id; /* The thread identifier */
mistachkinda0e4712012-07-21 22:49:08117 void *(*xTask)(void*); /* The routine to run as a thread */
118 void *pIn; /* Argument to xTask */
119 void *pResult; /* Result of xTask */
120};
121
122/* Thread procedure Win32 compatibility shim */
mistachkinb1ac2bc2014-07-29 16:37:53123static unsigned __stdcall sqlite3ThreadProc(
mistachkinda0e4712012-07-21 22:49:08124 void *pArg /* IN: Pointer to the SQLiteThread structure */
125){
126 SQLiteThread *p = (SQLiteThread *)pArg;
127
128 assert( p!=0 );
mistachkin0479c6a2014-07-29 21:44:13129#if 0
130 /*
131 ** This assert appears to trigger spuriously on certain
132 ** versions of Windows, possibly due to _beginthreadex()
133 ** and/or CreateThread() not fully setting their thread
134 ** ID parameter before starting the thread.
135 */
mistachkinb1ac2bc2014-07-29 16:37:53136 assert( p->id==GetCurrentThreadId() );
mistachkin0479c6a2014-07-29 21:44:13137#endif
mistachkinda0e4712012-07-21 22:49:08138 assert( p->xTask!=0 );
139 p->pResult = p->xTask(p->pIn);
mistachkinb1ac2bc2014-07-29 16:37:53140
141 _endthreadex(0);
142 return 0; /* NOT REACHED */
mistachkinda0e4712012-07-21 22:49:08143}
144
145/* Create a new thread */
146int sqlite3ThreadCreate(
147 SQLiteThread **ppThread, /* OUT: Write the thread object here */
148 void *(*xTask)(void*), /* Routine to run in a separate thread */
149 void *pIn /* Argument passed into xTask() */
150){
151 SQLiteThread *p;
152
153 assert( ppThread!=0 );
154 assert( xTask!=0 );
155 *ppThread = 0;
156 p = sqlite3Malloc(sizeof(*p));
mistachkinfad30392016-02-13 23:43:46157 if( p==0 ) return SQLITE_NOMEM_BKPT;
drh2ea31b12015-09-25 23:40:01158 /* 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) ){
drh6ddecb72012-08-21 17:36:44164 memset(p, 0, sizeof(*p));
165 }else{
166 p->xTask = xTask;
167 p->pIn = pIn;
drhab993382014-10-10 18:09:52168 p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
mistachkinacd57ea2014-07-29 19:00:43169 if( p->tid==0 ){
drh6ddecb72012-08-21 17:36:44170 memset(p, 0, sizeof(*p));
171 }
172 }
173 if( p->xTask==0 ){
mistachkinb1ac2bc2014-07-29 16:37:53174 p->id = GetCurrentThreadId();
drh6ddecb72012-08-21 17:36:44175 p->pResult = xTask(pIn);
mistachkinda0e4712012-07-21 22:49:08176 }
177 *ppThread = p;
178 return SQLITE_OK;
179}
180
mistachkinb1ac2bc2014-07-29 16:37:53181DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */
drh2b493272014-07-29 00:23:08182
mistachkinda0e4712012-07-21 22:49:08183/* Get the results of the thread */
184int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
185 DWORD rc;
mistachkinb1ac2bc2014-07-29 16:37:53186 BOOL bRc;
mistachkinda0e4712012-07-21 22:49:08187
188 assert( ppOut!=0 );
mistachkinfad30392016-02-13 23:43:46189 if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
drh6ddecb72012-08-21 17:36:44190 if( p->xTask==0 ){
drh17db1552015-09-26 01:28:46191 /* assert( p->id==GetCurrentThreadId() ); */
mistachkinf7da5552014-04-04 21:40:38192 rc = WAIT_OBJECT_0;
mistachkin7c2231c2014-07-29 18:53:01193 assert( p->tid==0 );
drh6ddecb72012-08-21 17:36:44194 }else{
mistachkinb1ac2bc2014-07-29 16:37:53195 assert( p->id!=0 && p->id!=GetCurrentThreadId() );
drh6ddecb72012-08-21 17:36:44196 rc = sqlite3Win32Wait((HANDLE)p->tid);
197 assert( rc!=WAIT_IO_COMPLETION );
mistachkinb1ac2bc2014-07-29 16:37:53198 bRc = CloseHandle((HANDLE)p->tid);
199 assert( bRc );
drh6ddecb72012-08-21 17:36:44200 }
mistachkinda0e4712012-07-21 22:49:08201 if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
202 sqlite3_free(p);
203 return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
204}
205
mistachkin89ea0d32015-01-19 20:05:53206#endif /* SQLITE_OS_WIN_THREADS */
mistachkinda0e4712012-07-21 22:49:08207/******************************** End Win32 Threads *************************/
208
209
drhf51446a2012-07-21 19:40:42210/********************************* Single-Threaded **************************/
211#ifndef SQLITE_THREADS_IMPLEMENTED
212/*
213** This implementation does not actually create a new thread. It does the
214** work of the thread in the main thread, when either the thread is created
215** or when it is joined
216*/
217
218/* A running thread */
219struct SQLiteThread {
220 void *(*xTask)(void*); /* The routine to run as a thread */
221 void *pIn; /* Argument to xTask */
222 void *pResult; /* Result of xTask */
223};
224
225/* Create a new thread */
226int sqlite3ThreadCreate(
227 SQLiteThread **ppThread, /* OUT: Write the thread object here */
228 void *(*xTask)(void*), /* Routine to run in a separate thread */
229 void *pIn /* Argument passed into xTask() */
230){
231 SQLiteThread *p;
mistachkinda0e4712012-07-21 22:49:08232
233 assert( ppThread!=0 );
234 assert( xTask!=0 );
235 *ppThread = 0;
236 p = sqlite3Malloc(sizeof(*p));
mistachkinfad30392016-02-13 23:43:46237 if( p==0 ) return SQLITE_NOMEM_BKPT;
drhf51446a2012-07-21 19:40:42238 if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
239 p->xTask = xTask;
240 p->pIn = pIn;
241 }else{
242 p->xTask = 0;
243 p->pResult = xTask(pIn);
244 }
mistachkinda0e4712012-07-21 22:49:08245 *ppThread = p;
246 return SQLITE_OK;
drhf51446a2012-07-21 19:40:42247}
248
249/* Get the results of the thread */
250int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
dand94d4ee2014-05-05 09:08:54251
mistachkinda0e4712012-07-21 22:49:08252 assert( ppOut!=0 );
mistachkinfad30392016-02-13 23:43:46253 if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
drhf51446a2012-07-21 19:40:42254 if( p->xTask ){
mistachkinda0e4712012-07-21 22:49:08255 *ppOut = p->xTask(p->pIn);
drhf51446a2012-07-21 19:40:42256 }else{
257 *ppOut = p->pResult;
258 }
259 sqlite3_free(p);
dand94d4ee2014-05-05 09:08:54260
261#if defined(SQLITE_TEST)
262 {
263 void *pTstAlloc = sqlite3Malloc(10);
mistachkinfad30392016-02-13 23:43:46264 if (!pTstAlloc) return SQLITE_NOMEM_BKPT;
dand94d4ee2014-05-05 09:08:54265 sqlite3_free(pTstAlloc);
266 }
267#endif
268
drhf51446a2012-07-21 19:40:42269 return SQLITE_OK;
270}
271
272#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
273/****************************** End Single-Threaded *************************/
danb3f56fd2014-03-31 19:57:34274#endif /* SQLITE_MAX_WORKER_THREADS>0 */