1/* 2 * Copyright (c) 2009, 2010, 2012, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#ifndef LIBBARRELFISH_THREADS_PRIV_H 11#define LIBBARRELFISH_THREADS_PRIV_H 12 13#include <barrelfish/dispatcher_arch.h> 14#include <barrelfish/except.h> 15 16/// Maximum number of thread-local storage keys 17#define MAX_TLS 16 18 19/** \brief TLS dynamic thread vector data structure 20 * 21 * See: ELF handling for thread-local storage. Ulrich Drepper, Dec 2005. 22 * http://www.akkadia.org/drepper/tls.pdf 23 */ 24struct tls_dtv { 25 uintptr_t gen; ///< Generation count 26 void *dtv[0]; ///< Variable-length array of pointers to TLS blocks 27}; 28 29enum thread_state { 30 THREAD_STATE_NULL = 0, 31 THREAD_STATE_RUNNABLE, 32 THREAD_STATE_BLOCKED, 33 THREAD_STATE_EXITED 34}; 35 36/** \brief A thread of execution / thread control block (TCB) 37 * 38 * NB: on some ABIs (namely x86_{32,64}), the TLS blocks for initially-loaded 39 * (i.e. not dlopen()ed) modules _precede_ this structure in memory. Therefore 40 * it's not safe to directly malloc() or free() a thread structure. 41 */ 42struct thread { 43 /* XXX: The offsets of the first two fields (self pointer and dispatcher 44 * pointer) are depended upon by the ABI and/or assembly code. Don't change! 45 */ 46 struct thread *self; ///< Points to itself 47 dispatcher_handle_t disp; ///< Dispatcher affinity 48 struct tls_dtv *tls_dtv; ///< TLS thread vector 49 struct thread *next, *prev; ///< Next/prev threads in list 50 arch_registers_state_t regs __attribute__ ((aligned (16))); ///< Register state snapshot 51 void *stack; ///< Malloced stack area 52 void *stack_top; ///< Stack bounds 53 void *exception_stack; ///< Stack for exception handling 54 void *exception_stack_top; ///< Bounds of exception stack 55 exception_handler_fn exception_handler; ///< Exception handler, or NULL 56 void *userptr; ///< User's thread local pointer 57 void *userptrs[MAX_TLS]; ///< User's thread local pointers 58 uintptr_t yield_epoch; ///< Yield epoch 59 void *wakeup_reason; ///< Value returned from block() 60 coreid_t coreid; ///< XXX: Core ID affinity 61 int return_value; ///< Value returned on exit 62 struct thread_cond exit_condition; ///< Thread exit condition 63 struct thread_mutex exit_lock; ///< Protects exited state 64 enum thread_state state; ///< Thread state 65 bool paused; ///< Thread is paused (not runnable) 66 bool detached; ///< true if detached 67 bool joining; ///< true if someone is joining 68 bool in_exception; ///< true if running exception handler 69#if defined(__x86_64__) 70 uint16_t thread_seg_selector; ///< Segment selector for TCB 71#endif 72 void *slab; ///< Base of slab block containing this TCB 73 uintptr_t id; ///< User-defined thread identifier 74 75 uint32_t token_number; ///< RPC next token 76 uint32_t token; ///< Token to be received 77 struct waitset_chanstate *channel; ///< on right channel 78 79 bool rpc_in_progress; ///< RPC in progress 80 errval_t async_error; ///< RPC async error 81 uint32_t outgoing_token; ///< Token of outgoing message 82 struct waitset_chanstate *local_trigger; ///< Trigger for a local thread event 83}; 84 85void thread_enqueue(struct thread *thread, struct thread **queue); 86struct thread *thread_dequeue(struct thread **queue); 87void thread_remove_from_queue(struct thread **queue, struct thread *thread); 88 89/* must only be called by dispatcher, while disabled */ 90void thread_init_disabled(dispatcher_handle_t handle, bool init_domain); 91 92/// Returns true if there is non-threaded work to be done on this dispatcher 93/// (ie. if we still need to run) 94static inline bool havework_disabled(dispatcher_handle_t handle) 95{ 96 struct dispatcher_generic *disp = get_dispatcher_generic(handle); 97 return disp->runq != NULL 98#ifdef CONFIG_INTERCONNECT_DRIVER_LMP 99 || disp->lmp_send_events_list != NULL 100#endif 101 || disp->polled_channels != NULL 102 || disp->notificators != NULL 103 || disp->ump_send_events_list != NULL 104 ; 105} 106 107void *thread_block(struct thread **queue); 108void *thread_block_disabled(dispatcher_handle_t handle, struct thread **queue); 109void *thread_block_and_release_spinlock_disabled(dispatcher_handle_t handle, 110 struct thread **queue, 111 spinlock_t *spinlock); 112struct thread *thread_unblock_one(struct thread **queue, void *reason); 113struct thread *thread_unblock_one_disabled(dispatcher_handle_t handle, 114 struct thread **queue, void *reason); 115struct thread *thread_unblock_all_disabled(dispatcher_handle_t handle, 116 struct thread **queue, void *reason); 117 118struct thread *thread_create_unrunnable(thread_func_t start_func, void *arg, 119 size_t stacksize); 120 121void thread_init_remote(dispatcher_handle_t handle, struct thread *thread); 122void threads_prepare_to_span(dispatcher_handle_t newdh); 123 124void thread_run_disabled(dispatcher_handle_t handle); 125void thread_deliver_exception_disabled(dispatcher_handle_t handle, 126 enum exception_type type, int subtype, 127 void *addr, arch_registers_state_t *regs); 128 129#endif // LIBBARRELFISH_THREADS_PRIV_H 130