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