Coverage Report

Created: 2025-10-10 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PROJ/curl/lib/curl_threads.c
Line
Count
Source
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) && defined(HAVE_PTHREAD_H)
30
#include <pthread.h>
31
#endif
32
33
#include "curl_threads.h"
34
#include "curl_memory.h"
35
/* The last #include FILE should be: */
36
#include "memdebug.h"
37
38
#ifdef USE_THREADS_POSIX
39
40
struct Curl_actual_call {
41
  unsigned int (*func)(void *);
42
  void *arg;
43
};
44
45
static void *curl_thread_create_thunk(void *arg)
46
0
{
47
0
  struct Curl_actual_call *ac = arg;
48
0
  unsigned int (*func)(void *) = ac->func;
49
0
  void *real_arg = ac->arg;
50
51
0
  free(ac);
52
53
0
  (*func)(real_arg);
54
55
0
  return 0;
56
0
}
57
58
curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
59
                                 (CURL_STDCALL *func) (void *), void *arg)
60
0
{
61
0
  curl_thread_t t = malloc(sizeof(pthread_t));
62
0
  struct Curl_actual_call *ac = malloc(sizeof(struct Curl_actual_call));
63
0
  if(!(ac && t))
64
0
    goto err;
65
66
0
  ac->func = func;
67
0
  ac->arg = arg;
68
69
0
  if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0)
70
0
    goto err;
71
72
0
  return t;
73
74
0
err:
75
0
  free(t);
76
0
  free(ac);
77
0
  return curl_thread_t_null;
78
0
}
79
80
void Curl_thread_destroy(curl_thread_t *hnd)
81
0
{
82
0
  if(*hnd != curl_thread_t_null) {
83
0
    pthread_detach(**hnd);
84
0
    free(*hnd);
85
0
    *hnd = curl_thread_t_null;
86
0
  }
87
0
}
88
89
int Curl_thread_join(curl_thread_t *hnd)
90
0
{
91
0
  int ret = (pthread_join(**hnd, NULL) == 0);
92
93
0
  free(*hnd);
94
0
  *hnd = curl_thread_t_null;
95
96
0
  return ret;
97
0
}
98
99
#elif defined(USE_THREADS_WIN32)
100
101
curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
102
                                 (CURL_STDCALL *func) (void *), void *arg)
103
{
104
  curl_thread_t t = CreateThread(NULL, 0, func, arg, 0, NULL);
105
  if(!t) {
106
#ifdef UNDER_CE
107
    DWORD gle = GetLastError();
108
    /* !checksrc! disable ERRNOVAR 1 */
109
    int err = (gle == ERROR_ACCESS_DENIED ||
110
               gle == ERROR_NOT_ENOUGH_MEMORY) ?
111
               EACCES : EINVAL;
112
    CURL_SETERRNO(err);
113
#endif
114
    return curl_thread_t_null;
115
  }
116
  return t;
117
}
118
119
void Curl_thread_destroy(curl_thread_t *hnd)
120
{
121
  if(*hnd != curl_thread_t_null) {
122
    CloseHandle(*hnd);
123
    *hnd = curl_thread_t_null;
124
  }
125
}
126
127
int Curl_thread_join(curl_thread_t *hnd)
128
{
129
#ifdef UNDER_CE
130
  int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
131
#else
132
  int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
133
#endif
134
135
  Curl_thread_destroy(hnd);
136
137
  return ret;
138
}
139
140
#endif /* USE_THREADS_* */