001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/assert.h>
020 #include <sos/list.h>
021 #include <sos/kmem_slab.h>
022 #include <hwcore/irq.h>
023 #include <drivers/bochs.h>
024
025 #include <sos/umem_vmm.h>
026
027 #include "process.h"
028
029 #define SOS_PROCESS_MAX_OPENED_FILES 64
030 #define SOS_PROCESS_MAX_NAMELEN 32
031
032
033
034
035
036
037
038
039 struct sos_process
040 {
041 char name[SOS_PROCESS_MAX_NAMELEN];
042
043
044 struct sos_umem_vmm_as *address_space;
045
046
047
048 struct sos_thread *thread_list;
049 sos_count_t nb_threads;
050
051
052 sos_count_t ref_cnt;
053
054
055 struct sos_fs_opened_file * fds[SOS_PROCESS_MAX_OPENED_FILES];
056
057
058 struct sos_fs_opened_file * root;
059
060
061 struct sos_fs_opened_file * cwd;
062
063 struct sos_process *prev, *next;
064 };
065
066
067
068 static struct sos_process *process_list = NULL;
069
070
071
072 struct sos_kslab_cache *cache_struct_process;
073
074
075
076
077
078 void sos_process_dumplist(void)
079 {
080 struct sos_thread * cur_thr = sos_thread_get_current();
081 struct sos_process * proc;
082 int nb_procs;
083
084 sos_bochs_printf("<ps>\n");
085 list_foreach(process_list, proc, nb_procs)
086 {
087 struct sos_thread * thr;
088 int nb_thrs;
089
090 sos_bochs_printf(" proc@%p: '%s', %d threads, %d refs\n",
091 proc, proc->name?proc->name:"(none)",
092 proc->nb_threads, proc->ref_cnt);
093
094 list_foreach_forward_named(proc->thread_list, thr, nb_thrs,
095 prev_in_process, next_in_process)
096 {
097 if (thr == cur_thr)
098 sos_bochs_printf(" thr@%p: [CURRENT]\n", thr);
099 else
100 sos_bochs_printf(" thr@%p: %cstate=%d eip=%p\n",
101 thr,
102 sos_cpu_context_is_in_user_mode(thr->cpu_state)?'u':'k',
103 thr->state,
104 (void*)sos_cpu_context_get_PC(thr->cpu_state));
105 }
106 }
107 sos_bochs_printf(" ======= %d processes =======\n", nb_procs);
108 sos_bochs_printf("</ps>\n");
109 }
110
111
112 sos_ret_t sos_process_subsystem_setup()
113 {
114
115 cache_struct_process = sos_kmem_cache_create("struct_process",
116 sizeof(struct sos_process),
117 3,
118 0,
119 SOS_KSLAB_CREATE_MAP
120 | SOS_KSLAB_CREATE_ZERO);
121 if (! cache_struct_process)
122 return -SOS_ENOMEM;
123
124 return SOS_OK;
125 }
126
127
128 struct sos_process *sos_process_create(const char *name,
129 sos_bool_t do_copy_current_process)
130 {
131 sos_ret_t retval = SOS_OK;
132 sos_ui32_t flags;
133 struct sos_process *proc;
134
135
136 proc = (struct sos_process*) sos_kmem_cache_alloc(cache_struct_process, 0);
137 if (! proc)
138 return NULL;
139
140
141
142
143
144 if (do_copy_current_process)
145 {
146 struct sos_process * myself = sos_thread_get_current()->process;
147 int fd;
148
149 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
150 if (NULL != myself->fds[fd])
151 {
152 retval = sos_fs_duplicate_opened_file(myself->fds[fd],
153 proc,
154 & proc->fds[fd]);
155 if (SOS_OK != retval)
156 goto end_create_proc;
157 }
158
159 retval = sos_fs_duplicate_opened_file(myself->root,
160 proc,
161 & proc->root);
162 if (SOS_OK != retval)
163 goto end_create_proc;
164
165 retval = sos_fs_duplicate_opened_file(myself->cwd,
166 proc,
167 & proc->cwd);
168 if (SOS_OK != retval)
169 goto end_create_proc;
170 }
171
172 if (do_copy_current_process)
173 proc->address_space = sos_umem_vmm_duplicate_current_thread_as(proc);
174 else
175 proc->address_space = sos_umem_vmm_create_empty_as(proc);
176
177 if (NULL == proc->address_space)
178 {
179
180 retval = -SOS_ENOMEM;
181 goto end_create_proc;
182 }
183
184 if (!name)
185 {
186 struct sos_thread * cur_thr = sos_thread_get_current();
187 if (do_copy_current_process)
188 name = cur_thr->process->name;
189 else
190 name = "[UNNAMED]";
191 }
192
193 strzcpy(proc->name, name, SOS_PROCESS_MAX_NAMELEN);
194
195
196 sos_disable_IRQs(flags);
197 list_add_tail(process_list, proc);
198 sos_restore_IRQs(flags);
199
200
201 proc->ref_cnt = 1;
202
203 end_create_proc:
204 if (SOS_OK != retval)
205 {
206 int fd;
207
208
209 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
210 if (NULL != proc->fds[fd])
211 {
212 sos_fs_close(proc->fds[fd]);
213 proc->fds[fd] = NULL;
214 }
215
216 if (proc->root)
217 sos_fs_close(proc->root);
218 if (proc->cwd)
219 sos_fs_close(proc->cwd);
220 proc->root = proc->cwd = NULL;
221
222 sos_kmem_cache_free((sos_vaddr_t) proc);
223 proc = NULL;
224 }
225
226 return proc;
227 }
228
229
230 inline
231 sos_ret_t sos_process_ref(struct sos_process *proc)
232 {
233 sos_ui32_t flags;
234 sos_disable_IRQs(flags);
235 proc->ref_cnt ++;
236 sos_restore_IRQs(flags);
237 return SOS_OK;
238 }
239
240
241 sos_count_t sos_process_get_nb_threads(const struct sos_process *proc)
242 {
243 sos_count_t retval;
244 sos_ui32_t flags;
245 sos_disable_IRQs(flags);
246 retval = proc->nb_threads;
247 sos_restore_IRQs(flags);
248 return retval;
249 }
250
251
252 struct sos_mm_context *
253 sos_process_get_mm_context(const struct sos_process *proc)
254 {
255 return sos_umem_vmm_get_mm_context(proc->address_space);
256 }
257
258
259 struct sos_umem_vmm_as *
260 sos_process_get_address_space(const struct sos_process *proc)
261 {
262 return proc->address_space;
263 }
264
265
266 sos_ret_t sos_process_set_address_space(struct sos_process *proc,
267 struct sos_umem_vmm_as *new_as)
268 {
269 int fd;
270
271
272 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
273 if ( (NULL != proc->fds[fd])
274 && (proc->fds[fd]->open_flags & SOS_FS_OPEN_CLOSEONEXEC) )
275 {
276 sos_fs_close(proc->fds[fd]);
277 proc->fds[fd] = NULL;
278 }
279
280 if (proc->address_space)
281 {
282 sos_ret_t retval = sos_umem_vmm_delete_as(proc->address_space);
283 if (SOS_OK != retval)
284 return retval;
285 }
286
287 proc->address_space = new_as;
288 return SOS_OK;
289 }
290
291
292 struct sos_fs_opened_file *
293 sos_process_get_root(const struct sos_process *proc)
294 {
295 return proc->root;
296 }
297
298
299 struct sos_fs_opened_file *
300 sos_process_get_cwd(const struct sos_process *proc)
301 {
302 return proc->cwd;
303 }
304
305
306 struct sos_fs_opened_file *
307 sos_process_get_opened_file(const struct sos_process *proc,
308 int fd)
309 {
310 if ((fd < 0) || (fd >= SOS_PROCESS_MAX_OPENED_FILES))
311 return NULL;
312 return proc->fds[fd];
313 }
314
315
316 sos_ret_t
317 sos_process_chroot(struct sos_process *proc,
318 struct sos_fs_opened_file * new_root,
319 struct sos_fs_opened_file ** old_root)
320 {
321 *old_root = proc->root;
322 proc->root = new_root;
323
324 return SOS_OK;
325 }
326
327
328 sos_ret_t
329 sos_process_chdir(struct sos_process *proc,
330 struct sos_fs_opened_file * new_cwd,
331 struct sos_fs_opened_file ** old_cwd)
332 {
333 *old_cwd = proc->cwd;
334 proc->cwd = new_cwd;
335
336 return SOS_OK;
337 }
338
339
340 sos_ret_t
341 sos_process_register_opened_file(struct sos_process *proc,
342 struct sos_fs_opened_file * of)
343 {
344 int i;
345 for (i = 0 ; i < SOS_PROCESS_MAX_OPENED_FILES ; i++)
346 if (NULL == proc->fds[i])
347 {
348 proc->fds[i] = of;
349 return i;
350 }
351
352 return -SOS_EMFILE;
353 }
354
355
356 sos_ret_t
357 sos_process_unregister_opened_file(struct sos_process *proc,
358 int fd)
359 {
360 if ((fd < 0) || (fd >= SOS_PROCESS_MAX_OPENED_FILES))
361 return -SOS_EBADF;
362
363 proc->fds[fd] = NULL;
364 return SOS_OK;
365 }
366
367
368
369
370
371
372
373
374 sos_ret_t sos_process_register_thread(struct sos_process *in_proc,
375 struct sos_thread *thr)
376 {
377 sos_ui32_t flags;
378
379
380 SOS_ASSERT_FATAL(in_proc->ref_cnt > 0);
381
382
383
384 SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED);
385
386
387 thr->process = in_proc;
388
389
390 sos_process_ref(in_proc);
391
392
393 sos_disable_IRQs(flags);
394 list_add_tail_named(in_proc->thread_list, thr,
395 prev_in_process, next_in_process);
396 in_proc->nb_threads ++;
397 sos_restore_IRQs(flags);
398
399 return SOS_OK;
400 }
401
402
403
404
405 sos_ret_t sos_process_unref(struct sos_process *proc)
406 {
407 sos_ui32_t flags;
408 sos_ret_t retval;
409 int fd;
410
411 SOS_ASSERT_FATAL(proc->ref_cnt > 0);
412
413 sos_disable_IRQs(flags);
414 proc->ref_cnt --;
415 if (proc->ref_cnt > 0)
416 {
417 sos_restore_IRQs(flags);
418 return -SOS_EBUSY;
419 }
420 list_delete(process_list, proc);
421 sos_restore_IRQs(flags);
422
423
424 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
425 if (NULL != proc->fds[fd])
426 {
427 sos_fs_close(proc->fds[fd]);
428 proc->fds[fd] = NULL;
429 }
430
431 sos_fs_close(proc->root);
432 sos_fs_close(proc->cwd);
433 proc->root = proc->cwd = NULL;
434
435
436 retval = sos_umem_vmm_delete_as(proc->address_space);
437 SOS_ASSERT_FATAL(SOS_OK == retval);
438
439
440 sos_kmem_cache_free((sos_vaddr_t)proc);
441
442 return SOS_OK;
443 }
444
445
446 sos_ret_t sos_process_unregister_thread(struct sos_thread *thr)
447 {
448 sos_ui32_t flags;
449 struct sos_process * in_proc = thr->process;
450
451 SOS_ASSERT_FATAL(thr->state == SOS_THR_ZOMBIE);
452
453
454 thr->process = NULL;
455 sos_disable_IRQs(flags);
456 list_delete_named(in_proc->thread_list, thr,
457 prev_in_process, next_in_process);
458 SOS_ASSERT_FATAL(in_proc->nb_threads > 0);
459 in_proc->nb_threads --;
460 sos_restore_IRQs(flags);
461
462
463 sos_process_unref(in_proc);
464
465 return SOS_OK;
466 }
467
468
469 sos_ret_t sos_process_set_name(struct sos_process * proc,
470 const char * new_name)
471 {
472 strzcpy(proc->name, new_name, SOS_PROCESS_MAX_NAMELEN);
473 return SOS_OK;
474 }