1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2013, 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 http://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#if defined(USE_THREADS_POSIX)
26#  ifdef HAVE_PTHREAD_H
27#    include <pthread.h>
28#  endif
29#elif defined(USE_THREADS_WIN32)
30#  ifdef HAVE_PROCESS_H
31#    include <process.h>
32#  endif
33#endif
34
35#include "curl_threads.h"
36
37#define _MPRINTF_REPLACE /* use our functions only */
38#include <curl/mprintf.h>
39
40#include "curl_memory.h"
41/* The last #include file should be: */
42#include "memdebug.h"
43
44#if defined(USE_THREADS_POSIX)
45
46struct curl_actual_call {
47  unsigned int (*func)(void *);
48  void *arg;
49};
50
51static void *curl_thread_create_thunk(void *arg)
52{
53  struct curl_actual_call * ac = arg;
54  unsigned int (*func)(void *) = ac->func;
55  void *real_arg = ac->arg;
56
57  free(ac);
58
59  (*func)(real_arg);
60
61  return 0;
62}
63
64curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
65{
66  curl_thread_t t = malloc(sizeof(pthread_t));
67  struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
68  if(!(ac && t))
69    goto err;
70
71  ac->func = func;
72  ac->arg = arg;
73
74  if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0)
75    goto err;
76
77  return t;
78
79err:
80  Curl_safefree(t);
81  Curl_safefree(ac);
82  return curl_thread_t_null;
83}
84
85void Curl_thread_destroy(curl_thread_t hnd)
86{
87  if(hnd != curl_thread_t_null) {
88    pthread_detach(*hnd);
89    free(hnd);
90  }
91}
92
93int Curl_thread_join(curl_thread_t *hnd)
94{
95  int ret = (pthread_join(**hnd, NULL) == 0);
96
97  free(*hnd);
98  *hnd = curl_thread_t_null;
99
100  return ret;
101}
102
103#elif defined(USE_THREADS_WIN32)
104
105curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
106                                 void *arg)
107{
108#ifdef _WIN32_WCE
109  return CreateThread(NULL, 0, func, arg, 0, NULL);
110#else
111  curl_thread_t t;
112  t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
113  if((t == 0) || (t == (curl_thread_t)-1L))
114    return curl_thread_t_null;
115  return t;
116#endif
117}
118
119void Curl_thread_destroy(curl_thread_t hnd)
120{
121  CloseHandle(hnd);
122}
123
124int Curl_thread_join(curl_thread_t *hnd)
125{
126  int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
127
128  Curl_thread_destroy(*hnd);
129
130  *hnd = curl_thread_t_null;
131
132  return ret;
133}
134
135#endif /* USE_THREADS_* */
136