1 #ifndef _THREAD_H
2 #define _THREAD_H
3
4 #include <stddef.h>
5 #include <inttypes.h>
6 #include <limits.h>
7 #include <stdbool.h>
8 #include <timer.h>
9 #include <sys/cpu.h>
10
11 /* The idle thread runs at this priority */
12 #define IDLE_THREAD_PRIORITY INT_MAX
13
14 /* This priority should normally be used for hardware-polling threads */
15 #define POLL_THREAD_PRIORITY (INT_MAX-1)
16
17 struct semaphore;
18
19 struct thread_list {
20 struct thread_list *next, *prev;
21 };
22
23 /*
24 * Stack frame used by __switch_to, see thread_asm.S
25 */
26 struct thread_stack {
27 int errno;
28 uint16_t rmsp, rmss;
29 uint32_t edi, esi, ebp, ebx;
30 void (*eip)(void);
31 };
32
33 struct thread_block {
34 struct thread_list list;
35 struct thread *thread;
36 struct semaphore *semaphore;
37 mstime_t block_time;
38 mstime_t timeout;
39 bool timed_out;
40 };
41
42 #define THREAD_MAGIC 0x3568eb7d
43
44 struct thread {
45 struct thread_stack *esp; /* Must be first; stack pointer */
46 unsigned int thread_magic;
47 const char *name; /* Name (for debugging) */
48 struct thread_list list;
49 struct thread_block *blocked;
50 void *stack, *rmstack; /* Stacks, iff allocated by malloc/lmalloc */
51 void *pvt; /* For the benefit of lwIP */
52 int prio;
53 };
54
55 extern void (*sched_hook_func)(void);
56
57 void __thread_process_timeouts(void);
58 void __schedule(void);
59 void __switch_to(struct thread *);
60 void thread_yield(void);
61
62 extern struct thread *__current;
current(void)63 static inline struct thread *current(void)
64 {
65 return __current;
66 }
67
68 struct semaphore {
69 int count;
70 struct thread_list list;
71 };
72
73 #define DECLARE_INIT_SEMAPHORE(sem, cnt) \
74 struct semaphore sem = { \
75 .count = (cnt), \
76 .list = { \
77 .next = &sem.list, \
78 .prev = &sem.list \
79 } \
80 }
81
82 mstime_t sem_down(struct semaphore *, mstime_t);
83 void sem_up(struct semaphore *);
84 void sem_init(struct semaphore *, int);
85
86 /*
87 * This marks a semaphore object as unusable; it will remain unusable
88 * until sem_init() is called on it again. This DOES NOT clear the
89 * list of blocked processes on this semaphore!
90 *
91 * It is also possible to mark the semaphore invalid by zeroing its
92 * memory structure.
93 */
sem_set_invalid(struct semaphore * sem)94 static inline void sem_set_invalid(struct semaphore *sem)
95 {
96 if (!!sem)
97 sem->list.next = NULL;
98 }
99
100 /*
101 * Ask if a semaphore object has been initialized.
102 */
sem_is_valid(struct semaphore * sem)103 static inline bool sem_is_valid(struct semaphore *sem)
104 {
105 return ((!!sem) && (!!sem->list.next));
106 }
107
108 struct thread *start_thread(const char *name, size_t stack_size, int prio,
109 void (*start_func)(void *), void *func_arg);
110 void __exit_thread(void);
111 void kill_thread(struct thread *);
112
113 void start_idle_thread(void);
114 void test_thread(void);
115
116 #endif /* _THREAD_H */
117