Greg Hartman | 76d05dc | 2016-11-23 15:51:27 -0800 | [diff] [blame] | 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; |
| 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 | */ |
| 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 | */ |
| 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 */ |