summaryrefslogtreecommitdiffstats
path: root/src/mercury/src/util/mercury_thread.h
blob: 3317c41c28724fed5a71fa9676758f7ad35dcae8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
 * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy,
 *                    UChicago Argonne, LLC and The HDF Group.
 * All rights reserved.
 *
 * The full copyright notice, including terms governing use, modification,
 * and redistribution, is contained in the COPYING file that can be
 * found at the root of the source code distribution tree.
 */

#ifndef MERCURY_THREAD_H
#define MERCURY_THREAD_H

#if !defined(_WIN32) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include "mercury_util_config.h"

#ifdef _WIN32
#include <windows.h>
typedef HANDLE                 hg_thread_t;
typedef LPTHREAD_START_ROUTINE hg_thread_func_t;
typedef DWORD                  hg_thread_ret_t;
#define HG_THREAD_RETURN_TYPE hg_thread_ret_t WINAPI
typedef DWORD     hg_thread_key_t;
typedef DWORD_PTR hg_cpu_set_t;
#else
#include <pthread.h>
typedef pthread_t hg_thread_t;
typedef void *(*hg_thread_func_t)(void *);
typedef void *        hg_thread_ret_t;
#define HG_THREAD_RETURN_TYPE hg_thread_ret_t
typedef pthread_key_t hg_thread_key_t;
#ifdef __APPLE__
/* Size definition for CPU sets.  */
#define HG_CPU_SETSIZE 1024
#define HG_NCPUBITS    (8 * sizeof(hg_cpu_mask_t))
/* Type for array elements in 'cpu_set_t'.  */
typedef hg_util_uint64_t hg_cpu_mask_t;
typedef struct {
    hg_cpu_mask_t bits[HG_CPU_SETSIZE / HG_NCPUBITS];
} hg_cpu_set_t;
#else
typedef cpu_set_t hg_cpu_set_t;
#endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Initialize the thread.
 *
 * \param thread [IN/OUT]       pointer to thread object
 */
HG_UTIL_PUBLIC void hg_thread_init(hg_thread_t *thread);

/**
 * Create a new thread for the given function.
 *
 * \param thread [IN/OUT]       pointer to thread object
 * \param f [IN]                pointer to function
 * \param data [IN]             pointer to data than be passed to function f
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_create(hg_thread_t *thread, hg_thread_func_t f, void *data);

/**
 * Ends the calling thread.
 *
 * \param ret [IN]              exit code for the thread
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC void hg_thread_exit(hg_thread_ret_t ret);

/**
 * Wait for thread completion.
 *
 * \param thread [IN]           thread object
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_join(hg_thread_t thread);

/**
 * Terminate the thread.
 *
 * \param thread [IN]           thread object
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_cancel(hg_thread_t thread);

/**
 * Yield the processor.
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_yield(void);

/**
 * Obtain handle of the calling thread.
 *
 * \return
 */
static HG_UTIL_INLINE hg_thread_t hg_thread_self(void);

/**
 * Compare thread IDs.
 *
 * \return Non-zero if equal, zero if not equal
 */
static HG_UTIL_INLINE int hg_thread_equal(hg_thread_t t1, hg_thread_t t2);

/**
 * Create a thread-specific data key visible to all threads in the process.
 *
 * \param key [OUT]             pointer to thread key object
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_key_create(hg_thread_key_t *key);

/**
 * Delete a thread-specific data key previously returned by
 * hg_thread_key_create().
 *
 * \param key [IN]              thread key object
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_key_delete(hg_thread_key_t key);

/**
 * Get value from specified key.
 *
 * \param key [IN]              thread key object
 *
 * \return Pointer to data associated to the key
 */
static HG_UTIL_INLINE void *hg_thread_getspecific(hg_thread_key_t key);

/**
 * Set value to specified key.
 *
 * \param key [IN]              thread key object
 * \param value [IN]            pointer to data that will be associated
 *
 * \return Non-negative on success or negative on failure
 */
static HG_UTIL_INLINE int hg_thread_setspecific(hg_thread_key_t key, const void *value);

/**
 * Get affinity mask.
 *
 * \param thread [IN]           thread object
 * \param cpu_mask [IN/OUT]     cpu mask
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_getaffinity(hg_thread_t thread, hg_cpu_set_t *cpu_mask);

/**
 * Set affinity mask.
 *
 * \param thread [IN]           thread object
 * \param cpu_mask [IN]         cpu mask
 *
 * \return Non-negative on success or negative on failure
 */
HG_UTIL_PUBLIC int hg_thread_setaffinity(hg_thread_t thread, const hg_cpu_set_t *cpu_mask);

/*---------------------------------------------------------------------------*/
static HG_UTIL_INLINE hg_thread_t
hg_thread_self(void)
{
#ifdef _WIN32
    return GetCurrentThread();
#else
    return pthread_self();
#endif
}

/*---------------------------------------------------------------------------*/
static HG_UTIL_INLINE int
hg_thread_equal(hg_thread_t t1, hg_thread_t t2)
{
#ifdef _WIN32
    return GetThreadId(t1) == GetThreadId(t2);
#else
    return pthread_equal(t1, t2);
#endif
}

/*---------------------------------------------------------------------------*/
static HG_UTIL_INLINE void *
hg_thread_getspecific(hg_thread_key_t key)
{
#ifdef _WIN32
    return TlsGetValue(key);
#else
    return pthread_getspecific(key);
#endif
}

/*---------------------------------------------------------------------------*/
static HG_UTIL_INLINE int
hg_thread_setspecific(hg_thread_key_t key, const void *value)
{
#ifdef _WIN32
    if (!TlsSetValue(key, (LPVOID)value))
        return HG_UTIL_FAIL;
#else
    if (pthread_setspecific(key, value))
        return HG_UTIL_FAIL;
#endif

    return HG_UTIL_SUCCESS;
}

#ifdef __cplusplus
}
#endif

#endif /* MERCURY_THREAD_H */