First version
[3rdparty/ote_partner/tlk.git] / include / kernel / thread.h
1 /*
2  * Copyright (c) 2008-2012 Travis Geiselbrecht
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #ifndef __KERNEL_THREAD_H
24 #define __KERNEL_THREAD_H
25
26 #include <sys/types.h>
27 #include <list.h>
28 #include <compiler.h>
29 #include <arch/defines.h>
30 #include <arch/ops.h>
31 #include <arch/thread.h>
32 #include <platform.h>
33
34 enum thread_state {
35         THREAD_SUSPENDED = 0,
36         THREAD_READY,
37         THREAD_RUNNING,
38         THREAD_BLOCKED,
39         THREAD_SLEEPING,
40         THREAD_DEATH,
41 };
42
43 typedef int (*thread_start_routine)(void *arg);
44
45 /* thread local storage */
46 enum thread_tls_list {
47         MAX_TLS_ENTRY
48 };
49
50 #define THREAD_MAGIC 'thrd'
51
52 typedef struct thread {
53         int magic;
54         struct list_node thread_list_node;
55
56         /* active bits */
57         struct list_node queue_node;
58         struct list_node task_node;
59         int priority;
60         enum thread_state state;
61         int saved_critical_section_count;
62         int remaining_quantum;
63
64         /* if blocked, a pointer to the wait queue */
65         struct wait_queue *blocking_wait_queue;
66         status_t wait_queue_block_ret;
67
68         /* architecture stuff */
69         struct arch_thread arch;
70
71         /* stack stuff */
72         void *stack;
73         size_t stack_size;
74
75         /* entry point */
76         thread_start_routine entry;
77         void *arg;
78
79         /* return code */
80         int retcode;
81
82         /* thread local storage */
83         uint32_t tls[MAX_TLS_ENTRY];
84
85         char name[32];
86 } thread_t;
87
88 /* thread priority */
89 #define NUM_PRIORITIES 32
90 #define LOWEST_PRIORITY 0
91 #define HIGHEST_PRIORITY (NUM_PRIORITIES - 1)
92 #define DPC_PRIORITY (NUM_PRIORITIES - 2)
93 #define IDLE_PRIORITY LOWEST_PRIORITY
94 #define LOW_PRIORITY (NUM_PRIORITIES / 4)
95 #define DEFAULT_PRIORITY (NUM_PRIORITIES / 2)
96 #define HIGH_PRIORITY ((NUM_PRIORITIES / 4) * 3)
97
98 /* stack size */
99 #ifdef CUSTOM_DEFAULT_STACK_SIZE
100 #define DEFAULT_STACK_SIZE CUSTOM_DEFAULT_STACK_SIZE
101 #else
102 #define DEFAULT_STACK_SIZE ARCH_DEFAULT_STACK_SIZE
103 #endif
104
105 /* functions */
106 void thread_init_early(void);
107 void thread_init(void);
108 void thread_become_idle(void) __NO_RETURN;
109 void thread_set_name(const char *name);
110 void thread_set_priority(int priority);
111 thread_t *thread_create(const char *name, thread_start_routine entry, void *arg, int priority, size_t stack_size);
112 status_t thread_resume(thread_t *);
113 void thread_exit(int retcode) __NO_RETURN;
114 void thread_sleep(lk_time_t delay);
115 void thread_suspend();
116
117 void dump_thread(thread_t *t);
118 void dump_all_threads(void);
119
120 /* scheduler routines */
121 void thread_yield(void); /* give up the cpu voluntarily */
122 void thread_preempt(void); /* get preempted (inserted into head of run queue) */
123 void thread_block(void); /* block on something and reschedule */
124
125 /* called on every timer tick for the scheduler to do quantum expiration */
126 enum handler_return thread_timer_tick(void);
127
128 /* the current thread */
129 extern thread_t *current_thread;
130
131 /* the idle thread */
132 extern thread_t *idle_thread;
133
134 /* critical sections */
135 extern int critical_section_count;
136
137 static inline __ALWAYS_INLINE void enter_critical_section(void)
138 {
139         if (critical_section_count == 0)
140                 arch_disable_ints();
141         critical_section_count++;
142 }
143
144 static inline __ALWAYS_INLINE void exit_critical_section(void)
145 {
146         critical_section_count--;
147         if ((critical_section_count == 0) && platform_intr_ready())
148                 arch_enable_ints();
149 }
150
151 static inline __ALWAYS_INLINE bool in_critical_section(void)
152 {
153         return critical_section_count > 0;
154 }
155
156 /* only used by interrupt glue */
157 static inline void inc_critical_section(void) { critical_section_count++; }
158 static inline void dec_critical_section(void) { critical_section_count--; }
159
160 /* thread local storage */
161 static inline __ALWAYS_INLINE uint32_t tls_get(uint entry)
162 {
163         return current_thread->tls[entry];
164 }
165
166 static inline __ALWAYS_INLINE uint32_t tls_set(uint entry, uint32_t val)
167 {
168         uint32_t oldval = current_thread->tls[entry];
169         current_thread->tls[entry] = val;
170         return oldval;
171 }
172
173 /* wait queue stuff */
174 #define WAIT_QUEUE_MAGIC 'wait'
175
176 typedef struct wait_queue {
177         int magic;
178         struct list_node list;
179         int count;
180 } wait_queue_t;
181
182 /* wait queue primitive */
183 /* NOTE: must be inside critical section when using these */
184 void wait_queue_init(wait_queue_t *);
185
186 /*
187  * release all the threads on this wait queue with a return code of ERR_OBJECT_DESTROYED.
188  * the caller must assure that no other threads are operating on the wait queue during or
189  * after the call.
190  */
191 void wait_queue_destroy(wait_queue_t *, bool reschedule);
192
193 /*
194  * block on a wait queue.
195  * return status is whatever the caller of wait_queue_wake_*() specifies.
196  * a timeout other than INFINITE_TIME will set abort after the specified time
197  * and return ERR_TIMED_OUT. a timeout of 0 will immediately return.
198  */
199 status_t wait_queue_block(wait_queue_t *, lk_time_t timeout);
200
201 /*
202  * release one or more threads from the wait queue.
203  * reschedule = should the system reschedule if any is released.
204  * wait_queue_error = what wait_queue_block() should return for the blocking thread.
205  */
206 int wait_queue_wake_one(wait_queue_t *, bool reschedule, status_t wait_queue_error);
207 int wait_queue_wake_all(wait_queue_t *, bool reschedule, status_t wait_queue_error);
208
209 /*
210  * remove the thread from whatever wait queue it's in.
211  * return an error if the thread is not currently blocked (or is the current thread)
212  */
213 status_t thread_unblock_from_wait_queue(thread_t *t, bool reschedule, status_t wait_queue_error);
214
215 /* thread level statistics */
216 #if DEBUGLEVEL > 1
217 #define THREAD_STATS 1
218 #else
219 #define THREAD_STATS 0
220 #endif
221 #if THREAD_STATS
222 struct thread_stats {
223         lk_bigtime_t idle_time;
224         lk_bigtime_t last_idle_timestamp;
225         int reschedules;
226         int context_switches;
227         int preempts;
228         int yields;
229         int interrupts; /* platform code increment this */
230         int timer_ints; /* timer code increment this */
231         int timers; /* timer code increment this */
232 };
233
234 extern struct thread_stats thread_stats;
235
236 #define THREAD_STATS_INC(name) do { thread_stats.name++; } while(0)
237
238 #else
239
240 #define THREAD_STATS_INC(name) do { } while (0)
241
242 #endif
243
244 #endif
245