868a9fc290bc97a53ee3bac804b401cf87da54fd
[lunaix-os.git] / lunaix-os / includes / lunaix / process.h
1 #ifndef __LUNAIX_PROCESS_H
2 #define __LUNAIX_PROCESS_H
3
4 #include <lunaix/clock.h>
5 #include <lunaix/ds/waitq.h>
6 #include <lunaix/fs.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>
17
18 #include <stdint.h>
19
20
21 /*
22     |C|Sp|Bk|De|Tn|Pu|Rn|
23             \----/
24               Dt
25
26     Group Dt: whether this process is terminated.
27
28     Rn: Running
29     Tn: Terminated
30     De: Destoryed
31     Pu: Paused
32     Bk: Blocked
33     Sp: Stopped
34     C : Created
35 */
36
37 #define PS_READY 0
38 #define PS_RUNNING 1
39 #define PS_TERMNAT 2
40 #define PS_DESTROY 4
41 #define PS_PAUSED 8
42 #define PS_BLOCKED 16
43 #define PS_STOPPED 32
44 #define PS_CREATED 64
45
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)
49
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)))
56
57
58 #define TH_DETACHED         0b00000001
59 #define TH_STALLED          0b00000010
60
61 #define thread_detached(th) ((th)->flags & TH_DETACHED)
62 #define detach_thread(th) ((th)->flags |= TH_DETACHED)
63
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))
68
69 struct proc_sig
70 {
71     int sig_num;
72     void* sigact;
73     void* sighand;
74     struct hart_state* saved_hstate;
75 } __attribute__((packed));
76
77
78 struct proc_info;
79
80 struct haybed {
81     struct llist_header sleepers;
82     time_t wakeup_time;
83     time_t alarm_time;
84 };
85
86 struct thread_stats
87 {
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;
92     
93     // number of times the thread is preempted in kerenl space
94     unsigned long kpreempt_count;
95
96     // timestamp of last time kernel entry
97     time_t last_entry;
98     // timestamp of last time kernel reentry
99     time_t last_reentry;
100
101     // timestamp of last time kernel leave
102     time_t last_leave;
103     // timestamp of last time the thread is resumed
104     time_t last_resume;
105     
106     union {
107         struct {
108             bool at_user;
109         };
110         int flags;
111     };
112 };
113
114 struct thread
115 {
116     /*
117         Any change to *critical section*, including layout, size
118         must be reflected in arch/<arch>/interrupt.S.inc to avoid
119         disaster!
120      */
121     struct
122     {
123         struct hart_state* hstate;
124         ptr_t ustack_top;
125     };                              // *critical section
126
127     struct {
128         tid_t tid;
129         time_t created;
130         int state;
131         int syscall_ret;
132         ptr_t exit_val;
133         int flags;
134     };
135
136     struct {
137         ptr_t kstack;               // process local kernel stack
138         struct mm_region* ustack;   // process local user stack (NULL for kernel thread)
139     };
140
141     struct thread_stats stats;
142
143     struct haybed sleep;
144
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;
149     waitq_t waitqueue;
150 };
151
152 struct proc_info
153 {
154     // active thread, must be at the very beginning
155     struct thread* th_active;
156
157     struct llist_header threads;
158     int thread_count;
159
160     struct llist_header tasks;
161
162     struct llist_header siblings;
163     struct llist_header children;
164     struct llist_header grp_member;
165
166     struct {
167         struct proc_info* parent;
168         pid_t pid;
169         pid_t pgid;
170         time_t created;
171
172         uid_t euid;
173         uid_t suid;
174         gid_t egid;
175         gid_t sgid;
176
177         struct user_scope uscope;
178         struct v_dnode* root;
179
180         int state;
181         int exit_code;
182     };
183
184     struct proc_mm* mm;
185     struct sigregistry* sigreg;
186     struct v_fdtable* fdtable;
187     struct v_dnode* cwd;
188     struct {
189         char* cmd;
190         size_t cmd_len;
191     };
192
193     struct iopoll pollctx;
194 };
195
196 extern volatile struct proc_info* __current;
197 extern volatile struct thread* current_thread;
198
199 /**
200  * @brief Check if current process belong to kernel itself
201  * (pid=0)
202  */
203 #define kernel_process(proc) (!(proc)->pid)
204
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
208
209 static inline void must_inline
210 set_current_executing(struct thread* thread)
211 {
212     current_thread = thread;
213     __current = thread->process;
214 }
215
216 static inline struct proc_mm* 
217 vmspace(struct proc_info* proc) 
218 {
219     return proc ? proc->mm : NULL;
220 }
221
222 static inline ptr_t
223 vmroot(struct proc_info* proc) 
224 {
225     return proc ? proc->mm->vmroot : 0;
226 }
227
228 static inline vm_regions_t* 
229 vmregions(struct proc_info* proc) 
230 {
231     return proc ? &proc->mm->regions : NULL;
232 }
233
234
235 static inline unsigned int
236 procvm_asid(struct proc_mm* mm)
237 {
238     return mm->proc->pid;
239 }
240
241 static inline void
242 block_current_thread()
243 {
244     block_thread(current_thread);
245 }
246
247 static inline void
248 pause_current_thread()
249 {
250     pause_thread(current_thread);
251 }
252
253 static inline void
254 resume_current_thread()
255 {
256     resume_thread(current_thread);
257 }
258
259 static inline int syscall_result(int retval) {
260     return (current_thread->syscall_ret = retval);
261 }
262
263 /**
264  * @brief Spawn a process with arbitary entry point. 
265  *        The inherit priviledge level is deduced automatically
266  *        from the given entry point
267  * 
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
271  * @return int 
272  */
273 int
274 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
275
276 /**
277  * @brief Spawn a process that housing a given executable image as well as 
278  *        program argument and environment setting
279  * 
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
284  * @return int 
285  */
286 int
287 spawn_process_usr(struct thread** created, char* path, 
288                     const char** argv, const char** envp);
289
290 /**
291  * @brief 分配并初始化一个进程控制块
292  *
293  * @return struct proc_info*
294  */
295 struct proc_info*
296 alloc_process();
297
298 /**
299  * @brief 初始化进程用户空间
300  *
301  * @param pcb
302  */
303 void
304 init_proc_user_space(struct proc_info* pcb);
305
306 /**
307  * @brief 向系统发布一个进程,使其可以被调度。
308  *
309  * @param process
310  */
311 void
312 commit_process(struct proc_info* process);
313
314 pid_t
315 destroy_process(pid_t pid);
316
317 void 
318 delete_process(struct proc_info* proc);
319
320 /**
321  * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
322  *
323  */
324 pid_t
325 dup_proc();
326
327 /**
328  * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
329  *
330  */
331 void
332 new_proc();
333
334 /**
335  * @brief 终止(退出)当前进程
336  *
337  */
338 void
339 terminate_current(int exit_code);
340
341 void 
342 terminate_proccess(struct proc_info* proc, int exit_code);
343
344 int
345 orphaned_proc(pid_t pid);
346
347 struct proc_info*
348 get_process(pid_t pid);
349
350 /* 
351     ========= Thread =========
352 */
353
354 void
355 commit_thread(struct thread* thread);
356
357 struct thread*
358 alloc_thread(struct proc_info* process);
359
360 void
361 destory_thread(struct thread* thread);
362
363 void
364 terminate_thread(struct thread* thread, ptr_t val);
365
366 void
367 terminate_current_thread(ptr_t val);
368
369 struct thread*
370 create_thread(struct proc_info* proc, bool with_ustack);
371
372 void
373 start_thread(struct thread* th, ptr_t entry);
374
375 static inline void
376 spawn_kthread(ptr_t entry) {
377     assert(kernel_process(__current));
378
379     struct thread* th = create_thread(__current, false);
380     
381     assert(th);
382     start_thread(th, entry);
383     detach_thread(th);
384 }
385
386 void 
387 exit_thread(void* val);
388
389 void
390 thread_release_mem(struct thread* thread);
391
392 /* 
393     ========= Signal =========
394 */
395
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))
400
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];
406
407
408 static inline void 
409 sigactive_push(struct thread* thread, int active_sig) {
410     struct sigctx* sigctx = &thread->sigctx;
411     int prev_active = sigctx->sig_active;
412
413     assert(sigact_of(thread->process, active_sig));
414
415     sigctx->sig_order[active_sig] = prev_active;
416     sigctx->sig_active = active_sig;
417 }
418
419 static inline void 
420 sigactive_pop(struct thread* thread) {
421     struct sigctx* sigctx = &thread->sigctx;
422     int active_sig = sigctx->sig_active;
423
424     sigctx->sig_active = sigctx->sig_order[active_sig];
425     sigctx->sig_order[active_sig] = active_sig;
426 }
427
428 void
429 proc_setsignal(struct proc_info* proc, signum_t signum);
430
431 void
432 thread_setsignal(struct thread* thread, signum_t signum);
433
434 void
435 thread_stats_update(bool inbound, bool voluntary);
436
437 static inline void
438 thread_stats_update_entering(bool voluntary)
439 {
440     thread_stats_update(true, voluntary);
441 }
442
443 static inline void
444 thread_stats_update_leaving()
445 {
446     thread_stats_update(false, true);
447 }
448
449 static inline void
450 thread_stats_update_kpreempt()
451 {
452     current_thread->stats.kpreempt_count++;
453 }
454
455 static inline void
456 thread_stats_reset_kpreempt()
457 {
458     current_thread->stats.kpreempt_count = 0;
459 }
460
461 static inline ticks_t
462 thread_stats_kernel_elapse(struct thread* thread)
463 {
464     return clock_systime() - thread->stats.last_reentry;
465 }
466
467 static inline ticks_t
468 thread_stats_user_elapse(struct thread* thread)
469 {
470     struct thread_stats* stats;
471     stats = &thread->stats;
472
473     return stats->last_entry - stats->last_leave;
474 }
475
476 static inline struct user_scope*
477 current_user_scope()
478 {
479     return &__current->uscope;
480 }
481
482 static inline uid_t must_inline
483 current_euid()
484 {
485     return __current->euid;
486 }
487
488 static inline bool must_inline
489 current_is_root()
490 {
491     return current_euid() == 0;
492 }
493
494 static inline gid_t must_inline
495 current_egid()
496 {
497     return __current->egid;
498 }
499
500 static inline void must_inline
501 current_set_egid(gid_t gid)
502 {
503     __current->egid = gid;
504 }
505
506 static inline void must_inline
507 current_set_euid(uid_t uid)
508 {
509     __current->euid = uid;
510 }
511
512 #endif /* __LUNAIX_PROCESS_H */