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 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 103curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), 104 void *arg) 105{ 106#ifdef _WIN32_WCE 107 return CreateThread(NULL, 0, func, arg, 0, NULL); 108#else 109 curl_thread_t t; 110 t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL); 111 if((t == 0) || (t == (curl_thread_t)-1L)) 112 return curl_thread_t_null; 113 return t; 114#endif 115} 116 117void Curl_thread_destroy(curl_thread_t hnd) 118{ 119 CloseHandle(hnd); 120} 121 122int Curl_thread_join(curl_thread_t *hnd) 123{ 124#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ 125 (_WIN32_WINNT < _WIN32_WINNT_VISTA) 126 int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); 127#else 128 int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); 129#endif 130 131 Curl_thread_destroy(*hnd); 132 133 *hnd = curl_thread_t_null; 134 135 return ret; 136} 137 138#endif /* USE_THREADS_* */ 139