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) \
49 (!(proc) || ((proc)->state) & PS_GrDT)
50 #define proc_hanged(proc) \
51 ((proc) && ((proc)->state) & PS_BLOCKED)
52 #define proc_runnable(proc) \
53 ((proc) && (!(proc)->state || !(((proc)->state) & ~PS_Rn)))
56 #define TH_DETACHED 0b00000001
57 #define TH_STALLED 0b00000010
59 #define thread_detached(th) ((th)->flags & TH_DETACHED)
60 #define detach_thread(th) ((th)->flags |= TH_DETACHED)
62 #define thread_flags_set(th, flag) ((th)->flags |= (flag))
63 #define thread_flags_clear(th, flag) ((th)->flags &= ~(flag))
64 #define thread_flags_test(th, flag) ((th)->flags & (flag))
65 #define thread_flags_test_all(th, flag) (((th)->flags & (flag)) == (flag))
72 struct hart_state* saved_hstate;
73 } __attribute__((packed));
79 struct llist_header sleepers;
86 // number of times the thread entering kernel space involuntarily
87 unsigned long entry_count_invol;
88 // number of times the thread entering kernel space voluntarily
89 unsigned long entry_count_vol;
91 // number of times the thread is preempted in kerenl space
92 unsigned long kpreempt_count;
94 // timestamp of last time kernel entry
96 // timestamp of last time kernel reentry
99 // timestamp of last time kernel leave
101 // timestamp of last time the thread is resumed
115 Any change to *critical section*, including layout, size
116 must be reflected in arch/x86/interrupt.S.inc to avoid
121 struct hart_state* hstate;
123 }; // *critical section
135 ptr_t kstack; // process local kernel stack
136 struct mm_region* ustack; // process local user stack (NULL for kernel thread)
139 struct thread_stats stats;
143 struct proc_info* process;
144 struct llist_header proc_sibs; // sibling to process-local threads
145 struct llist_header sched_sibs; // sibling to scheduler (global) threads
146 struct sigctx sigctx;
152 // active thread, must be at the very beginning
153 struct thread* th_active;
155 struct llist_header threads;
158 struct llist_header tasks;
160 struct llist_header siblings;
161 struct llist_header children;
162 struct llist_header grp_member;
165 struct proc_info* parent;
175 struct sigregistry* sigreg;
176 struct v_fdtable* fdtable;
183 struct iopoll pollctx;
186 extern volatile struct proc_info* __current;
187 extern volatile struct thread* current_thread;
190 * @brief Check if current process belong to kernel itself
193 #define kernel_process(proc) (!(proc)->pid)
195 #define resume_thread(th) (th)->state = PS_READY
196 #define pause_thread(th) (th)->state = PS_PAUSED
197 #define block_thread(th) (th)->state = PS_BLOCKED
199 static inline void must_inline
200 set_current_executing(struct thread* thread)
202 current_thread = thread;
203 __current = thread->process;
206 static inline struct proc_mm*
207 vmspace(struct proc_info* proc)
209 return proc ? proc->mm : NULL;
213 vmroot(struct proc_info* proc)
215 return proc ? proc->mm->vmroot : 0;
218 static inline vm_regions_t*
219 vmregions(struct proc_info* proc)
221 return proc ? &proc->mm->regions : NULL;
225 static inline unsigned int
226 procvm_asid(struct proc_mm* mm)
228 return mm->proc->pid;
232 block_current_thread()
234 block_thread(current_thread);
238 pause_current_thread()
240 pause_thread(current_thread);
244 resume_current_thread()
246 resume_thread(current_thread);
249 static inline int syscall_result(int retval) {
250 return (current_thread->syscall_ret = retval);
254 * @brief Spawn a process with arbitary entry point.
255 * The inherit priviledge level is deduced automatically
256 * from the given entry point
258 * @param created returned created main thread
259 * @param entry entry point
260 * @param with_ustack whether to pre-allocate a user stack with it
264 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
267 * @brief Spawn a process that housing a given executable image as well as
268 * program argument and environment setting
270 * @param created returned created main thread
271 * @param path file system path to executable
272 * @param argv arguments passed to executable
273 * @param envp environment variables passed to executable
277 spawn_process_usr(struct thread** created, char* path,
278 const char** argv, const char** envp);
281 * @brief 分配并初始化一个进程控制块
283 * @return struct proc_info*
294 init_proc_user_space(struct proc_info* pcb);
297 * @brief 向系统发布一个进程,使其可以被调度。
302 commit_process(struct proc_info* process);
305 destroy_process(pid_t pid);
308 delete_process(struct proc_info* proc);
311 * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
318 * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
329 terminate_current(int exit_code);
332 terminate_proccess(struct proc_info* proc, int exit_code);
335 orphaned_proc(pid_t pid);
338 get_process(pid_t pid);
341 ========= Thread =========
345 commit_thread(struct thread* thread);
348 alloc_thread(struct proc_info* process);
351 destory_thread(struct thread* thread);
354 terminate_thread(struct thread* thread, ptr_t val);
357 terminate_current_thread(ptr_t val);
360 create_thread(struct proc_info* proc, bool with_ustack);
363 start_thread(struct thread* th, ptr_t entry);
366 spawn_kthread(ptr_t entry) {
367 assert(kernel_process(__current));
369 struct thread* th = create_thread(__current, false);
372 start_thread(th, entry);
377 exit_thread(void* val);
380 thread_release_mem(struct thread* thread);
386 ========= Signal =========
389 #define pending_sigs(thread) ((thread)->sigctx.sig_pending)
390 #define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig)
391 #define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)])
392 #define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact))
394 static inline struct sigact*
395 active_signal(struct thread* thread) {
396 struct sigctx* sigctx = &thread->sigctx;
397 struct sigregistry* sigreg = thread->process->sigreg;
398 return sigreg->signals[sigctx->sig_active];
402 sigactive_push(struct thread* thread, int active_sig) {
403 struct sigctx* sigctx = &thread->sigctx;
404 int prev_active = sigctx->sig_active;
406 assert(sigact_of(thread->process, active_sig));
408 sigctx->sig_order[active_sig] = prev_active;
409 sigctx->sig_active = active_sig;
413 sigactive_pop(struct thread* thread) {
414 struct sigctx* sigctx = &thread->sigctx;
415 int active_sig = sigctx->sig_active;
417 sigctx->sig_active = sigctx->sig_order[active_sig];
418 sigctx->sig_order[active_sig] = active_sig;
422 proc_setsignal(struct proc_info* proc, signum_t signum);
425 thread_setsignal(struct thread* thread, signum_t signum);
428 thread_stats_update(bool inbound, bool voluntary);
431 thread_stats_update_entering(bool voluntary)
433 thread_stats_update(true, voluntary);
437 thread_stats_update_leaving()
439 thread_stats_update(false, true);
443 thread_stats_update_kpreempt()
445 current_thread->stats.kpreempt_count++;
449 thread_stats_reset_kpreempt()
451 current_thread->stats.kpreempt_count = 0;
454 static inline ticks_t
455 thread_stats_kernel_elapse(struct thread* thread)
457 return clock_systime() - thread->stats.last_reentry;
460 static inline ticks_t
461 thread_stats_user_elapse(struct thread* thread)
463 struct thread_stats* stats;
464 stats = &thread->stats;
466 return stats->last_entry - stats->last_leave;
470 #endif /* __LUNAIX_PROCESS_H */