Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * _ _ ____ _ |
| 3 | * Project ___| | | | _ \| | |
| 4 | * / __| | | | |_) | | |
| 5 | * | (__| |_| | _ <| |___ |
| 6 | * \___|\___/|_| \_\_____| |
| 7 | * |
Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 8 | * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 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 |
Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 12 | * are also available at https://curl.haxx.se/docs/copyright.html. |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 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 | ***************************************************************************/ |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 22 | |
| 23 | #include "curl_setup.h" |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 24 | |
Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 25 | #include <curl/curl.h> |
| 26 | |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 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" |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 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 | |
Elliott Hughes | cee0338 | 2017-06-23 12:17:18 -0700 | [diff] [blame] | 62 | curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg) |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 63 | { |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 64 | curl_thread_t t = malloc(sizeof(pthread_t)); |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 65 | struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 66 | if(!(ac && t)) |
| 67 | goto err; |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 68 | |
| 69 | ac->func = func; |
| 70 | ac->arg = arg; |
| 71 | |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 72 | if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0) |
| 73 | goto err; |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 74 | |
| 75 | return t; |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 76 | |
| 77 | err: |
| 78 | free(t); |
| 79 | free(ac); |
| 80 | return curl_thread_t_null; |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | void Curl_thread_destroy(curl_thread_t hnd) |
| 84 | { |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 85 | if(hnd != curl_thread_t_null) { |
| 86 | pthread_detach(*hnd); |
| 87 | free(hnd); |
| 88 | } |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | int Curl_thread_join(curl_thread_t *hnd) |
| 92 | { |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 93 | int ret = (pthread_join(**hnd, NULL) == 0); |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 94 | |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 95 | free(*hnd); |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 96 | *hnd = curl_thread_t_null; |
| 97 | |
| 98 | return ret; |
| 99 | } |
| 100 | |
| 101 | #elif defined(USE_THREADS_WIN32) |
| 102 | |
Elliott Hughes | 82be86d | 2017-09-20 17:00:17 -0700 | [diff] [blame] | 103 | /* !checksrc! disable SPACEBEFOREPAREN 1 */ |
Elliott Hughes | cee0338 | 2017-06-23 12:17:18 -0700 | [diff] [blame] | 104 | curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 105 | void *arg) |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 106 | { |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 107 | curl_thread_t t; |
Elliott Hughes | 82be86d | 2017-09-20 17:00:17 -0700 | [diff] [blame] | 108 | #ifdef _WIN32_WCE |
| 109 | t = CreateThread(NULL, 0, func, arg, 0, NULL); |
| 110 | #else |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 111 | t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL); |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 112 | #endif |
Elliott Hughes | 82be86d | 2017-09-20 17:00:17 -0700 | [diff] [blame] | 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; |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 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 | { |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 132 | #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ |
| 133 | (_WIN32_WINNT < _WIN32_WINNT_VISTA) |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 134 | int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); |
Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 135 | #else |
| 136 | int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); |
| 137 | #endif |
Kristian Monsen | 5ab5018 | 2010-05-14 18:53:44 +0100 | [diff] [blame] | 138 | |
| 139 | Curl_thread_destroy(*hnd); |
| 140 | |
| 141 | *hnd = curl_thread_t_null; |
| 142 | |
| 143 | return ret; |
| 144 | } |
| 145 | |
| 146 | #endif /* USE_THREADS_* */ |