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