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