1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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 #ifdef _WIN32_WCE 108 typedef HANDLE curl_win_thread_handle_t; 109 #elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 110 typedef unsigned long curl_win_thread_handle_t; 111 #else 112 typedef uintptr_t curl_win_thread_handle_t; 113 #endif 114 curl_thread_t t; 115 curl_win_thread_handle_t thread_handle; 116 #ifdef _WIN32_WCE 117 thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL); 118 #else 119 thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL); 120 #endif 121 t = (curl_thread_t)thread_handle; 122 if((t == 0) || (t == LongToHandle(-1L))) { 123 #ifdef _WIN32_WCE 124 DWORD gle = GetLastError(); 125 errno = ((gle == ERROR_ACCESS_DENIED || 126 gle == ERROR_NOT_ENOUGH_MEMORY) ? 127 EACCES : EINVAL); 128 #endif 129 return curl_thread_t_null; 130 } 131 return t; 132 } 133 134 void Curl_thread_destroy(curl_thread_t hnd) 135 { 136 CloseHandle(hnd); 137 } 138 139 int Curl_thread_join(curl_thread_t *hnd) 140 { 141 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ 142 (_WIN32_WINNT < _WIN32_WINNT_VISTA) 143 int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); 144 #else 145 int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); 146 #endif 147 148 Curl_thread_destroy(*hnd); 149 150 *hnd = curl_thread_t_null; 151 152 return ret; 153 } 154 155 #endif /* USE_THREADS_* */ 156