#ifndef _THREAD_H
#define _THREAD_H
#include <stddef.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <timer.h>
#include <sys/cpu.h>
/* The idle thread runs at this priority */
#define IDLE_THREAD_PRIORITY INT_MAX
/* This priority should normally be used for hardware-polling threads */
#define POLL_THREAD_PRIORITY (INT_MAX-1)
struct semaphore;
struct thread_list {
struct thread_list *next, *prev;
};
/*
* Stack frame used by __switch_to, see thread_asm.S
*/
struct thread_stack {
int errno;
uint16_t rmsp, rmss;
uint32_t edi, esi, ebp, ebx;
void (*eip)(void);
};
struct thread_block {
struct thread_list list;
struct thread *thread;
struct semaphore *semaphore;
mstime_t block_time;
mstime_t timeout;
bool timed_out;
};
#define THREAD_MAGIC 0x3568eb7d
struct thread {
struct thread_stack *esp; /* Must be first; stack pointer */
unsigned int thread_magic;
const char *name; /* Name (for debugging) */
struct thread_list list;
struct thread_block *blocked;
void *stack, *rmstack; /* Stacks, iff allocated by malloc/lmalloc */
void *pvt; /* For the benefit of lwIP */
int prio;
};
extern void (*sched_hook_func)(void);
void __thread_process_timeouts(void);
void __schedule(void);
void __switch_to(struct thread *);
void thread_yield(void);
extern struct thread *__current;
static inline struct thread *current(void)
{
return __current;
}
struct semaphore {
int count;
struct thread_list list;
};
#define DECLARE_INIT_SEMAPHORE(sem, cnt) \
struct semaphore sem = { \
.count = (cnt), \
.list = { \
.next = &sem.list, \
.prev = &sem.list \
} \
}
mstime_t sem_down(struct semaphore *, mstime_t);
void sem_up(struct semaphore *);
void sem_init(struct semaphore *, int);
/*
* This marks a semaphore object as unusable; it will remain unusable
* until sem_init() is called on it again. This DOES NOT clear the
* list of blocked processes on this semaphore!
*
* It is also possible to mark the semaphore invalid by zeroing its
* memory structure.
*/
static inline void sem_set_invalid(struct semaphore *sem)
{
if (!!sem)
sem->list.next = NULL;
}
/*
* Ask if a semaphore object has been initialized.
*/
static inline bool sem_is_valid(struct semaphore *sem)
{
return ((!!sem) && (!!sem->list.next));
}
struct thread *start_thread(const char *name, size_t stack_size, int prio,
void (*start_func)(void *), void *func_arg);
void __exit_thread(void);
void kill_thread(struct thread *);
void start_idle_thread(void);
void test_thread(void);
#endif /* _THREAD_H */