46
47
#include "private/thread.h"
48
#include "../include/thread.h"
49
#include "../include/fibril_synch.h"
48
51
#ifdef FUTEX_UPGRADABLE
63
fibril_mutex_t state_lock;
64
fibril_condvar_t state_condvar;
65
thread_retval_t retval;
70
static futex_t threads_protect = FUTEX_INITIALIZER;
71
static thread_internal_t **threads = NULL;
73
static void thread_del(thread_internal_t *thread);
75
static void thread_add(thread_internal_t *thread);
77
static thread_internal_t *thread_get(thread_id_t id);
79
static thread_internal_t *thread_alloc(void);
53
81
/** Main thread function.
105
132
* @return Zero on success or a code from @ref errno.h on failure.
107
int thread_create(void (* function)(void *), void *arg, const char *name,
134
int thread_create(void* (*function)(void *), void *arg, const char *name,
108
135
thread_id_t *tid)
111
(uspace_arg_t *) malloc(sizeof(uspace_arg_t));
137
thread_internal_t *thread = thread_alloc();
115
size_t stack_size = stack_size_get();
141
uspace_arg_t *uarg = &thread->arg;
144
size_t stack_size = stack_size_get();
116
145
void *stack = as_area_create(AS_AREA_ANY, stack_size,
117
146
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD |
118
147
AS_AREA_LATE_RESERVE);
132
162
uarg->uspace_uarg = uarg;
134
164
int rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg,
135
(sysarg_t) name, (sysarg_t) str_size(name), (sysarg_t) tid);
165
(sysarg_t) name, (sysarg_t) str_size(name), (sysarg_t) &thread->id);
139
171
* Failed to create a new thread.
140
172
* Free up the allocated data.
142
174
as_area_destroy(stack);
185
thread_internal_t *thread_alloc(void) {
186
thread_internal_t *thread = (thread_internal_t*)malloc(sizeof(thread_internal_t));
188
thread->state = THREAD_JOINABLE;
189
atomic_set(&thread->ref_count,1);
190
fibril_mutex_initialize(&thread->state_lock);
191
fibril_condvar_initialize(&thread->state_condvar);
196
void thread_add(thread_internal_t *thread)
198
futex_down(&threads_protect);
200
threads = malloc(sizeof(thread_internal_t*)* THREAD_MAX);
202
threads[thread->id] = thread;
203
fprintf(stdout, "Thread id: %"PRIu64" add to address:%p",thread->id,thread);
204
futex_up(&threads_protect);
207
thread_internal_t *thread_get(thread_id_t id)
209
thread_internal_t *ret;
210
futex_down(&threads_protect);
212
futex_up(&threads_protect);
216
void thread_del(thread_internal_t *thread)
218
futex_down(&threads_protect);
219
threads[thread->id] = NULL;
220
fprintf(stdout, "Thread id: %"PRIu64" with address:%p deleted.",thread->id,thread);
221
futex_up(&threads_protect);
224
static void thread_dealloc(thread_internal_t *thread)
226
if(atomic_predec(&thread->ref_count)){
229
//TODO dealloc thread
149
232
/** Terminate current thread.
151
234
* @param status Exit status. Currently not used.
154
void thread_exit(int status)
237
void thread_exit(thread_retval_t status)
156
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
239
thread_id_t id = thread_get_id();
240
fprintf(stdout, "Exit id:%"PRIu64"\n", id);
241
thread_internal_t *thread = thread_get(id);
242
fprintf(stdout, " of address:%p",thread);
243
fprintf(stdout, " and id:%"PRIu64"\n", thread->id);
245
fibril_mutex_lock(&thread->state_lock);
246
if(thread->state == THREAD_JOINABLE){
247
thread->state = THREAD_EXITED;
248
thread->retval = status;
249
fibril_condvar_broadcast(&thread->state_condvar);
251
fibril_mutex_unlock(&thread->state_lock);
254
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) 0);
158
257
/* Unreachable */
162
262
/** Detach thread.
164
264
* Currently not implemented.
179
279
* @return Thread exit status.
181
int thread_join(thread_id_t thread)
281
int thread_join(thread_id_t thread_id, thread_retval_t *retval)
283
fprintf(stdout, "Join to:%"PRIu64"\n", thread_id);
285
thread_internal_t *thread = thread_get(thread_id);
291
fibril_mutex_lock(&thread->state_lock);
292
fprintf(stdout, "*");
293
/* Rely on pthread_cond_wait being a cancellation point to make
294
pthread_join one too. */
295
while (thread->state == THREAD_JOINABLE){
296
fibril_condvar_wait(&thread->state_condvar,&thread->state_lock);
297
fprintf(stdout, "@");
301
switch (thread->state)
304
/* THREAD has already exited. Salvage its exit status. */
306
*retval = thread->retval;
308
fibril_mutex_unlock(&thread->state_lock);
310
thread_dealloc(thread);
314
/* Thou shalt not join non-joinable threads! */
315
fibril_mutex_unlock (&thread->state_lock);
320
fprintf(stderr, "Join end:%"PRIu64"\n", thread_id);
186
324
/** Get current thread ID.