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>
26 Group Dt: whether this process is terminated.
46 #define PS_GrBP (PS_PAUSED | PS_BLOCKED | PS_STOPPED)
47 #define PS_GrDT (PS_TERMNAT | PS_DESTROY)
48 #define PS_Rn (PS_RUNNING | PS_CREATED)
50 #define proc_terminated(proc) \
51 (!(proc) || ((proc)->state) & PS_GrDT)
52 #define proc_hanged(proc) \
53 ((proc) && ((proc)->state) & PS_BLOCKED)
54 #define proc_runnable(proc) \
55 ((proc) && (!(proc)->state || !(((proc)->state) & ~PS_Rn)))
58 #define TH_DETACHED 0b00000001
59 #define TH_STALLED 0b00000010
61 #define thread_detached(th) ((th)->flags & TH_DETACHED)
62 #define detach_thread(th) ((th)->flags |= TH_DETACHED)
64 #define thread_flags_set(th, flag) ((th)->flags |= (flag))
65 #define thread_flags_clear(th, flag) ((th)->flags &= ~(flag))
66 #define thread_flags_test(th, flag) ((th)->flags & (flag))
67 #define thread_flags_test_all(th, flag) (((th)->flags & (flag)) == (flag))
74 struct hart_state* saved_hstate;
75 } __attribute__((packed));
81 struct llist_header sleepers;
88 // number of times the thread entering kernel space involuntarily
89 unsigned long entry_count_invol;
90 // number of times the thread entering kernel space voluntarily
91 unsigned long entry_count_vol;
93 // number of times the thread is preempted in kerenl space
94 unsigned long kpreempt_count;
96 // timestamp of last time kernel entry
98 // timestamp of last time kernel reentry
101 // timestamp of last time kernel leave
103 // timestamp of last time the thread is resumed
117 Any change to *critical section*, including layout, size
118 must be reflected in arch/<arch>/interrupt.S.inc to avoid
123 struct hart_state* hstate;
125 }; // *critical section
137 ptr_t kstack; // process local kernel stack
138 struct mm_region* ustack; // process local user stack (NULL for kernel thread)
141 struct thread_stats stats;
145 struct proc_info* process;
146 struct llist_header proc_sibs; // sibling to process-local threads
147 struct llist_header sched_sibs; // sibling to scheduler (global) threads
148 struct sigctx sigctx;
154 // active thread, must be at the very beginning
155 struct thread* th_active;
157 struct llist_header threads;
160 struct llist_header tasks;
162 struct llist_header siblings;
163 struct llist_header children;
164 struct llist_header grp_member;
167 struct proc_info* parent;
177 struct user_scope uscope;
178 struct v_dnode* root;
185 struct sigregistry* sigreg;
186 struct v_fdtable* fdtable;
193 struct iopoll pollctx;
196 extern volatile struct proc_info* __current;
197 extern volatile struct thread* current_thread;
200 * @brief Check if current process belong to kernel itself
203 #define kernel_process(proc) (!(proc)->pid)
205 #define resume_thread(th) (th)->state = PS_READY
206 #define pause_thread(th) (th)->state = PS_PAUSED
207 #define block_thread(th) (th)->state = PS_BLOCKED
209 static inline void must_inline
210 set_current_executing(struct thread* thread)
212 current_thread = thread;
213 __current = thread->process;
216 static inline struct proc_mm*
217 vmspace(struct proc_info* proc)
219 return proc ? proc->mm : NULL;
223 vmroot(struct proc_info* proc)
225 return proc ? proc->mm->vmroot : 0;
228 static inline vm_regions_t*
229 vmregions(struct proc_info* proc)
231 return proc ? &proc->mm->regions : NULL;
235 static inline unsigned int
236 procvm_asid(struct proc_mm* mm)
238 return mm->proc->pid;
242 block_current_thread()
244 block_thread(current_thread);
248 pause_current_thread()
250 pause_thread(current_thread);
254 resume_current_thread()
256 resume_thread(current_thread);
259 static inline int syscall_result(int retval) {
260 return (current_thread->syscall_ret = retval);
264 * @brief Spawn a process with arbitary entry point.
265 * The inherit priviledge level is deduced automatically
266 * from the given entry point
268 * @param created returned created main thread
269 * @param entry entry point
270 * @param with_ustack whether to pre-allocate a user stack with it
274 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
277 * @brief Spawn a process that housing a given executable image as well as
278 * program argument and environment setting
280 * @param created returned created main thread
281 * @param path file system path to executable
282 * @param argv arguments passed to executable
283 * @param envp environment variables passed to executable
287 spawn_process_usr(struct thread** created, char* path,
288 const char** argv, const char** envp);
291 * @brief 分配并初始化一个进程控制块
293 * @return struct proc_info*
304 init_proc_user_space(struct proc_info* pcb);
307 * @brief 向系统发布一个进程,使其可以被调度。
312 commit_process(struct proc_info* process);
315 destroy_process(pid_t pid);
318 delete_process(struct proc_info* proc);
321 * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
328 * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
339 terminate_current(int exit_code);
342 terminate_proccess(struct proc_info* proc, int exit_code);
345 orphaned_proc(pid_t pid);
348 get_process(pid_t pid);
351 ========= Thread =========
355 commit_thread(struct thread* thread);
358 alloc_thread(struct proc_info* process);
361 destory_thread(struct thread* thread);
364 terminate_thread(struct thread* thread, ptr_t val);
367 terminate_current_thread(ptr_t val);
370 create_thread(struct proc_info* proc, bool with_ustack);
373 start_thread(struct thread* th, ptr_t entry);
376 spawn_kthread(ptr_t entry) {
377 assert(kernel_process(__current));
379 struct thread* th = create_thread(__current, false);
382 start_thread(th, entry);
387 exit_thread(void* val);
390 thread_release_mem(struct thread* thread);
393 ========= Signal =========
396 #define pending_sigs(thread) ((thread)->sigctx.sig_pending)
397 #define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig)
398 #define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)])
399 #define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact))
401 static inline struct sigact*
402 active_signal(struct thread* thread) {
403 struct sigctx* sigctx = &thread->sigctx;
404 struct sigregistry* sigreg = thread->process->sigreg;
405 return sigreg->signals[sigctx->sig_active];
409 sigactive_push(struct thread* thread, int active_sig) {
410 struct sigctx* sigctx = &thread->sigctx;
411 int prev_active = sigctx->sig_active;
413 assert(sigact_of(thread->process, active_sig));
415 sigctx->sig_order[active_sig] = prev_active;
416 sigctx->sig_active = active_sig;
420 sigactive_pop(struct thread* thread) {
421 struct sigctx* sigctx = &thread->sigctx;
422 int active_sig = sigctx->sig_active;
424 sigctx->sig_active = sigctx->sig_order[active_sig];
425 sigctx->sig_order[active_sig] = active_sig;
429 proc_setsignal(struct proc_info* proc, signum_t signum);
432 thread_setsignal(struct thread* thread, signum_t signum);
435 thread_stats_update(bool inbound, bool voluntary);
438 thread_stats_update_entering(bool voluntary)
440 thread_stats_update(true, voluntary);
444 thread_stats_update_leaving()
446 thread_stats_update(false, true);
450 thread_stats_update_kpreempt()
452 current_thread->stats.kpreempt_count++;
456 thread_stats_reset_kpreempt()
458 current_thread->stats.kpreempt_count = 0;
461 static inline ticks_t
462 thread_stats_kernel_elapse(struct thread* thread)
464 return clock_systime() - thread->stats.last_reentry;
467 static inline ticks_t
468 thread_stats_user_elapse(struct thread* thread)
470 struct thread_stats* stats;
471 stats = &thread->stats;
473 return stats->last_entry - stats->last_leave;
476 static inline struct user_scope*
479 return &__current->uscope;
482 static inline uid_t must_inline
485 return __current->euid;
488 static inline bool must_inline
491 return current_euid() == 0;
494 static inline gid_t must_inline
497 return __current->egid;
500 static inline void must_inline
501 current_set_egid(gid_t gid)
503 __current->egid = gid;
506 static inline void must_inline
507 current_set_euid(uid_t uid)
509 __current->euid = uid;
512 #endif /* __LUNAIX_PROCESS_H */