tlk: 6/19 update
[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_kill(thread_t *thread);
115 void thread_sleep(lk_time_t delay);
116 void thread_suspend();
117
118 void dump_thread(thread_t *t);
119 void dump_all_threads(void);
120
121 /* scheduler routines */
122 void thread_yield(void); /* give up the cpu voluntarily */
123 void thread_preempt(void); /* get preempted (inserted into head of run queue) */
124 void thread_block(void); /* block on something and reschedule */
125
126 /* called on every timer tick for the scheduler to do quantum expiration */
127 enum handler_return thread_timer_tick(void);
128
129 /* the current thread */
130 extern thread_t *current_thread;
131
132 /* the idle thread */
133 extern thread_t *idle_thread;
134
135 /* critical sections */
136 extern int critical_section_count;
137
138 static inline __ALWAYS_INLINE void enter_critical_section(void)
139 {
140         if (critical_section_count == 0)
141                 arch_disable_ints();
142         critical_section_count++;
143 }
144
145 static inline __ALWAYS_INLINE void exit_critical_section(void)
146 {
147         critical_section_count--;
148         if (critical_section_count == 0)
149                 arch_enable_ints();
150 }
151
152 static inline __ALWAYS_INLINE bool in_critical_section(void)
153 {
154         return critical_section_count > 0;
155 }
156
157 /* only used by interrupt glue */
158 static inline void inc_critical_section(void) { critical_section_count++; }
159 static inline void dec_critical_section(void) { critical_section_count--; }
160
161 /* thread local storage */
162 static inline __ALWAYS_INLINE uint32_t tls_get(uint entry)
163 {
164         return current_thread->tls[entry];
165 }
166
167 static inline __ALWAYS_INLINE uint32_t tls_set(uint entry, uint32_t val)
168 {
169         uint32_t oldval = current_thread->tls[entry];
170         current_thread->tls[entry] = val;
171         return oldval;
172 }
173
174 /* wait queue stuff */
175 #define WAIT_QUEUE_MAGIC 'wait'
176
177 typedef struct wait_queue {
178         int magic;
179         struct list_node list;
180         int count;
181 } wait_queue_t;
182
183 /* wait queue primitive */
184 /* NOTE: must be inside critical section when using these */
185 void wait_queue_init(wait_queue_t *);
186
187 /*
188  * release all the threads on this wait queue with a return code of ERR_OBJECT_DESTROYED.
189  * the caller must assure that no other threads are operating on the wait queue during or
190  * after the call.
191  */
192 void wait_queue_destroy(wait_queue_t *, bool reschedule);
193
194 /*
195  * block on a wait queue.
196  * return status is whatever the caller of wait_queue_wake_*() specifies.
197  * a timeout other than INFINITE_TIME will set abort after the specified time
198  * and return ERR_TIMED_OUT. a timeout of 0 will immediately return.
199  */
200 status_t wait_queue_block(wait_queue_t *, lk_time_t timeout);
201
202 /*
203  * release one or more threads from the wait queue.
204  * reschedule = should the system reschedule if any is released.
205  * wait_queue_error = what wait_queue_block() should return for the blocking thread.
206  */
207 int wait_queue_wake_one(wait_queue_t *, bool reschedule, status_t wait_queue_error);
208 int wait_queue_wake_all(wait_queue_t *, bool reschedule, status_t wait_queue_error);
209
210 /*
211  * remove the thread from whatever wait queue it's in.
212  * return an error if the thread is not currently blocked (or is the current thread)
213  */
214 status_t thread_unblock_from_wait_queue(thread_t *t, bool reschedule, status_t wait_queue_error);
215
216 /* thread level statistics */
217 #if DEBUGLEVEL > 1
218 #define THREAD_STATS 1
219 #else
220 #define THREAD_STATS 0
221 #endif
222 #if THREAD_STATS
223 struct thread_stats {
224         lk_bigtime_t idle_time;
225         lk_bigtime_t last_idle_timestamp;
226         int reschedules;
227         int context_switches;
228         int preempts;
229         int yields;
230         int interrupts; /* platform code increment this */
231         int timer_ints; /* timer code increment this */
232         int timers; /* timer code increment this */
233 };
234
235 extern struct thread_stats thread_stats;
236
237 #define THREAD_STATS_INC(name) do { thread_stats.name++; } while(0)
238
239 #else
240
241 #define THREAD_STATS_INC(name) do { } while (0)
242
243 #endif
244
245 #endif
246