4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
11 ******************************************************************************
13 ** This file presents a simple cross-platform threading interface for
14 ** use internally by SQLite.
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.
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.
28 #include "sqliteInt.h"
30 #if SQLITE_MAX_WORKER_THREADS>0
32 /********************************* Unix Pthreads ****************************/
33 #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
35 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
38 /* A running thread */
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 */
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() */
56 assert( ppThread
!=0 );
58 /* This routine is never used in single-threaded mode */
59 assert( sqlite3GlobalConfig
.bCoreMutex
!=0 );
62 p
= sqlite3Malloc(sizeof(*p
));
63 if( p
==0 ) return SQLITE_NOMEM
;
64 memset(p
, 0, sizeof(*p
));
67 if( sqlite3FaultSim(200) ){
70 rc
= pthread_create(&p
->tid
, 0, xTask
, pIn
);
80 /* Get the results of the thread */
81 int sqlite3ThreadJoin(SQLiteThread
*p
, void **ppOut
){
85 if( NEVER(p
==0) ) return SQLITE_NOMEM
;
90 rc
= pthread_join(p
->tid
, ppOut
) ? SQLITE_ERROR
: SQLITE_OK
;
96 #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
97 /******************************** End Unix Pthreads *************************/
100 /********************************* Win32 Threads ****************************/
101 #if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
103 #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
106 /* A running thread */
107 struct SQLiteThread
{
108 void *tid
; /* The thread handle */
109 unsigned id
; /* The thread identifier */
110 void *(*xTask
)(void*); /* The routine to run as a thread */
111 void *pIn
; /* Argument to xTask */
112 void *pResult
; /* Result of xTask */
115 /* Thread procedure Win32 compatibility shim */
116 static unsigned __stdcall
sqlite3ThreadProc(
117 void *pArg
/* IN: Pointer to the SQLiteThread structure */
119 SQLiteThread
*p
= (SQLiteThread
*)pArg
;
124 ** This assert appears to trigger spuriously on certain
125 ** versions of Windows, possibly due to _beginthreadex()
126 ** and/or CreateThread() not fully setting their thread
127 ** ID parameter before starting the thread.
129 assert( p
->id
==GetCurrentThreadId() );
131 assert( p
->xTask
!=0 );
132 p
->pResult
= p
->xTask(p
->pIn
);
135 return 0; /* NOT REACHED */
138 /* Create a new thread */
139 int sqlite3ThreadCreate(
140 SQLiteThread
**ppThread
, /* OUT: Write the thread object here */
141 void *(*xTask
)(void*), /* Routine to run in a separate thread */
142 void *pIn
/* Argument passed into xTask() */
146 assert( ppThread
!=0 );
149 p
= sqlite3Malloc(sizeof(*p
));
150 if( p
==0 ) return SQLITE_NOMEM
;
151 if( sqlite3GlobalConfig
.bCoreMutex
==0 ){
152 memset(p
, 0, sizeof(*p
));
156 p
->tid
= (void*)_beginthreadex(0, 0, sqlite3ThreadProc
, p
, 0, &p
->id
);
158 memset(p
, 0, sizeof(*p
));
162 p
->id
= GetCurrentThreadId();
163 p
->pResult
= xTask(pIn
);
169 DWORD
sqlite3Win32Wait(HANDLE hObject
); /* os_win.c */
171 /* Get the results of the thread */
172 int sqlite3ThreadJoin(SQLiteThread
*p
, void **ppOut
){
177 if( NEVER(p
==0) ) return SQLITE_NOMEM
;
179 assert( p
->id
==GetCurrentThreadId() );
183 assert( p
->id
!=0 && p
->id
!=GetCurrentThreadId() );
184 rc
= sqlite3Win32Wait((HANDLE
)p
->tid
);
185 assert( rc
!=WAIT_IO_COMPLETION
);
186 bRc
= CloseHandle((HANDLE
)p
->tid
);
189 if( rc
==WAIT_OBJECT_0
) *ppOut
= p
->pResult
;
191 return (rc
==WAIT_OBJECT_0
) ? SQLITE_OK
: SQLITE_ERROR
;
194 #endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */
195 /******************************** End Win32 Threads *************************/
198 /********************************* Single-Threaded **************************/
199 #ifndef SQLITE_THREADS_IMPLEMENTED
201 ** 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
203 ** or when it is joined
206 /* A running thread */
207 struct SQLiteThread
{
208 void *(*xTask
)(void*); /* The routine to run as a thread */
209 void *pIn
; /* Argument to xTask */
210 void *pResult
; /* Result of xTask */
213 /* Create a new thread */
214 int sqlite3ThreadCreate(
215 SQLiteThread
**ppThread
, /* OUT: Write the thread object here */
216 void *(*xTask
)(void*), /* Routine to run in a separate thread */
217 void *pIn
/* Argument passed into xTask() */
221 assert( ppThread
!=0 );
224 p
= sqlite3Malloc(sizeof(*p
));
225 if( p
==0 ) return SQLITE_NOMEM
;
226 if( (SQLITE_PTR_TO_INT(p
)/17)&1 ){
231 p
->pResult
= xTask(pIn
);
237 /* Get the results of the thread */
238 int sqlite3ThreadJoin(SQLiteThread
*p
, void **ppOut
){
241 if( NEVER(p
==0) ) return SQLITE_NOMEM
;
243 *ppOut
= p
->xTask(p
->pIn
);
249 #if defined(SQLITE_TEST)
251 void *pTstAlloc
= sqlite3Malloc(10);
252 if (!pTstAlloc
) return SQLITE_NOMEM
;
253 sqlite3_free(pTstAlloc
);
260 #endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
261 /****************************** End Single-Threaded *************************/
262 #endif /* SQLITE_MAX_WORKER_THREADS>0 */