X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/aa2843fdbdd9b5cc579d198fd1a9ec874642706e..b60166b327a9108b07e3069fa6568a451529ffd9:/lunaix-os/includes/lunaix/process.h diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 10dc5ec..78756de 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -4,21 +4,22 @@ #include #include #include +#include #include +#include #include #include #include #include +#include +#include #include -#include -// 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。 -#define KERNEL_PID -1 /* - |C|Bk|De|Tn|Pu|Rn| - \----/ - Dt + |C|Sp|Bk|De|Tn|Pu|Rn| + \----/ + Dt Group Dt: whether this process is terminated. @@ -27,6 +28,7 @@ De: Destoryed Pu: Paused Bk: Blocked + Sp: Stopped C : Created */ @@ -36,31 +38,22 @@ #define PS_DESTROY 4 #define PS_PAUSED 8 #define PS_BLOCKED 16 -#define PS_CREATED 32 +#define PS_STOPPED 32 +#define PS_CREATED 64 -#define PS_GrBP (PS_PAUSED | PS_BLOCKED) +#define PS_GrBP (PS_PAUSED | PS_BLOCKED | PS_STOPPED) #define PS_GrDT (PS_TERMNAT | PS_DESTROY) +#define PS_Rn (PS_RUNNING | PS_CREATED) #define proc_terminated(proc) (((proc)->state) & PS_GrDT) #define proc_hanged(proc) (((proc)->state) & PS_BLOCKED) -#define proc_runnable(proc) (((proc)->state) & PS_PAUSED) +#define proc_runnable(proc) (!(proc)->state || !(((proc)->state) & ~PS_Rn)) -struct sigact -{ - struct sigact* prev; - sigset_t sa_mask; - void* sa_actor; - void* sa_handler; - pid_t sender; -}; -struct sighail -{ - sigset_t sig_pending; - sigset_t sig_mask; - struct sigact* inprogress; - struct sigact signals[_SIG_NUM]; -}; +#define TH_DETACHED 0b0001 + +#define thread_detached(th) ((th)->flags & TH_DETACHED) +#define detach_thread(th) ((th)->flags |= TH_DETACHED) struct proc_sig { @@ -70,68 +63,174 @@ struct proc_sig isr_param* saved_ictx; } __attribute__((packed)); -struct proc_info + +struct proc_info; + +struct haybed { + struct llist_header sleepers; + time_t wakeup_time; + time_t alarm_time; +}; + +struct thread { /* Any change to *critical section*, including layout, size must be reflected in arch/i386/interrupt.S.inc to avoid disaster! */ + struct + { + isr_param* intr_ctx; + ptr_t ustack_top; + }; // *critical section + + struct { + tid_t tid; + time_t created; + int state; + int syscall_ret; + ptr_t exit_val; + int flags; + }; + + struct { + ptr_t kstack; // process local kernel stack + struct mm_region* ustack; // process local user stack (NULL for kernel thread) + }; + + struct haybed sleep; + + struct proc_info* process; + struct llist_header proc_sibs; // sibling to process-local threads + struct llist_header sched_sibs; // sibling to scheduler (global) threads + struct sigctx sigctx; + waitq_t waitqueue; +}; - /* ---- critical section start ---- */ - - pid_t pid; - struct proc_info* parent; - isr_param* intr_ctx; - ptr_t ustack_top; - ptr_t page_table; +struct proc_info +{ + // active thread, must be at the very beginning + struct thread* th_active; - /* ---- critical section end ---- */ + struct llist_header threads; + int thread_count; struct llist_header tasks; + struct llist_header siblings; struct llist_header children; struct llist_header grp_member; - waitq_t waitqueue; - struct - { - struct llist_header sleepers; - time_t wakeup_time; - time_t alarm_time; - } sleep; - - struct proc_mm mm; - time_t created; - u8_t state; - int32_t exit_code; - int32_t k_status; - struct sighail sigctx; + struct { + struct proc_info* parent; + pid_t pid; + pid_t pgid; + time_t created; + + int state; + int exit_code; + }; + + struct proc_mm* mm; + struct sigregister* sigreg; struct v_fdtable* fdtable; struct v_dnode* cwd; - pid_t pgid; + struct { + char* cmd; + size_t cmd_len; + }; + + struct iopoll pollctx; }; extern volatile struct proc_info* __current; +extern volatile struct thread* current_thread; + +/** + * @brief Check if current process belong to kernel itself + * (pid=0) + */ +#define kernel_process(proc) (!(proc)->pid) + +#define resume_thread(th) (th)->state = PS_READY +#define pause_thread(th) (th)->state = PS_PAUSED +#define block_thread(th) (th)->state = PS_BLOCKED + +static inline void must_inline +set_current_executing(struct thread* thread) +{ + current_thread = thread; + __current = thread->process; +} + +static inline struct proc_mm* +vmspace(struct proc_info* proc) +{ + return proc->mm; +} + +static inline ptr_t +vmroot(struct proc_info* proc) +{ + return proc->mm->vmroot; +} + +static inline vm_regions_t* +vmregions(struct proc_info* proc) +{ + return &proc->mm->regions; +} static inline void -block_current() +block_current_thread() { - __current->state = PS_BLOCKED; + block_thread(current_thread); } static inline void -pause_current() +pause_current_thread() { - __current->state = PS_PAUSED; + pause_thread(current_thread); } static inline void -resume_current() +resume_current_thread() { - __current->state = PS_RUNNING; + resume_thread(current_thread); +} + +static inline int syscall_result(int retval) { + return (current_thread->syscall_ret = retval); } +/** + * @brief Spawn a process with arbitary entry point. + * The inherit priviledge level is deduced automatically + * from the given entry point + * + * @param created returned created main thread + * @param entry entry point + * @param with_ustack whether to pre-allocate a user stack with it + * @return int + */ +int +spawn_process(struct thread** created, ptr_t entry, bool with_ustack); + +/** + * @brief Spawn a process that housing a given executable image as well as + * program argument and environment setting + * + * @param created returned created main thread + * @param path file system path to executable + * @param argv arguments passed to executable + * @param envp environment variables passed to executable + * @return int + */ +int +spawn_process_usr(struct thread** created, char* path, + const char** argv, const char** envp); + /** * @brief 分配并初始化一个进程控制块 * @@ -159,8 +258,8 @@ commit_process(struct proc_info* process); pid_t destroy_process(pid_t pid); -void -copy_kernel_stack(struct proc_info* proc, ptr_t kstack_from); +void +delete_process(struct proc_info* proc); /** * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现) @@ -181,7 +280,10 @@ new_proc(); * */ void -terminate_proc(int exit_code); +terminate_current(int exit_code); + +void +terminate_proccess(struct proc_info* proc, int exit_code); int orphaned_proc(pid_t pid); @@ -189,24 +291,88 @@ orphaned_proc(pid_t pid); struct proc_info* get_process(pid_t pid); +/* + ========= Thread ========= +*/ + void -proc_setsignal(struct proc_info* proc, int signum); +commit_thread(struct thread* thread); + +struct thread* +alloc_thread(struct proc_info* process); void -proc_clear_signal(struct proc_info* proc); +destory_thread(ptr_t vm_mnt, struct thread* thread); -// enable interrupt upon transfer -#define TRANSFER_IE 1 +void +terminate_thread(struct thread* thread, ptr_t val); + +void +terminate_current_thread(ptr_t val); + +struct thread* +create_thread(struct proc_info* proc, ptr_t vm_mnt, bool with_ustack); + +void +start_thread(struct thread* th, ptr_t vm_mnt, ptr_t entry); + +static inline void +spawn_kthread(ptr_t entry) { + assert(kernel_process(__current)); + + struct thread* th = create_thread(__current, VMS_SELF, false); + + assert(th); + start_thread(th, VMS_SELF, entry); +} + +void +exit_thread(void* val); -/** - * @brief Setup process initial context, used to initiate first switch - * - * @param proc - * @param stop - * @param target - * @param flags - */ void -proc_init_transfer(struct proc_info* proc, ptr_t stop, ptr_t target, int flags); +thread_release_mem(struct thread* thread, ptr_t vm_mnt); + +/* + ========= Signal ========= +*/ + +#define pending_sigs(thread) ((thread)->sigctx.sig_pending) +#define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig) +#define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)]) +#define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact)) + +static inline struct sigact* +active_signal(struct thread* thread) { + struct sigctx* sigctx = &thread->sigctx; + struct sigregister* sigreg = thread->process->sigreg; + return sigreg->signals[sigctx->sig_active]; +} + +static inline void +sigactive_push(struct thread* thread, int active_sig) { + struct sigctx* sigctx = &thread->sigctx; + int prev_active = sigctx->sig_active; + + assert(sigact_of(thread->process, active_sig)); + + sigctx->sig_order[active_sig] = prev_active; + sigctx->sig_active = active_sig; +} + +static inline void +sigactive_pop(struct thread* thread) { + struct sigctx* sigctx = &thread->sigctx; + int active_sig = sigctx->sig_active; + + sigctx->sig_active = sigctx->sig_order[active_sig]; + sigctx->sig_order[active_sig] = active_sig; +} + +void +proc_setsignal(struct proc_info* proc, signum_t signum); + +void +thread_setsignal(struct thread* thread, signum_t signum); + #endif /* __LUNAIX_PROCESS_H */