176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef _THREAD_H 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define _THREAD_H 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stddef.h> 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <inttypes.h> 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <limits.h> 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdbool.h> 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <timer.h> 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/cpu.h> 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The idle thread runs at this priority */ 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IDLE_THREAD_PRIORITY INT_MAX 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* This priority should normally be used for hardware-polling threads */ 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define POLL_THREAD_PRIORITY (INT_MAX-1) 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct semaphore; 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct thread_list { 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread_list *next, *prev; 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Stack frame used by __switch_to, see thread_asm.S 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct thread_stack { 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int errno; 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint16_t rmsp, rmss; 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t edi, esi, ebp, ebx; 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void (*eip)(void); 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct thread_block { 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread_list list; 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread *thread; 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct semaphore *semaphore; 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mstime_t block_time; 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mstime_t timeout; 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bool timed_out; 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define THREAD_MAGIC 0x3568eb7d 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct thread { 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread_stack *esp; /* Must be first; stack pointer */ 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int thread_magic; 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *name; /* Name (for debugging) */ 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread_list list; 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread_block *blocked; 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void *stack, *rmstack; /* Stacks, iff allocated by malloc/lmalloc */ 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void *pvt; /* For the benefit of lwIP */ 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int prio; 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern void (*sched_hook_func)(void); 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid __thread_process_timeouts(void); 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid __schedule(void); 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid __switch_to(struct thread *); 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid thread_yield(void); 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern struct thread *__current; 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline struct thread *current(void) 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return __current; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct semaphore { 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int count; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct thread_list list; 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DECLARE_INIT_SEMAPHORE(sem, cnt) \ 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct semaphore sem = { \ 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .count = (cnt), \ 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .list = { \ 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .next = &sem.list, \ 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .prev = &sem.list \ 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } \ 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanmstime_t sem_down(struct semaphore *, mstime_t); 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid sem_up(struct semaphore *); 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid sem_init(struct semaphore *, int); 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This marks a semaphore object as unusable; it will remain unusable 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * until sem_init() is called on it again. This DOES NOT clear the 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * list of blocked processes on this semaphore! 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * It is also possible to mark the semaphore invalid by zeroing its 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * memory structure. 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline void sem_set_invalid(struct semaphore *sem) 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!!sem) 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sem->list.next = NULL; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Ask if a semaphore object has been initialized. 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline bool sem_is_valid(struct semaphore *sem) 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return ((!!sem) && (!!sem->list.next)); 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct thread *start_thread(const char *name, size_t stack_size, int prio, 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void (*start_func)(void *), void *func_arg); 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid __exit_thread(void); 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid kill_thread(struct thread *); 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid start_idle_thread(void); 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid test_thread(void); 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* _THREAD_H */ 117