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