source: mainline/kernel/generic/include/proc/thread.h@ 8996582

Last change on this file since 8996582 was 5663872, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 18 months ago

Move stuff around for thread sleep

Only mark the thread as ready for wakeup after we switch to
another context. This way, soundness of the sychronization
does not depend on thread lock being held across the context
switch, which gives us more freedom.

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[f761f1eb]1/*
[ea7890e7]2 * Copyright (c) 2001-2007 Jakub Jermar
[f761f1eb]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[174156fd]29/** @addtogroup kernel_generic_proc
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[06e1e95]35#ifndef KERN_THREAD_H_
36#define KERN_THREAD_H_
[f761f1eb]37
[b3f8fb7]38#include <synch/waitq.h>
39#include <proc/task.h>
[831a04d0]40#include <time/timeout.h>
[b3f8fb7]41#include <cpu.h>
[ea7890e7]42#include <synch/spinlock.h>
[ef1eab7]43#include <adt/odict.h>
[f76fed4]44#include <mm/slab.h>
[b3f8fb7]45#include <arch/cpu.h>
46#include <mm/tlb.h>
[c0699467]47#include <abi/proc/uarg.h>
[9a1b20c]48#include <udebug/udebug.h>
[9ba415e]49#include <abi/proc/thread.h>
[c0699467]50#include <abi/sysinfo.h>
[1066041]51#include <arch.h>
52
[a6e55886]53#define THREAD CURRENT->thread
[f761f1eb]54
[da1bafb]55#define THREAD_NAME_BUFLEN 20
[f761f1eb]56
[a000878c]57extern const char *thread_states[];
[f761f1eb]58
[32fffef0]59/* Thread flags */
[6eef3c4]60typedef enum {
61 THREAD_FLAG_NONE = 0,
62 /** Thread executes in user space. */
63 THREAD_FLAG_USPACE = (1 << 0),
64 /** Thread will be attached by the caller. */
65 THREAD_FLAG_NOATTACH = (1 << 1),
66 /** Thread accounting doesn't affect accumulated task accounting. */
67 THREAD_FLAG_UNCOUNTED = (1 << 2)
68} thread_flags_t;
[f761f1eb]69
[4c60255]70/** Thread structure. There is one per thread. */
71typedef struct thread {
[1871118]72 atomic_refcount_t refcount;
73
[da1bafb]74 link_t rq_link; /**< Run queue link. */
75 link_t wq_link; /**< Wait queue link. */
76 link_t th_link; /**< Links to threads within containing task. */
[a35b458]77
[ef1eab7]78 /** Link to @c threads ordered dictionary. */
79 odlink_t lthreads;
[a35b458]80
[111b9b9]81 /** Tracking variable for thread_wait/thread_wakeup */
82 atomic_int sleep_state;
83
[1871118]84 /**
85 * If true, the thread is terminating.
86 * It will not go to sleep in interruptible synchronization functions
87 * and will call thread_exit() before returning to userspace.
88 */
89 volatile bool interrupted;
90
[111b9b9]91 /** Wait queue in which this thread sleeps. Used for debug printouts. */
92 _Atomic(waitq_t *) sleep_queue;
93
[1871118]94 /** Waitq for thread_join_timeout(). */
95 waitq_t join_wq;
96
[4c60255]97 /** Lock protecting thread structure.
98 *
[1871118]99 * Protects the whole thread structure except fields listed above.
[4c60255]100 */
[da1bafb]101 IRQ_SPINLOCK_DECLARE(lock);
[a35b458]102
[4c60255]103 char name[THREAD_NAME_BUFLEN];
[a35b458]104
[80bcaed]105 /** Function implementing the thread. */
[df58e44]106 void (*thread_code)(void *);
[80bcaed]107 /** Argument passed to thread_code() function. */
108 void *thread_arg;
[a35b458]109
[80bcaed]110 /**
[df58e44]111 * From here, the stored context is restored
112 * when the thread is scheduled.
[80bcaed]113 */
[4c60255]114 context_t saved_context;
[c030818]115 ipl_t saved_ipl;
[a35b458]116
[80bcaed]117 /**
118 * True if this thread is executing copy_from_uspace().
119 * False otherwise.
120 */
[4c60255]121 bool in_copy_from_uspace;
[a35b458]122
[80bcaed]123 /**
124 * True if this thread is executing copy_to_uspace().
125 * False otherwise.
126 */
[4c60255]127 bool in_copy_to_uspace;
[a35b458]128
[0366d09d]129#ifdef CONFIG_FPU
130 fpu_context_t fpu_context;
131#endif
[6eef3c4]132 bool fpu_context_exists;
[a35b458]133
[43ac0cc]134 /* The thread will not be migrated if nomigrate is non-zero. */
[6eef3c4]135 unsigned int nomigrate;
[a35b458]136
[6eef3c4]137 /** Thread state. */
[80bcaed]138 state_t state;
[a35b458]139
[6eef3c4]140 /** Thread CPU. */
[80bcaed]141 cpu_t *cpu;
142 /** Containing task. */
143 task_t *task;
[6eef3c4]144 /** Thread was migrated to another CPU and has not run yet. */
145 bool stolen;
146 /** Thread is executed in user space. */
147 bool uspace;
[a35b458]148
[80bcaed]149 /** Thread accounting. */
[a2a00e8]150 uint64_t ucycles;
151 uint64_t kcycles;
[80bcaed]152 /** Last sampled cycle. */
153 uint64_t last_cycle;
[da1bafb]154 /** Thread doesn't affect accumulated accounting. */
[80bcaed]155 bool uncounted;
[a35b458]156
[80bcaed]157 /** Thread's priority. Implemented as index to CPU->rq */
158 int priority;
159 /** Thread ID. */
[201abde]160 thread_id_t tid;
[8a64e81e]161
[80bcaed]162 /** Architecture-specific data. */
163 thread_arch_t arch;
[a35b458]164
[80bcaed]165 /** Thread's kernel stack. */
166 uint8_t *kstack;
[a35b458]167
[9a1b20c]168#ifdef CONFIG_UDEBUG
[5b7a107]169 /**
170 * If true, the scheduler will print a stack trace
171 * to the kernel console upon scheduling this thread.
172 */
173 bool btrace;
[a35b458]174
[9a1b20c]175 /** Debugging stuff */
176 udebug_thread_t udebug;
[da1bafb]177#endif /* CONFIG_UDEBUG */
[4c60255]178} thread_t;
179
[da1bafb]180IRQ_SPINLOCK_EXTERN(threads_lock);
[ef1eab7]181extern odict_t threads;
[f761f1eb]182
183extern void thread_init(void);
[da1bafb]184extern thread_t *thread_create(void (*)(void *), void *, task_t *,
[6eef3c4]185 thread_flags_t, const char *);
186extern void thread_wire(thread_t *, cpu_t *);
[d52b82ad]187extern void thread_attach(thread_t *, task_t *);
188extern void thread_ready(thread_t *);
[874621f]189extern void thread_exit(void) __attribute__((noreturn));
[111b9b9]190extern void thread_interrupt(thread_t *);
191
[5663872]192enum sleep_state {
193 SLEEP_INITIAL,
194 SLEEP_ASLEEP,
195 SLEEP_WOKE,
196};
197
[111b9b9]198typedef enum {
199 THREAD_OK,
200 THREAD_TERMINATING,
201} thread_termination_state_t;
202
203typedef enum {
204 THREAD_WAIT_SUCCESS,
205 THREAD_WAIT_TIMEOUT,
206} thread_wait_result_t;
207
208extern thread_termination_state_t thread_wait_start(void);
209extern thread_wait_result_t thread_wait_finish(deadline_t);
210extern void thread_wakeup(thread_t *);
[f761f1eb]211
[1871118]212static inline thread_t *thread_ref(thread_t *thread)
213{
214 refcount_up(&thread->refcount);
215 return thread;
216}
217
218static inline thread_t *thread_try_ref(thread_t *thread)
219{
220 if (refcount_try_up(&thread->refcount))
221 return thread;
222 else
223 return NULL;
224}
225
226extern void thread_put(thread_t *);
227
[3fa424a9]228#ifndef thread_create_arch
[deacd722]229extern errno_t thread_create_arch(thread_t *, thread_flags_t);
[3fa424a9]230#endif
[da1bafb]231
[32fffef0]232#ifndef thr_constructor_arch
[d52b82ad]233extern void thr_constructor_arch(thread_t *);
[32fffef0]234#endif
[da1bafb]235
[32fffef0]236#ifndef thr_destructor_arch
[d52b82ad]237extern void thr_destructor_arch(thread_t *);
[32fffef0]238#endif
[3fa424a9]239
[d52b82ad]240extern void thread_sleep(uint32_t);
241extern void thread_usleep(uint32_t);
[f761f1eb]242
[5110d0a]243extern errno_t thread_join(thread_t *);
[b7fd2a0]244extern errno_t thread_join_timeout(thread_t *, uint32_t, unsigned int);
[fe19611]245
[48dcc69]246extern void thread_print_list(bool);
[e1b6742]247extern thread_t *thread_find_by_id(thread_id_t);
[aab5e46]248extern size_t thread_count(void);
249extern thread_t *thread_first(void);
250extern thread_t *thread_next(thread_t *);
[a2a00e8]251extern void thread_update_accounting(bool);
[1871118]252extern thread_t *thread_try_get(thread_t *);
[f761f1eb]253
[43ac0cc]254extern void thread_migration_disable(void);
255extern void thread_migration_enable(void);
256
[5b7a107]257#ifdef CONFIG_UDEBUG
[df58e44]258extern void thread_stack_trace(thread_id_t);
[5b7a107]259#endif
[f761f1eb]260
[80bcaed]261/** Fpu context slab cache. */
[82d515e9]262extern slab_cache_t *fpu_context_cache;
[f76fed4]263
[80bcaed]264/* Thread syscall prototypes. */
[5a5269d]265extern sys_errno_t sys_thread_create(uspace_ptr_uspace_arg_t, uspace_ptr_char, size_t,
266 uspace_ptr_thread_id_t);
[b7fd2a0]267extern sys_errno_t sys_thread_exit(int);
[5a5269d]268extern sys_errno_t sys_thread_get_id(uspace_ptr_thread_id_t);
[b7fd2a0]269extern sys_errno_t sys_thread_usleep(uint32_t);
270extern sys_errno_t sys_thread_udelay(uint32_t);
[9f52563]271
[f761f1eb]272#endif
[b45c443]273
[764c302]274/** @}
[b45c443]275 */
Note: See TracBrowser for help on using the repository browser.