1 #ifndef __LUNAIX_PROCESS_H
2 #define __LUNAIX_PROCESS_H
4 #include <lunaix/clock.h>
5 #include <lunaix/ds/waitq.h>
7 #include <lunaix/iopoll.h>
8 #include <lunaix/mm/mm.h>
9 #include <lunaix/mm/pagetable.h>
10 #include <lunaix/mm/region.h>
11 #include <lunaix/signal.h>
12 #include <lunaix/timer.h>
13 #include <lunaix/types.h>
14 #include <lunaix/spike.h>
15 #include <lunaix/hart_state.h>
16 #include <lunaix/usrscope.h>
18 #include <usr/lunaix/wait.h>
28 Group Dt: whether this process is terminated.
48 #define PS_GrBP (PS_PAUSED | PS_BLOCKED | PS_STOPPED)
49 #define PS_GrDT (PS_TERMNAT | PS_DESTROY)
50 #define PS_Rn (PS_RUNNING | PS_CREATED)
52 #define proc_terminated(proc) \
53 (!(proc) || ((proc)->state) & PS_GrDT)
54 #define proc_hanged(proc) \
55 ((proc) && ((proc)->state) & PS_BLOCKED)
56 #define proc_runnable(proc) \
57 ((proc) && (!(proc)->state || !(((proc)->state) & ~PS_Rn)))
60 #define TH_DETACHED 0b00000001
61 #define TH_STALLED 0b00000010
63 #define thread_detached(th) ((th)->flags & TH_DETACHED)
64 #define detach_thread(th) ((th)->flags |= TH_DETACHED)
66 #define thread_flags_set(th, flag) ((th)->flags |= (flag))
67 #define thread_flags_clear(th, flag) ((th)->flags &= ~(flag))
68 #define thread_flags_test(th, flag) ((th)->flags & (flag))
69 #define thread_flags_test_all(th, flag) (((th)->flags & (flag)) == (flag))
76 struct hart_state* saved_hstate;
77 } __attribute__((packed));
83 struct llist_header sleepers;
90 // number of times the thread entering kernel space involuntarily
91 unsigned long entry_count_invol;
92 // number of times the thread entering kernel space voluntarily
93 unsigned long entry_count_vol;
95 // number of times the thread is preempted in kerenl space
96 unsigned long kpreempt_count;
98 // timestamp of last time kernel entry
100 // timestamp of last time kernel reentry
103 // timestamp of last time kernel leave
105 // timestamp of last time the thread is resumed
119 Any change to *critical section*, including layout, size
120 must be reflected in arch/<arch>/interrupt.S.inc to avoid
125 struct hart_state* hstate;
127 }; // *critical section
139 ptr_t kstack; // process local kernel stack
140 struct mm_region* ustack; // process local user stack (NULL for kernel thread)
143 struct thread_stats stats;
147 struct proc_info* process;
148 struct llist_header proc_sibs; // sibling to process-local threads
149 struct llist_header sched_sibs; // sibling to scheduler (global) threads
150 struct sigctx sigctx;
156 // active thread, must be at the very beginning
157 struct thread* th_active;
159 struct llist_header threads;
162 struct llist_header tasks;
164 struct llist_header siblings;
165 struct llist_header children;
166 struct llist_header grp_member;
169 struct proc_info* parent;
179 struct user_scope uscope;
180 struct v_dnode* root;
187 struct sigregistry* sigreg;
188 struct v_fdtable* fdtable;
195 struct iopoll pollctx;
198 extern volatile struct proc_info* __current;
199 extern volatile struct thread* current_thread;
202 * @brief Check if current process belong to kernel itself
205 #define kernel_process(proc) (!(proc)->pid)
207 #define resume_thread(th) (th)->state = PS_READY
208 #define pause_thread(th) (th)->state = PS_PAUSED
209 #define block_thread(th) (th)->state = PS_BLOCKED
211 static inline void must_inline
212 set_current_executing(struct thread* thread)
214 current_thread = thread;
215 __current = thread->process;
218 static inline struct proc_mm*
219 vmspace(struct proc_info* proc)
221 return proc ? proc->mm : NULL;
225 vmroot(struct proc_info* proc)
227 return proc ? proc->mm->vmroot : 0;
230 static inline vm_regions_t*
231 vmregions(struct proc_info* proc)
233 return proc ? &proc->mm->regions : NULL;
237 static inline unsigned int
238 procvm_asid(struct proc_mm* mm)
240 return mm->proc->pid;
244 block_current_thread()
246 block_thread(current_thread);
250 pause_current_thread()
252 pause_thread(current_thread);
256 resume_current_thread()
258 resume_thread(current_thread);
261 static inline int syscall_result(int retval) {
262 return (current_thread->syscall_ret = retval);
266 * @brief Spawn a process with arbitary entry point.
267 * The inherit priviledge level is deduced automatically
268 * from the given entry point
270 * @param created returned created main thread
271 * @param entry entry point
272 * @param with_ustack whether to pre-allocate a user stack with it
276 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
279 * @brief Spawn a process that housing a given executable image as well as
280 * program argument and environment setting
282 * @param created returned created main thread
283 * @param path file system path to executable
284 * @param argv arguments passed to executable
285 * @param envp environment variables passed to executable
289 spawn_process_usr(struct thread** created, char* path,
290 const char** argv, const char** envp);
293 * @brief 分配并初始化一个进程控制块
295 * @return struct proc_info*
306 init_proc_user_space(struct proc_info* pcb);
309 * @brief 向系统发布一个进程,使其可以被调度。
314 commit_process(struct proc_info* process);
317 destroy_process(pid_t pid);
320 delete_process(struct proc_info* proc);
323 * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
330 * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
341 terminate_current(int exit_code);
344 terminate_proccess(struct proc_info* proc, int exit_code);
347 orphaned_proc(pid_t pid);
350 get_process(pid_t pid);
353 ========= Thread =========
357 commit_thread(struct thread* thread);
360 alloc_thread(struct proc_info* process);
363 destory_thread(struct thread* thread);
366 terminate_thread(struct thread* thread, ptr_t val);
369 terminate_current_thread(ptr_t val);
372 create_thread(struct proc_info* proc, bool with_ustack);
375 start_thread(struct thread* th, ptr_t entry);
378 spawn_kthread(ptr_t entry) {
379 assert(kernel_process(__current));
381 struct thread* th = create_thread(__current, false);
384 start_thread(th, entry);
389 exit_thread(void* val);
392 thread_release_mem(struct thread* thread);
395 ========= Signal =========
398 #define pending_sigs(thread) ((thread)->sigctx.sig_pending)
399 #define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig)
400 #define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)])
401 #define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact))
403 static inline struct sigact*
404 active_signal(struct thread* thread) {
405 struct sigctx* sigctx = &thread->sigctx;
406 struct sigregistry* sigreg = thread->process->sigreg;
407 return sigreg->signals[sigctx->sig_active];
411 sigactive_push(struct thread* thread, int active_sig) {
412 struct sigctx* sigctx = &thread->sigctx;
413 int prev_active = sigctx->sig_active;
415 assert(sigact_of(thread->process, active_sig));
417 sigctx->sig_order[active_sig] = prev_active;
418 sigctx->sig_active = active_sig;
422 sigactive_pop(struct thread* thread) {
423 struct sigctx* sigctx = &thread->sigctx;
424 int active_sig = sigctx->sig_active;
426 sigctx->sig_active = sigctx->sig_order[active_sig];
427 sigctx->sig_order[active_sig] = active_sig;
431 proc_setsignal(struct proc_info* proc, signum_t signum);
434 thread_setsignal(struct thread* thread, signum_t signum);
437 thread_stats_update(bool inbound, bool voluntary);
440 thread_stats_update_entering(bool voluntary)
442 thread_stats_update(true, voluntary);
446 thread_stats_update_leaving()
448 thread_stats_update(false, true);
452 thread_stats_update_kpreempt()
454 current_thread->stats.kpreempt_count++;
458 thread_stats_reset_kpreempt()
460 current_thread->stats.kpreempt_count = 0;
463 static inline ticks_t
464 thread_stats_kernel_elapse(struct thread* thread)
466 return clock_systime() - thread->stats.last_reentry;
469 static inline ticks_t
470 thread_stats_user_elapse(struct thread* thread)
472 struct thread_stats* stats;
473 stats = &thread->stats;
475 return stats->last_entry - stats->last_leave;
478 static inline struct user_scope*
481 return &__current->uscope;
484 static inline uid_t must_inline
487 return __current->euid;
490 static inline bool must_inline
493 return current_euid() == 0;
496 static inline gid_t must_inline
499 return __current->egid;
502 static inline void must_inline
503 current_set_egid(gid_t gid)
505 __current->egid = gid;
508 static inline void must_inline
509 current_set_euid(uid_t uid)
511 __current->euid = uid;
514 #endif /* __LUNAIX_PROCESS_H */