PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
thread.c
Go to the documentation of this file.
1#include "thread.h"
2#include "syscalls.h"
3
4#include <stdlib.h>
5
7
8static _Atomic(_thread_t*) threads[_THREADS_MAX];
9
10static mtx_t entryMutex;
11
12static uint64_t _thread_hash(tid_t id)
13{
14 return id % _THREADS_MAX;
15}
16
18{
19 uint64_t index = _thread_hash(thread->id);
20 for (uint64_t i = 0; i < _THREADS_MAX; i++)
21 {
22 uint64_t probe = (index + i) % _THREADS_MAX;
23 _thread_t* expected = NULL;
24 if (atomic_compare_exchange_strong_explicit(&threads[probe], &expected, thread, memory_order_release,
26 {
27 return 0;
28 }
29 }
30 return ERR;
31}
32
33static void _thread_remove(_thread_t* thread)
34{
35 uint64_t index = _thread_hash(thread->id);
36 for (uint64_t i = 0; i < _THREADS_MAX; i++)
37 {
38 uint64_t probe = (index + i) % _THREADS_MAX;
39 _thread_t* current = (_thread_t*)atomic_load_explicit(&threads[probe], memory_order_acquire);
40 if (current == thread)
41 {
43 return;
44 }
45 if (current == NULL)
46 {
47 return;
48 }
49 }
50}
51
52static void _thread_init(_thread_t* thread)
53{
55 thread->id = 0;
56 thread->result = 0;
57 thread->err = EOK;
58 thread->func = NULL;
59 thread->arg = NULL;
60}
61
63{
64 for (uint64_t i = 0; i < _THREADS_MAX; i++)
65 {
66 atomic_init(&threads[i], NULL);
67 }
68 mtx_init(&entryMutex, mtx_recursive);
69
72
74}
75
76_NORETURN static void _thread_entry(_thread_t* thread)
77{
78 // Synchronize with creator
79 mtx_lock(&entryMutex);
80 mtx_unlock(&entryMutex);
81
82 thrd_exit(thread->func(thread->arg));
83}
84
86{
87 _thread_t* thread = malloc(sizeof(_thread_t));
88 if (thread == NULL)
89 {
90 return NULL;
91 }
92
93 _thread_init(thread);
94 thread->func = func;
95 thread->arg = arg;
96
97 mtx_lock(&entryMutex);
98
99 thread->id = _syscall_thread_create(_thread_entry, thread);
100 if (thread->id == ERR)
101 {
103 mtx_unlock(&entryMutex);
104 free(thread);
105 return NULL;
106 }
107
108 if (_thread_insert(thread) == ERR)
109 {
110 errno = ENOSPC;
111 mtx_unlock(&entryMutex);
112 free(thread);
113 return NULL;
114 }
115 mtx_unlock(&entryMutex);
116
117 return thread;
118}
119
121{
122 _thread_remove(thread);
123 if (thread != &thread0)
124 {
125 free(thread);
126 }
127}
128
130{
131 uint64_t index = _thread_hash(id);
132 for (uint64_t i = 0; i < _THREADS_MAX; i++)
133 {
134 uint64_t probe = (index + i) % _THREADS_MAX;
135 _thread_t* thread = (_thread_t*)atomic_load_explicit(&threads[probe], memory_order_acquire);
136 if (thread == NULL)
137 {
138 return NULL;
139 }
140 if (thread->id == id)
141 {
142 return thread;
143 }
144 }
145 return NULL;
146}
#define ENOSPC
No space left on device.
Definition errno.h:172
#define errno
Error number variable.
Definition errno.h:27
#define EOK
No error.
Definition errno.h:32
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ tid_t
Thread Identifier.
Definition tid_t.h:12
#define _NORETURN
Definition config.h:28
static uint64_t _thread_insert(_thread_t *thread)
Definition thread.c:17
void _threading_init(void)
Definition thread.c:62
static _thread_t thread0
Definition thread.c:6
_thread_t * _thread_new(thrd_start_t func, void *arg)
Definition thread.c:85
static void _thread_remove(_thread_t *thread)
Definition thread.c:33
static void _thread_init(_thread_t *thread)
Definition thread.c:52
static _NORETURN void _thread_entry(_thread_t *thread)
Definition thread.c:76
_thread_t * _thread_get(tid_t id)
Definition thread.c:129
void _thread_free(_thread_t *thread)
Definition thread.c:120
#define _THREAD_ATTACHED
Definition thread.h:17
#define _THREADS_MAX
Definition thread.h:11
@ memory_order_release
Definition stdatomic.h:119
@ memory_order_relaxed
Definition stdatomic.h:116
@ memory_order_acquire
Definition stdatomic.h:118
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure)
Definition stdatomic.h:230
#define _Atomic(T)
Definition stdatomic.h:59
#define atomic_load_explicit(object, order)
Definition stdatomic.h:264
#define atomic_store_explicit(object, desired, order)
Definition stdatomic.h:265
#define atomic_init(obj, value)
Definition stdatomic.h:75
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
tid_t id
Definition thread.h:25
int result
Definition thread.h:26
errno_t err
Definition thread.h:27
atomic_uint64_t state
Definition thread.h:24
thrd_start_t func
Definition thread.h:28
void * arg
Definition thread.h:29
static tid_t _syscall_thread_create(void *entry, void *arg)
Definition syscalls.h:208
static tid_t _syscall_gettid(void)
Definition syscalls.h:123
static errno_t _syscall_errno(void)
Definition syscalls.h:113
int(* thrd_start_t)(void *)
Definition threads.h:60
_PUBLIC int mtx_lock(mtx_t *mtx)
Definition mtx_lock.c:11
_PUBLIC int mtx_init(mtx_t *mtx, int type)
Definition mtx_init.c:10
@ mtx_recursive
Definition threads.h:67
_PUBLIC int mtx_unlock(mtx_t *mtx)
Definition mtx_unlock.c:10
_PUBLIC _NORETURN void thrd_exit(int res)
Definition thrd_exit.c:11