Changeset 391 for python/trunk/Python/thread_nt.h
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Python/thread_nt.h
r2 r391 11 11 12 12 typedef struct NRMUTEX { 13 14 15 13 LONG owned ; 14 DWORD thread_id ; 15 HANDLE hevent ; 16 16 } NRMUTEX, *PNRMUTEX ; 17 17 … … 20 20 InitializeNonRecursiveMutex(PNRMUTEX mutex) 21 21 { 22 23 24 25 return mutex->hevent != NULL ;/* TRUE if the mutex is created */22 mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */ 23 mutex->thread_id = 0 ; 24 mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ; 25 return mutex->hevent != NULL ; /* TRUE if the mutex is created */ 26 26 } 27 27 … … 29 29 DeleteNonRecursiveMutex(PNRMUTEX mutex) 30 30 { 31 32 33 31 /* No in-use check */ 32 CloseHandle(mutex->hevent) ; 33 mutex->hevent = NULL ; /* Just in case */ 34 34 } 35 35 … … 37 37 EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait) 38 38 { 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 39 /* Assume that the thread waits successfully */ 40 DWORD ret ; 41 42 /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ 43 if (!wait) 44 { 45 if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1) 46 return WAIT_TIMEOUT ; 47 ret = WAIT_OBJECT_0 ; 48 } 49 else 50 ret = InterlockedIncrement(&mutex->owned) ? 51 /* Some thread owns the mutex, let's wait... */ 52 WaitForSingleObject(mutex->hevent, INFINITE) : WAIT_OBJECT_0 ; 53 54 mutex->thread_id = GetCurrentThreadId() ; /* We own it */ 55 return ret ; 56 56 } 57 57 … … 59 59 LeaveNonRecursiveMutex(PNRMUTEX mutex) 60 60 { 61 62 63 64 65 61 /* We don't own the mutex */ 62 mutex->thread_id = 0 ; 63 return 64 InterlockedDecrement(&mutex->owned) < 0 || 65 SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */ 66 66 } 67 67 … … 69 69 AllocNonRecursiveMutex(void) 70 70 { 71 72 73 74 75 76 77 71 PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ; 72 if (mutex && !InitializeNonRecursiveMutex(mutex)) 73 { 74 free(mutex) ; 75 mutex = NULL ; 76 } 77 return mutex ; 78 78 } 79 79 … … 81 81 FreeNonRecursiveMutex(PNRMUTEX mutex) 82 82 { 83 84 85 86 87 83 if (mutex) 84 { 85 DeleteNonRecursiveMutex(mutex) ; 86 free(mutex) ; 87 } 88 88 } 89 89 … … 103 103 104 104 typedef struct { 105 void (*func)(void*); 106 void *arg; 107 long id; 108 HANDLE done; 105 void (*func)(void*); 106 void *arg; 109 107 } callobj; 110 108 111 static int 109 /* thunker to call adapt between the function type used by the system's 110 thread start function and the internally used one. */ 111 #if defined(MS_WINCE) 112 static DWORD WINAPI 113 #else 114 static unsigned __stdcall 115 #endif 112 116 bootstrap(void *call) 113 117 { 114 callobj *obj = (callobj*)call; 115 /* copy callobj since other thread might free it before we're done */ 116 void (*func)(void*) = obj->func; 117 void *arg = obj->arg; 118 119 obj->id = PyThread_get_thread_ident(); 120 ReleaseSemaphore(obj->done, 1, NULL); 121 func(arg); 122 return 0; 118 callobj *obj = (callobj*)call; 119 void (*func)(void*) = obj->func; 120 void *arg = obj->arg; 121 HeapFree(GetProcessHeap(), 0, obj); 122 func(arg); 123 return 0; 123 124 } 124 125 … … 126 127 PyThread_start_new_thread(void (*func)(void *), void *arg) 127 128 { 128 Py_uintptr_t rv; 129 callobj obj; 130 131 dprintf(("%ld: PyThread_start_new_thread called\n", 132 PyThread_get_thread_ident())); 133 if (!initialized) 134 PyThread_init_thread(); 135 136 obj.id = -1; /* guilty until proved innocent */ 137 obj.func = func; 138 obj.arg = arg; 139 obj.done = CreateSemaphore(NULL, 0, 1, NULL); 140 if (obj.done == NULL) 141 return -1; 142 143 rv = _beginthread(bootstrap, 144 Py_SAFE_DOWNCAST(_pythread_stacksize, 145 Py_ssize_t, int), 146 &obj); 147 if (rv == (Py_uintptr_t)-1) { 148 /* I've seen errno == EAGAIN here, which means "there are 149 * too many threads". 150 */ 151 dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", 152 PyThread_get_thread_ident(), (void*)rv, errno)); 153 obj.id = -1; 154 } 155 else { 156 dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", 157 PyThread_get_thread_ident(), (void*)rv)); 158 /* wait for thread to initialize, so we can get its id */ 159 WaitForSingleObject(obj.done, INFINITE); 160 assert(obj.id != -1); 161 } 162 CloseHandle((HANDLE)obj.done); 163 return obj.id; 129 HANDLE hThread; 130 unsigned threadID; 131 callobj *obj; 132 133 dprintf(("%ld: PyThread_start_new_thread called\n", 134 PyThread_get_thread_ident())); 135 if (!initialized) 136 PyThread_init_thread(); 137 138 obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); 139 if (!obj) 140 return -1; 141 obj->func = func; 142 obj->arg = arg; 143 #if defined(MS_WINCE) 144 hThread = CreateThread(NULL, 145 Py_SAFE_DOWNCAST(_pythread_stacksize, Py_ssize_t, SIZE_T), 146 bootstrap, obj, 0, &threadID); 147 #else 148 hThread = (HANDLE)_beginthreadex(0, 149 Py_SAFE_DOWNCAST(_pythread_stacksize, 150 Py_ssize_t, unsigned int), 151 bootstrap, obj, 152 0, &threadID); 153 #endif 154 if (hThread == 0) { 155 #if defined(MS_WINCE) 156 /* Save error in variable, to prevent PyThread_get_thread_ident 157 from clobbering it. */ 158 unsigned e = GetLastError(); 159 dprintf(("%ld: PyThread_start_new_thread failed, win32 error code %u\n", 160 PyThread_get_thread_ident(), e)); 161 #else 162 /* I've seen errno == EAGAIN here, which means "there are 163 * too many threads". 164 */ 165 int e = errno; 166 dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n", 167 PyThread_get_thread_ident(), e)); 168 #endif 169 threadID = (unsigned)-1; 170 HeapFree(GetProcessHeap(), 0, obj); 171 } 172 else { 173 dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", 174 PyThread_get_thread_ident(), (void*)hThread)); 175 CloseHandle(hThread); 176 } 177 return (long) threadID; 164 178 } 165 179 … … 171 185 PyThread_get_thread_ident(void) 172 186 { 173 if (!initialized) 174 PyThread_init_thread(); 175 176 return GetCurrentThreadId(); 177 } 178 179 static void 180 do_PyThread_exit_thread(int no_cleanup) 181 { 182 dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); 183 if (!initialized) 184 if (no_cleanup) 185 _exit(0); 186 else 187 exit(0); 188 _endthread(); 187 if (!initialized) 188 PyThread_init_thread(); 189 190 return GetCurrentThreadId(); 189 191 } 190 192 … … 192 194 PyThread_exit_thread(void) 193 195 { 194 do_PyThread_exit_thread(0); 195 } 196 197 void 198 PyThread__exit_thread(void) 199 { 200 do_PyThread_exit_thread(1); 201 } 202 203 #ifndef NO_EXIT_PROG 204 static void 205 do_PyThread_exit_prog(int status, int no_cleanup) 206 { 207 dprintf(("PyThread_exit_prog(%d) called\n", status)); 208 if (!initialized) 209 if (no_cleanup) 210 _exit(status); 211 else 212 exit(status); 213 } 214 215 void 216 PyThread_exit_prog(int status) 217 { 218 do_PyThread_exit_prog(status, 0); 219 } 220 221 void 222 PyThread__exit_prog(int status) 223 { 224 do_PyThread_exit_prog(status, 1); 225 } 226 #endif /* NO_EXIT_PROG */ 196 dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); 197 if (!initialized) 198 exit(0); 199 #if defined(MS_WINCE) 200 ExitThread(0); 201 #else 202 _endthreadex(0); 203 #endif 204 } 227 205 228 206 /* … … 234 212 PyThread_allocate_lock(void) 235 213 { 236 237 238 239 240 241 242 243 244 245 246 214 PNRMUTEX aLock; 215 216 dprintf(("PyThread_allocate_lock called\n")); 217 if (!initialized) 218 PyThread_init_thread(); 219 220 aLock = AllocNonRecursiveMutex() ; 221 222 dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); 223 224 return (PyThread_type_lock) aLock; 247 225 } 248 226 … … 250 228 PyThread_free_lock(PyThread_type_lock aLock) 251 229 { 252 253 254 230 dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); 231 232 FreeNonRecursiveMutex(aLock) ; 255 233 } 256 234 … … 264 242 PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) 265 243 { 266 267 268 269 270 271 272 273 274 244 int success ; 245 246 dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); 247 248 success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ; 249 250 dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); 251 252 return success; 275 253 } 276 254 … … 278 256 PyThread_release_lock(PyThread_type_lock aLock) 279 257 { 280 281 282 283 258 dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); 259 260 if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) 261 dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); 284 262 } 285 263 286 264 /* minimum/maximum thread stack sizes supported */ 287 #define THREAD_MIN_STACKSIZE 0x8000/* 32kB */288 #define THREAD_MAX_STACKSIZE 0x10000000/* 256MB */265 #define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */ 266 #define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */ 289 267 290 268 /* set the thread stack size. … … 294 272 _pythread_nt_set_stacksize(size_t size) 295 273 { 296 /* set to default */ 297 if (size == 0) { 298 _pythread_stacksize = 0; 299 return 0; 300 } 301 302 /* valid range? */ 303 if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { 304 _pythread_stacksize = size; 305 return 0; 306 } 307 308 return -1; 309 } 310 311 #define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x) 274 /* set to default */ 275 if (size == 0) { 276 _pythread_stacksize = 0; 277 return 0; 278 } 279 280 /* valid range? */ 281 if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { 282 _pythread_stacksize = size; 283 return 0; 284 } 285 286 return -1; 287 } 288 289 #define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x) 290 291 292 /* use native Windows TLS functions */ 293 #define Py_HAVE_NATIVE_TLS 294 295 #ifdef Py_HAVE_NATIVE_TLS 296 int 297 PyThread_create_key(void) 298 { 299 return (int) TlsAlloc(); 300 } 301 302 void 303 PyThread_delete_key(int key) 304 { 305 TlsFree(key); 306 } 307 308 /* We must be careful to emulate the strange semantics implemented in thread.c, 309 * where the value is only set if it hasn't been set before. 310 */ 311 int 312 PyThread_set_key_value(int key, void *value) 313 { 314 BOOL ok; 315 void *oldvalue; 316 317 assert(value != NULL); 318 oldvalue = TlsGetValue(key); 319 if (oldvalue != NULL) 320 /* ignore value if already set */ 321 return 0; 322 ok = TlsSetValue(key, value); 323 if (!ok) 324 return -1; 325 return 0; 326 } 327 328 void * 329 PyThread_get_key_value(int key) 330 { 331 /* because TLS is used in the Py_END_ALLOW_THREAD macro, 332 * it is necessary to preserve the windows error state, because 333 * it is assumed to be preserved across the call to the macro. 334 * Ideally, the macro should be fixed, but it is simpler to 335 * do it here. 336 */ 337 DWORD error = GetLastError(); 338 void *result = TlsGetValue(key); 339 SetLastError(error); 340 return result; 341 } 342 343 void 344 PyThread_delete_key_value(int key) 345 { 346 /* NULL is used as "key missing", and it is also the default 347 * given by TlsGetValue() if nothing has been set yet. 348 */ 349 TlsSetValue(key, NULL); 350 } 351 352 /* reinitialization of TLS is not necessary after fork when using 353 * the native TLS functions. And forking isn't supported on Windows either. 354 */ 355 void 356 PyThread_ReInitTLS(void) 357 {} 358 359 #endif
Note:
See TracChangeset
for help on using the changeset viewer.