Support to multi-threading and pthread interface (POSIX.1-2008) (#23)
[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/page.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/pcontext.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     isr_param* saved_ictx;
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/i386/interrupt.S.inc to avoid
80         disaster!
81      */
82     struct
83     {
84         isr_param* intr_ctx;
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 sigregister* 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->mm;
171 }
172
173 static inline ptr_t
174 vmroot(struct proc_info* proc) 
175 {
176     return proc->mm->vmroot;
177 }
178
179 static inline vm_regions_t* 
180 vmregions(struct proc_info* proc) 
181 {
182     return &proc->mm->regions;
183 }
184
185 static inline void
186 block_current_thread()
187 {
188     block_thread(current_thread);
189 }
190
191 static inline void
192 pause_current_thread()
193 {
194     pause_thread(current_thread);
195 }
196
197 static inline void
198 resume_current_thread()
199 {
200     resume_thread(current_thread);
201 }
202
203 static inline int syscall_result(int retval) {
204     return (current_thread->syscall_ret = retval);
205 }
206
207 /**
208  * @brief Spawn a process with arbitary entry point. 
209  *        The inherit priviledge level is deduced automatically
210  *        from the given entry point
211  * 
212  * @param created returned created main thread
213  * @param entry entry point
214  * @param with_ustack whether to pre-allocate a user stack with it
215  * @return int 
216  */
217 int
218 spawn_process(struct thread** created, ptr_t entry, bool with_ustack);
219
220 /**
221  * @brief Spawn a process that housing a given executable image as well as 
222  *        program argument and environment setting
223  * 
224  * @param created returned created main thread
225  * @param path file system path to executable
226  * @param argv arguments passed to executable
227  * @param envp environment variables passed to executable
228  * @return int 
229  */
230 int
231 spawn_process_usr(struct thread** created, char* path, 
232                     const char** argv, const char** envp);
233
234 /**
235  * @brief 分配并初始化一个进程控制块
236  *
237  * @return struct proc_info*
238  */
239 struct proc_info*
240 alloc_process();
241
242 /**
243  * @brief 初始化进程用户空间
244  *
245  * @param pcb
246  */
247 void
248 init_proc_user_space(struct proc_info* pcb);
249
250 /**
251  * @brief 向系统发布一个进程,使其可以被调度。
252  *
253  * @param process
254  */
255 void
256 commit_process(struct proc_info* process);
257
258 pid_t
259 destroy_process(pid_t pid);
260
261 void 
262 delete_process(struct proc_info* proc);
263
264 /**
265  * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
266  *
267  */
268 pid_t
269 dup_proc();
270
271 /**
272  * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
273  *
274  */
275 void
276 new_proc();
277
278 /**
279  * @brief 终止(退出)当前进程
280  *
281  */
282 void
283 terminate_current(int exit_code);
284
285 void 
286 terminate_proccess(struct proc_info* proc, int exit_code);
287
288 int
289 orphaned_proc(pid_t pid);
290
291 struct proc_info*
292 get_process(pid_t pid);
293
294 /* 
295     ========= Thread =========
296 */
297
298 void
299 commit_thread(struct thread* thread);
300
301 struct thread*
302 alloc_thread(struct proc_info* process);
303
304 void
305 destory_thread(ptr_t vm_mnt, struct thread* thread);
306
307 void
308 terminate_thread(struct thread* thread, ptr_t val);
309
310 void
311 terminate_current_thread(ptr_t val);
312
313 struct thread*
314 create_thread(struct proc_info* proc, ptr_t vm_mnt, bool with_ustack);
315
316 void
317 start_thread(struct thread* th, ptr_t vm_mnt, ptr_t entry);
318
319 static inline void
320 spawn_kthread(ptr_t entry) {
321     assert(kernel_process(__current));
322
323     struct thread* th = create_thread(__current, VMS_SELF, false);
324     
325     assert(th);
326     start_thread(th, VMS_SELF, entry);
327 }
328
329 void 
330 exit_thread(void* val);
331
332 void
333 thread_release_mem(struct thread* thread, ptr_t vm_mnt);
334
335 /* 
336     ========= Signal =========
337 */
338
339 #define pending_sigs(thread) ((thread)->sigctx.sig_pending)
340 #define raise_signal(thread, sig) sigset_add(pending_sigs(thread), sig)
341 #define sigact_of(proc, sig) ((proc)->sigreg->signals[(sig)])
342 #define set_sigact(proc, sig, sigact) ((proc)->sigreg->signals[(sig)] = (sigact))
343
344 static inline struct sigact*
345 active_signal(struct thread* thread) {
346     struct sigctx* sigctx = &thread->sigctx;
347     struct sigregister* sigreg = thread->process->sigreg;
348     return sigreg->signals[sigctx->sig_active];
349
350
351 static inline void 
352 sigactive_push(struct thread* thread, int active_sig) {
353     struct sigctx* sigctx = &thread->sigctx;
354     int prev_active = sigctx->sig_active;
355
356     assert(sigact_of(thread->process, active_sig));
357
358     sigctx->sig_order[active_sig] = prev_active;
359     sigctx->sig_active = active_sig;
360 }
361
362 static inline void 
363 sigactive_pop(struct thread* thread) {
364     struct sigctx* sigctx = &thread->sigctx;
365     int active_sig = sigctx->sig_active;
366
367     sigctx->sig_active = sigctx->sig_order[active_sig];
368     sigctx->sig_order[active_sig] = active_sig;
369 }
370
371 void
372 proc_setsignal(struct proc_info* proc, signum_t signum);
373
374 void
375 thread_setsignal(struct thread* thread, signum_t signum);
376
377
378 #endif /* __LUNAIX_PROCESS_H */