1/**
2 * \file
3 * \brief Threads.
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef LIBBARRELFISH_THREADS_H
16#define LIBBARRELFISH_THREADS_H
17
18#include <assert.h>
19#include <sys/cdefs.h>
20
21#include <barrelfish/caddr.h> // for struct capref.
22#include <barrelfish/thread_sync.h>
23#include <barrelfish_kpi/registers_arch.h>
24#include <barrelfish_kpi/dispatcher_handle.h>
25#include <errors/errno.h>
26#include <barrelfish/waitset.h>
27
28__BEGIN_DECLS
29
30typedef int (*thread_func_t)(void *);
31
32/// Default size of a thread's stack
33#define THREADS_DEFAULT_STACK_BYTES     (64 * 1024)
34
35struct thread *thread_create(thread_func_t start_func, void *data);
36struct thread *thread_create_varstack(thread_func_t start_func, void *arg,
37                                      size_t stacksize);
38void thread_yield(void);
39void thread_yield_dispatcher(struct capref endpoint);
40void thread_exit(int status);
41struct thread *thread_self(void);
42struct thread *thread_self_disabled(void);
43errval_t thread_join(struct thread *thread, int *retval);
44errval_t thread_detach(struct thread *thread);
45
46void thread_pause(struct thread *thread);
47void thread_pause_and_capture_state(struct thread *thread,
48                                    arch_registers_state_t **ret_regs);
49void thread_resume(struct thread *thread);
50
51void thread_mutex_init(struct thread_mutex *mutex);
52void thread_mutex_lock(struct thread_mutex *mutex);
53bool thread_mutex_trylock(struct thread_mutex *mutex);
54void thread_mutex_lock_nested(struct thread_mutex *mutex);
55void thread_mutex_unlock(struct thread_mutex *mutex);
56struct thread *thread_mutex_unlock_disabled(dispatcher_handle_t handle,
57                                            struct thread_mutex *mutex);
58
59void thread_cond_init(struct thread_cond *cond);
60void thread_cond_signal(struct thread_cond *cond);
61void thread_cond_broadcast(struct thread_cond *cond);
62void thread_cond_wait(struct thread_cond *cond, struct thread_mutex *mutex);
63
64void thread_sem_init(struct thread_sem *sem, unsigned int value);
65void thread_sem_wait(struct thread_sem *sem);
66bool thread_sem_trywait(struct thread_sem *sem);
67void thread_sem_post(struct thread_sem *sem);
68
69void thread_set_tls(void *);
70void *thread_get_tls(void);
71
72void thread_set_tls_key(int, void *);
73void *thread_get_tls_key(int);
74
75uintptr_t thread_id(void);
76uintptr_t thread_get_id(struct thread *t);
77void thread_set_id(uintptr_t id);
78
79uint32_t thread_set_token(struct waitset_chanstate *channel);
80void thread_clear_token(struct waitset_chanstate *channel);
81uint32_t thread_current_token(void);
82
83void thread_set_outgoing_token(uint32_t token);
84void thread_get_outgoing_token(uint32_t *token);
85
86/// Set/get a local trigger for currently processed event channel
87void thread_set_local_trigger(struct waitset_chanstate *trigger);
88struct waitset_chanstate * thread_get_local_trigger(void);
89
90struct flounder_rpc_context;
91
92void thread_set_rpc_in_progress(bool v);
93bool thread_get_rpc_in_progress(void);
94void thread_set_async_error(errval_t e);
95errval_t thread_get_async_error(void);
96
97void thread_store_recv_slot(struct capref recv_slot);
98struct capref thread_get_next_recv_slot(void);
99
100extern __thread thread_once_t thread_once_local_epoch;
101extern void thread_once_internal(thread_once_t *control, void (*func)(void));
102
103/**
104 * \brief Run a routine exactly once; use this for thread-safe initialization.
105 *
106 * \param control Control word - should be initialized with THREAD_ONCE_INIT.
107 * \param func Callback to be invoked.
108 */
109static inline void thread_once(thread_once_t *control, void (*func)(void)) {
110    assert(control != NULL);
111    assert(func != NULL);
112    thread_once_t x = *control; // unprotected access
113    if (x > thread_once_local_epoch) {
114        thread_once_internal(control, func);
115    }
116}
117
118/**
119 * \brief Set a thread's exit status.
120 *
121 * \param status The status.
122 */
123void thread_set_status(int status);
124
125__END_DECLS
126
127#endif  // LIBBARRELFISH_THREADS_H
128