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