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>
24 Group Dt: whether this process is terminated.
44 #define PS_GrBP (PS_PAUSED | PS_BLOCKED | PS_STOPPED)
45 #define PS_GrDT (PS_TERMNAT | PS_DESTROY)
46 #define PS_Rn (PS_RUNNING | PS_CREATED)
48 #define proc_terminated(proc) (((proc)->state) & PS_GrDT)
49 #define proc_hanged(proc) (((proc)->state) & PS_BLOCKED)
50 #define proc_runnable(proc) (!(proc)->state || !(((proc)->state) & ~PS_Rn))
53 #define TH_DETACHED 0b00000001
54 #define TH_STALLED 0b00000010
56 #define thread_detached(th) ((th)->flags & TH_DETACHED)
57 #define detach_thread(th) ((th)->flags |= TH_DETACHED)
59 #define thread_flags_set(th, flag) ((th)->flags |= (flag))
60 #define thread_flags_clear(th, flag) ((th)->flags &= ~(flag))
61 #define thread_flags_test(th, flag) ((th)->flags & (flag))
62 #define thread_flags_test_all(th, flag) (((th)->flags & (flag)) == (flag))
69 struct hart_state* saved_hstate;
70 } __attribute__((packed));
76 struct llist_header sleepers;
83 // number of times the thread entering kernel space involuntarily
84 unsigned long entry_count_invol;
85 // number of times the thread entering kernel space voluntarily
86 unsigned long entry_count_vol;
88 // number of times the thread is preempted in kerenl space
89 unsigned long kpreempt_count;
91 // timestamp of last time kernel entry
93 // timestamp of last time kernel reentry
96 // timestamp of last time kernel leave
98 // timestamp of last time the thread is resumed
112 Any change to *critical section*, including layout, size
113 must be reflected in arch/x86/interrupt.S.inc to avoid
118 struct hart_state* hstate;
120 }; // *critical section
132 ptr_t kstack; // process local kernel stack
133 struct mm_region* ustack; // process local user stack (NULL for kernel thread)
136 struct thread_stats stats;
140 struct proc_info* process;
141 struct llist_header proc_sibs; // sibling to process-local threads
142 struct llist_header sched_sibs; // sibling to scheduler (global) threads
143 struct sigctx sigctx;
149 // active thread, must be at the very beginning
150 struct thread* th_active;
152 struct llist_header threads;
155 struct llist_header tasks;
157 struct llist_header siblings;
158 struct llist_header children;
159 struct llist_header grp_member;
162 struct proc_info* parent;
172 struct sigregistry* sigreg;
173 struct v_fdtable* fdtable;
180 struct iopoll pollctx;
183 extern volatile struct proc_info* __current;
184 extern volatile struct thread* current_thread;
187 * @brief Check if current process belong to kernel itself
190 #define kernel_process(proc) (!(proc)->pid)
192 #define resume_thread(th) (th)->state = PS_READY
193 #define pause_thread(th) (th)->state = PS_PAUSED
194 #define block_thread(th) (th)->state = PS_BLOCKED
196 static inline void must_inline
197 set_current_executing(struct thread* thread)
199 current_thread = thread;
200 __current = thread->process;
203 static inline struct proc_mm*
204 vmspace(struct proc_info* proc)
206 return proc ? proc->mm : NULL;
210 vmroot(struct proc_info* proc)
212 return proc ? proc->mm->vmroot : 0;
215 static inline vm_regions_t*
216 vmregions(struct proc_info* proc)
218 return proc ? &proc->mm->regions : NULL;
222 static inline unsigned int
223 procvm_asid(struct proc_mm* mm)
225 return mm->proc->pid;
229 block_current_thread()
231 block_thread(current_thread);
235 pause_current_thread()
237 pause_thread(current_thread);
241 resume_current_thread()
243 resume_thread(current_thread);
246 static inline int syscall_result(int retval) {
247 return (current_thread->syscall_ret = retval);
251 * @brief Spawn a process with arbitary entry point.
252 * The inherit priviledge level is deduced automatically
253 * from the given entry point
255 * @param created returned created main thread
256 * @param entry entry point
257 * @param with_ustack whether to pre-allocate a user stack with it
261 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
264 * @brief Spawn a process that housing a given executable image as well as
265 * program argument and environment setting
267 * @param created returned created main thread
268 * @param path file system path to executable
269 * @param argv arguments passed to executable
270 * @param envp environment variables passed to executable
274 spawn_process_usr(struct thread** created, char* path,
275 const char** argv, const char** envp);
278 * @brief 分配并初始化一个进程控制块
280 * @return struct proc_info*
291 init_proc_user_space(struct proc_info* pcb);
294 * @brief 向系统发布一个进程,使其可以被调度。
299 commit_process(struct proc_info* process);
302 destroy_process(pid_t pid);
305 delete_process(struct proc_info* proc);
308 * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
315 * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
326 terminate_current(int exit_code);
329 terminate_proccess(struct proc_info* proc, int exit_code);
332 orphaned_proc(pid_t pid);
335 get_process(pid_t pid);
338 ========= Thread =========
342 commit_thread(struct thread* thread);
345 alloc_thread(struct proc_info* process);
348 destory_thread(struct thread* thread);
351 terminate_thread(struct thread* thread, ptr_t val);
354 terminate_current_thread(ptr_t val);
357 create_thread(struct proc_info* proc, bool with_ustack);
360 start_thread(struct thread* th, ptr_t entry);
363 spawn_kthread(ptr_t entry) {
364 assert(kernel_process(__current));
366 struct thread* th = create_thread(__current, false);
369 start_thread(th, entry);
373 exit_thread(void* val);
376 thread_release_mem(struct thread* thread);
379 ========= Signal =========
382 #define pending_sigs(thread) ((thread)->sigctx.sig_pending)
383 #define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig)
384 #define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)])
385 #define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact))
387 static inline struct sigact*
388 active_signal(struct thread* thread) {
389 struct sigctx* sigctx = &thread->sigctx;
390 struct sigregistry* sigreg = thread->process->sigreg;
391 return sigreg->signals[sigctx->sig_active];
395 sigactive_push(struct thread* thread, int active_sig) {
396 struct sigctx* sigctx = &thread->sigctx;
397 int prev_active = sigctx->sig_active;
399 assert(sigact_of(thread->process, active_sig));
401 sigctx->sig_order[active_sig] = prev_active;
402 sigctx->sig_active = active_sig;
406 sigactive_pop(struct thread* thread) {
407 struct sigctx* sigctx = &thread->sigctx;
408 int active_sig = sigctx->sig_active;
410 sigctx->sig_active = sigctx->sig_order[active_sig];
411 sigctx->sig_order[active_sig] = active_sig;
415 proc_setsignal(struct proc_info* proc, signum_t signum);
418 thread_setsignal(struct thread* thread, signum_t signum);
421 thread_stats_update(bool inbound, bool voluntary);
424 thread_stats_update_entering(bool voluntary)
426 thread_stats_update(true, voluntary);
430 thread_stats_update_leaving()
432 thread_stats_update(false, true);
436 thread_stats_update_kpreempt()
438 current_thread->stats.kpreempt_count++;
442 thread_stats_reset_kpreempt()
444 current_thread->stats.kpreempt_count = 0;
447 static inline ticks_t
448 thread_stats_kernel_elapse(struct thread* thread)
450 return clock_systime() - thread->stats.last_reentry;
453 static inline ticks_t
454 thread_stats_user_elapse(struct thread* thread)
456 struct thread_stats* stats;
457 stats = &thread->stats;
459 return stats->last_entry - stats->last_leave;
463 #endif /* __LUNAIX_PROCESS_H */