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
17struct semaphore;
18
19struct thread_list {
20    struct thread_list *next, *prev;
21};
22
23/*
24 * Stack frame used by __switch_to, see thread_asm.S
25 */
26struct thread_stack {
27    int errno;
28    uint16_t rmsp, rmss;
29    uint32_t edi, esi, ebp, ebx;
30    void (*eip)(void);
31};
32
33struct 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
44struct 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
55extern void (*sched_hook_func)(void);
56
57void __thread_process_timeouts(void);
58void __schedule(void);
59void __switch_to(struct thread *);
60void thread_yield(void);
61
62extern struct thread *__current;
63static inline struct thread *current(void)
64{
65    return __current;
66}
67
68struct 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
82mstime_t sem_down(struct semaphore *, mstime_t);
83void sem_up(struct semaphore *);
84void 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 */
94static 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 */
103static inline bool sem_is_valid(struct semaphore *sem)
104{
105    return ((!!sem) && (!!sem->list.next));
106}
107
108struct thread *start_thread(const char *name, size_t stack_size, int prio,
109			    void (*start_func)(void *), void *func_arg);
110void __exit_thread(void);
111void kill_thread(struct thread *);
112
113void start_idle_thread(void);
114void test_thread(void);
115
116#endif /* _THREAD_H */
117