#pragma once struct thread; #include "cpu_context.h" #include "mem.h" #include "process.h" #include "wait.h" #define THREAD_NAME_MAX_LENGTH 32 #define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE typedef enum { RUNNING, READY, SLEEPING, WAITING, EXITING } thread_state; typedef unsigned long int thread_id_t; struct thread { char name[THREAD_NAME_MAX_LENGTH]; thread_id_t tid; struct cpu_state *cpuState; thread_state state; vaddr_t stackAddr; size_t stackSize; unsigned long jiffiesSleeping; int sleepHaveTimeouted; struct thread *next, *prev; struct thread *timeNext, *timePrev; // For User thread only struct thread *nextInProcess, *prevInProcess; struct process *process; struct wait_queue *wqExit; // This will be signaled at thread exit (user only) /** * Address space currently "squatted" by the thread, or used to be * active when the thread was interrupted/preempted. This is the MMU * configuration expected before the cpu_state of the thread is * restored on CPU. * - For kernel threads: should normally be NULL, meaning that the * thread will squat the current mm_context currently set in the * MMU. Might be NON NULL when a kernel thread squats a given * process to manipulate its address space. * - For user threads: should normally be NULL. More precisely: * - in user mode: the thread->process.mm_context is ALWAYS * set on MMU. squatted_mm_context is ALWAYS NULL in this * situation, meaning that the thread in user mode uses its * process-space as expected * - in kernel mode: NULL means that we keep on using the * mm_context currently set on MMU, which might be the * mm_context of another process. This is natural since a * thread in kernel mode normally only uses data in kernel * space. BTW, this limits the number of TLB flushes. However, * there are exceptions where this squatted_mm_context will * NOT be NULL. One is the copy_from/to_user API, which can * force the effective mm_context so that the MMU will be * (re)configured upon every context to the thread to match * the squatted_mm_context. Another exception is when a parent * thread creates the address space of a child process, in * which case the parent thread might temporarilly decide to * switch to the child's process space. * * This is the SOS/matos implementation of the Linux "Lazy TLB" and * address-space loaning. */ struct mmu_context *squattedContext; }; int threadSetup(vaddr_t mainStack, size_t mainStackSize); void threadExit(); struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, void *args); struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t startPc, uint32_t arg1, uint32_t arg2, uaddr_t startSP); void threadDelete(struct thread *thread); struct thread *threadSelectNext(); struct cpu_state *threadSwitch(struct cpu_state *prevCpu); int threadYield(); int threadWait(struct thread *current, struct thread *next, unsigned long msec); int threadUnsched(struct thread *th); int threadMsleep(unsigned long msec); int threadUsleep(unsigned long usec); int threadOnJieffiesTick(); struct thread *getCurrentThread(); int threadAddThread(struct thread *th); int threadChangeCurrentContext(struct mmu_context *ctx); int threadCount(); thread_id_t threadGetId(struct thread *th);