PatchworkOS  69292a3
A non-POSIX operating system.
Loading...
Searching...
No Matches
threading.c
Go to the documentation of this file.
1#include "threading.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 volatile _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{
54 thread->self = thread;
56 thread->id = 0;
57 thread->result = 0;
58 thread->err = EOK;
59 thread->func = NULL;
60 thread->arg = NULL;
61}
62
64{
65 for (uint64_t i = 0; i < _THREADS_MAX; i++)
66 {
67 atomic_init(&threads[i], NULL);
68 }
69 mtx_init(&entryMutex, mtx_recursive);
70
73
75
77}
78
79_NORETURN static void _thread_entry(_thread_t* thread)
80{
82
83 thrd_exit(thread->func(thread->arg));
84}
85
87{
88 _thread_t* thread = malloc(sizeof(_thread_t));
89 if (thread == NULL)
90 {
91 return NULL;
92 }
93
94 _thread_init(thread);
95 thread->func = func;
96 thread->arg = arg;
97
98 mtx_lock(&entryMutex);
99
100 thread->id = _syscall_thread_create(_thread_entry, thread);
101 if (thread->id == ERR)
102 {
104 mtx_unlock(&entryMutex);
105 free(thread);
106 return NULL;
107 }
108
109 if (_thread_insert(thread) == ERR)
110 {
111 errno = ENOSPC;
112 mtx_unlock(&entryMutex);
113 free(thread);
114 return NULL;
115 }
116 mtx_unlock(&entryMutex);
117
118 return thread;
119}
120
122{
123 _thread_remove(thread);
124 if (thread != &thread0)
125 {
126 free(thread);
127 }
128}
129
131{
132 uint64_t index = _thread_hash(id);
133 for (uint64_t i = 0; i < _THREADS_MAX; i++)
134 {
135 uint64_t probe = (index + i) % _THREADS_MAX;
136 _thread_t* thread = (_thread_t*)atomic_load_explicit(&threads[probe], memory_order_acquire);
137 if (thread == NULL)
138 {
139 return NULL;
140 }
141 if (thread->id == id)
142 {
143 return thread;
144 }
145 }
146 return NULL;
147}
void _threading_init(void)
Definition threading.c:63
_thread_t * _thread_new(thrd_start_t func, void *arg)
Definition threading.c:86
#define _THREAD_ATTACHED
Definition threading.h:29
_thread_t * _thread_get(tid_t id)
Definition threading.c:130
#define _THREADS_MAX
Definition threading.h:23
void _thread_free(_thread_t *thread)
Definition threading.c:121
#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
uint64_t arch_prctl(arch_prctl_t op, uintptr_t addr)
System call for setting architecture specific thread data.
Definition arch_prctl.c:6
@ ARCH_SET_FS
Set the FS base address.
Definition proc.h:349
#define NULL
Pointer error value.
Definition NULL.h:25
#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
@ 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
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
tid_t id
Definition threading.h:38
int result
Definition threading.h:39
errno_t err
Definition threading.h:40
atomic_uint64_t state
Definition threading.h:37
thrd_start_t func
Definition threading.h:41
_thread_t * self
Definition threading.h:36
void * arg
Definition threading.h:42
static tid_t _syscall_thread_create(void *entry, void *arg)
Definition syscalls.h:196
static tid_t _syscall_gettid(void)
Definition syscalls.h:116
static errno_t _syscall_errno(void)
Definition syscalls.h:106
static uint64_t _thread_insert(_thread_t *thread)
Definition threading.c:17
static _thread_t thread0
Definition threading.c:6
static void _thread_remove(_thread_t *thread)
Definition threading.c:33
static void _thread_init(_thread_t *thread)
Definition threading.c:52
static _NORETURN void _thread_entry(_thread_t *thread)
Definition threading.c:79
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