curl_threads.c (4038B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #include <curl/curl.h> 28 29 #if defined(USE_THREADS_POSIX) 30 # ifdef HAVE_PTHREAD_H 31 # include <pthread.h> 32 # endif 33 #elif defined(USE_THREADS_WIN32) 34 # include <process.h> 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 *hnd = curl_thread_t_null; 89 } 90 } 91 92 int Curl_thread_join(curl_thread_t *hnd) 93 { 94 int ret = (pthread_join(**hnd, NULL) == 0); 95 96 free(*hnd); 97 *hnd = curl_thread_t_null; 98 99 return ret; 100 } 101 102 #elif defined(USE_THREADS_WIN32) 103 104 curl_thread_t Curl_thread_create( 105 #if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE) 106 DWORD 107 #else 108 unsigned int 109 #endif 110 (CURL_STDCALL *func) (void *), 111 void *arg) 112 { 113 #if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE) 114 typedef HANDLE curl_win_thread_handle_t; 115 #else 116 typedef uintptr_t curl_win_thread_handle_t; 117 #endif 118 curl_thread_t t; 119 curl_win_thread_handle_t thread_handle; 120 #if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE) 121 thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL); 122 #else 123 thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL); 124 #endif 125 t = (curl_thread_t)thread_handle; 126 if((t == 0) || (t == LongToHandle(-1L))) { 127 #ifdef UNDER_CE 128 DWORD gle = GetLastError(); 129 /* !checksrc! disable ERRNOVAR 1 */ 130 int err = (gle == ERROR_ACCESS_DENIED || 131 gle == ERROR_NOT_ENOUGH_MEMORY) ? 132 EACCES : EINVAL; 133 CURL_SETERRNO(err); 134 #endif 135 return curl_thread_t_null; 136 } 137 return t; 138 } 139 140 void Curl_thread_destroy(curl_thread_t *hnd) 141 { 142 if(*hnd != curl_thread_t_null) { 143 CloseHandle(*hnd); 144 *hnd = curl_thread_t_null; 145 } 146 } 147 148 int Curl_thread_join(curl_thread_t *hnd) 149 { 150 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ 151 (_WIN32_WINNT < _WIN32_WINNT_VISTA) 152 int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); 153 #else 154 int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); 155 #endif 156 157 Curl_thread_destroy(hnd); 158 159 return ret; 160 } 161 162 #endif /* USE_THREADS_* */