forked from mjansson/rpmalloc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
thread.c
101 lines (88 loc) · 1.74 KB
/
thread.c
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
#include <thread.h>
#include <errno.h>
#ifdef _MSC_VER
# define ATTRIBUTE_NORETURN
#else
# define ATTRIBUTE_NORETURN __attribute__((noreturn))
#endif
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wnonportable-system-include-path"
#endif
#ifdef _WIN32
# include <windows.h>
# include <process.h>
static unsigned __stdcall
thread_entry(void* argptr) {
thread_arg* arg = argptr;
arg->fn(arg->arg);
return 0;
}
#else
# include <time.h>
# include <pthread.h>
# include <sched.h>
static void*
thread_entry(void* argptr) {
thread_arg* arg = argptr;
arg->fn(arg->arg);
return 0;
}
#endif
uintptr_t
thread_run(thread_arg* arg) {
#ifdef _WIN32
return _beginthreadex(0, 0, thread_entry, arg, 0, 0);
#else
pthread_t id = 0;
int err = pthread_create(&id, 0, thread_entry, arg);
if (err)
return 0;
return (uintptr_t)id;
#endif
}
void ATTRIBUTE_NORETURN
thread_exit(uintptr_t value) {
#ifdef _WIN32
_endthreadex((unsigned)value);
#else
pthread_exit((void*)value);
#endif
}
uintptr_t
thread_join(uintptr_t handle) {
if (!handle)
return (uintptr_t)-1;
uintptr_t ret;
#ifdef _WIN32
DWORD exit_code = 0;
WaitForSingleObject((HANDLE)handle, INFINITE);
GetExitCodeThread((HANDLE)handle, &exit_code);
CloseHandle((HANDLE)handle);
ret = exit_code;
#else
void* result = 0;
pthread_join((pthread_t)handle, &result);
ret = (uintptr_t)result;
#endif
return ret;
}
void
thread_sleep(int milliseconds) {
#ifdef _WIN32
SleepEx((DWORD)milliseconds, 0);
#else
struct timespec ts, remaining;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (long)(milliseconds % 1000) * 1000000L;
while (nanosleep(&ts, &remaining) != 0 && errno == EINTR)
ts = remaining;
#endif
}
void
thread_yield(void) {
#ifdef _WIN32
SleepEx(0, 1);
#else
sched_yield();
#endif
}