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 44struct Curl_actual_call { 45 unsigned int (*func)(void *); 46 void *arg; 47}; 48 49static 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 62curl_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 77err: 78 free(t); 79 free(ac); 80 return curl_thread_t_null; 81} 82 83void 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 91int 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 */ 104curl_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#else 110 typedef uintptr_t curl_win_thread_handle_t; 111#endif 112 curl_thread_t t; 113 curl_win_thread_handle_t thread_handle; 114#ifdef _WIN32_WCE 115 thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL); 116#else 117 thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL); 118#endif 119 t = (curl_thread_t)thread_handle; 120 if((t == 0) || (t == LongToHandle(-1L))) { 121#ifdef _WIN32_WCE 122 DWORD gle = GetLastError(); 123 errno = ((gle == ERROR_ACCESS_DENIED || 124 gle == ERROR_NOT_ENOUGH_MEMORY) ? 125 EACCES : EINVAL); 126#endif 127 return curl_thread_t_null; 128 } 129 return t; 130} 131 132void Curl_thread_destroy(curl_thread_t hnd) 133{ 134 CloseHandle(hnd); 135} 136 137int Curl_thread_join(curl_thread_t *hnd) 138{ 139#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ 140 (_WIN32_WINNT < _WIN32_WINNT_VISTA) 141 int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); 142#else 143 int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); 144#endif 145 146 Curl_thread_destroy(*hnd); 147 148 *hnd = curl_thread_t_null; 149 150 return ret; 151} 152 153#endif /* USE_THREADS_* */ 154