1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #include <curl/curl.h> 26 27 #if defined(USE_THREADS_POSIX) 28 # ifdef HAVE_PTHREAD_H 29 # include <pthread.h> 30 # endif 31 #elif defined(USE_THREADS_WIN32) 32 # ifdef HAVE_PROCESS_H 33 # include <process.h> 34 # endif 35 #endif 36 37 #include "curl_threads.h" 38 #include "curl_memory.h" 39 /* The last #include file should be: */ 40 #include "memdebug.h" 41 42 #if defined(USE_THREADS_POSIX) 43 44 struct curl_actual_call { 45 unsigned int (*func)(void *); 46 void *arg; 47 }; 48 49 static void *curl_thread_create_thunk(void *arg) 50 { 51 struct curl_actual_call * ac = arg; 52 unsigned int (*func)(void *) = ac->func; 53 void *real_arg = ac->arg; 54 55 free(ac); 56 57 (*func)(real_arg); 58 59 return 0; 60 } 61 62 curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg) 63 { 64 curl_thread_t t = malloc(sizeof(pthread_t)); 65 struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); 66 if(!(ac && t)) 67 goto err; 68 69 ac->func = func; 70 ac->arg = arg; 71 72 if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0) 73 goto err; 74 75 return t; 76 77 err: 78 free(t); 79 free(ac); 80 return curl_thread_t_null; 81 } 82 83 void Curl_thread_destroy(curl_thread_t hnd) 84 { 85 if(hnd != curl_thread_t_null) { 86 pthread_detach(*hnd); 87 free(hnd); 88 } 89 } 90 91 int Curl_thread_join(curl_thread_t *hnd) 92 { 93 int ret = (pthread_join(**hnd, NULL) == 0); 94 95 free(*hnd); 96 *hnd = curl_thread_t_null; 97 98 return ret; 99 } 100 101 #elif defined(USE_THREADS_WIN32) 102 103 /* !checksrc! disable SPACEBEFOREPAREN 1 */ 104 curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), 105 void *arg) 106 { 107 curl_thread_t t; 108 #ifdef _WIN32_WCE 109 t = CreateThread(NULL, 0, func, arg, 0, NULL); 110 #else 111 t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL); 112 #endif 113 if((t == 0) || (t == LongToHandle(-1L))) { 114 #ifdef _WIN32_WCE 115 DWORD gle = GetLastError(); 116 errno = ((gle == ERROR_ACCESS_DENIED || 117 gle == ERROR_NOT_ENOUGH_MEMORY) ? 118 EACCES : EINVAL); 119 #endif 120 return curl_thread_t_null; 121 } 122 return t; 123 } 124 125 void Curl_thread_destroy(curl_thread_t hnd) 126 { 127 CloseHandle(hnd); 128 } 129 130 int Curl_thread_join(curl_thread_t *hnd) 131 { 132 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ 133 (_WIN32_WINNT < _WIN32_WINNT_VISTA) 134 int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); 135 #else 136 int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); 137 #endif 138 139 Curl_thread_destroy(*hnd); 140 141 *hnd = curl_thread_t_null; 142 143 return ret; 144 } 145 146 #endif /* USE_THREADS_* */ 147