Architectural Support: x86_64 (#37)
[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 0b0001
54
55 #define thread_detached(th) ((th)->flags & TH_DETACHED)
56 #define detach_thread(th) ((th)->flags |= TH_DETACHED)
57
58 struct proc_sig
59 {
60     int sig_num;
61     void* sigact;
62     void* sighand;
63     struct hart_state* saved_hstate;
64 } __attribute__((packed));
65
66
67 struct proc_info;
68
69 struct haybed {
70     struct llist_header sleepers;
71     time_t wakeup_time;
72     time_t alarm_time;
73 };
74
75 struct thread
76 {
77     /*
78         Any change to *critical section*, including layout, size
79         must be reflected in arch/x86/interrupt.S.inc to avoid
80         disaster!
81      */
82     struct
83     {
84         struct hart_state* hstate;
85         ptr_t ustack_top;
86     };                              // *critical section
87
88     struct {
89         tid_t tid;
90         time_t created;
91         int state;
92         int syscall_ret;
93         ptr_t exit_val;
94         int flags;
95     };
96
97     struct {
98         ptr_t kstack;               // process local kernel stack
99         struct mm_region* ustack;   // process local user stack (NULL for kernel thread)
100     };
101
102     struct haybed sleep;
103
104     struct proc_info* process;
105     struct llist_header proc_sibs;  // sibling to process-local threads
106     struct llist_header sched_sibs; // sibling to scheduler (global) threads
107     struct sigctx sigctx;
108     waitq_t waitqueue;
109 };
110
111 struct proc_info
112 {
113     // active thread, must be at the very beginning
114     struct thread* th_active;
115
116     struct llist_header threads;
117     int thread_count;
118
119     struct llist_header tasks;
120
121     struct llist_header siblings;
122     struct llist_header children;
123     struct llist_header grp_member;
124
125     struct {
126         struct proc_info* parent;
127         pid_t pid;
128         pid_t pgid;
129         time_t created;
130
131         int state;
132         int exit_code;
133     };
134
135     struct proc_mm* mm;
136     struct sigregistry* sigreg;
137     struct v_fdtable* fdtable;
138     struct v_dnode* cwd;
139     struct {
140         char* cmd;
141         size_t cmd_len;
142     };
143
144     struct iopoll pollctx;
145 };
146
147 extern volatile struct proc_info* __current;
148 extern volatile struct thread* current_thread;
149
150 /**
151  * @brief Check if current process belong to kernel itself
152  * (pid=0)
153  */
154 #define kernel_process(proc) (!(proc)->pid)
155
156 #define resume_thread(th) (th)->state = PS_READY
157 #define pause_thread(th) (th)->state = PS_PAUSED
158 #define block_thread(th) (th)->state = PS_BLOCKED
159
160 static inline void must_inline
161 set_current_executing(struct thread* thread)
162 {
163     current_thread = thread;
164     __current = thread->process;
165 }
166
167 static inline struct proc_mm* 
168 vmspace(struct proc_info* proc) 
169 {
170     return proc ? proc->mm : NULL;
171 }
172
173 static inline ptr_t
174 vmroot(struct proc_info* proc) 
175 {
176     return proc ? proc->mm->vmroot : 0;
177 }
178
179 static inline vm_regions_t* 
180 vmregions(struct proc_info* proc) 
181 {
182     return proc ? &proc->mm->regions : NULL;
183 }
184
185
186 static inline unsigned int
187 procvm_asid(struct proc_mm* mm)
188 {
189     return mm->proc->pid;
190 }
191
192 static inline void
193 block_current_thread()
194 {
195     block_thread(current_thread);
196 }
197
198 static inline void
199 pause_current_thread()
200 {
201     pause_thread(current_thread);
202 }
203
204 static inline void
205 resume_current_thread()
206 {
207     resume_thread(current_thread);
208 }
209
210 static inline int syscall_result(int retval) {
211     return (current_thread->syscall_ret = retval);
212 }
213
214 /**
215  * @brief Spawn a process with arbitary entry point. 
216  *        The inherit priviledge level is deduced automatically
217  *        from the given entry point
218  * 
219  * @param created returned created main thread
220  * @param entry entry point
221  * @param with_ustack whether to pre-allocate a user stack with it
222  * @return int 
223  */
224 int
225 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
226
227 /**
228  * @brief Spawn a process that housing a given executable image as well as 
229  *        program argument and environment setting
230  * 
231  * @param created returned created main thread
232  * @param path file system path to executable
233  * @param argv arguments passed to executable
234  * @param envp environment variables passed to executable
235  * @return int 
236  */
237 int
238 spawn_process_usr(struct thread** created, char* path, 
239                     const char** argv, const char** envp);
240
241 /**
242  * @brief 分配并初始化一个进程控制块
243  *
244  * @return struct proc_info*
245  */
246 struct proc_info*
247 alloc_process();
248
249 /**
250  * @brief 初始化进程用户空间
251  *
252  * @param pcb
253  */
254 void
255 init_proc_user_space(struct proc_info* pcb);
256
257 /**
258  * @brief 向系统发布一个进程,使其可以被调度。
259  *
260  * @param process
261  */
262 void
263 commit_process(struct proc_info* process);
264
265 pid_t
266 destroy_process(pid_t pid);
267
268 void 
269 delete_process(struct proc_info* proc);
270
271 /**
272  * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
273  *
274  */
275 pid_t
276 dup_proc();
277
278 /**
279  * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
280  *
281  */
282 void
283 new_proc();
284
285 /**
286  * @brief 终止(退出)当前进程
287  *
288  */
289 void
290 terminate_current(int exit_code);
291
292 void 
293 terminate_proccess(struct proc_info* proc, int exit_code);
294
295 int
296 orphaned_proc(pid_t pid);
297
298 struct proc_info*
299 get_process(pid_t pid);
300
301 /* 
302     ========= Thread =========
303 */
304
305 void
306 commit_thread(struct thread* thread);
307
308 struct thread*
309 alloc_thread(struct proc_info* process);
310
311 void
312 destory_thread(struct thread* thread);
313
314 void
315 terminate_thread(struct thread* thread, ptr_t val);
316
317 void
318 terminate_current_thread(ptr_t val);
319
320 struct thread*
321 create_thread(struct proc_info* proc, bool with_ustack);
322
323 void
324 start_thread(struct thread* th, ptr_t entry);
325
326 static inline void
327 spawn_kthread(ptr_t entry) {
328     assert(kernel_process(__current));
329
330     struct thread* th = create_thread(__current, false);
331     
332     assert(th);
333     start_thread(th, entry);
334 }
335
336 void 
337 exit_thread(void* val);
338
339 void
340 thread_release_mem(struct thread* thread);
341
342 /* 
343     ========= Signal =========
344 */
345
346 #define pending_sigs(thread) ((thread)->sigctx.sig_pending)
347 #define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig)
348 #define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)])
349 #define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact))
350
351 static inline struct sigact*
352 active_signal(struct thread* thread) {
353     struct sigctx* sigctx = &thread->sigctx;
354     struct sigregistry* sigreg = thread->process->sigreg;
355     return sigreg->signals[sigctx->sig_active];
356
357
358 static inline void 
359 sigactive_push(struct thread* thread, int active_sig) {
360     struct sigctx* sigctx = &thread->sigctx;
361     int prev_active = sigctx->sig_active;
362
363     assert(sigact_of(thread->process, active_sig));
364
365     sigctx->sig_order[active_sig] = prev_active;
366     sigctx->sig_active = active_sig;
367 }
368
369 static inline void 
370 sigactive_pop(struct thread* thread) {
371     struct sigctx* sigctx = &thread->sigctx;
372     int active_sig = sigctx->sig_active;
373
374     sigctx->sig_active = sigctx->sig_order[active_sig];
375     sigctx->sig_order[active_sig] = active_sig;
376 }
377
378 void
379 proc_setsignal(struct proc_info* proc, signum_t signum);
380
381 void
382 thread_setsignal(struct thread* thread, signum_t signum);
383
384
385 #endif /* __LUNAIX_PROCESS_H */