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()
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 proc = (struct sos_process*) sos_kmem_cache_alloc(cache_struct_process, 0);
136 if (! proc)
137 return NULL;
138
139
140
141
142
143 if (do_copy_current_process)
144 {
145 struct sos_process * myself = sos_thread_get_current()->process;
146 int fd;
147
148 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
149 if (NULL != myself->fds[fd])
150 {
151 retval = sos_fs_duplicate_opened_file(myself->fds[fd],
152 proc,
153 & proc->fds[fd]);
154 if (SOS_OK != retval)
155 goto end_create_proc;
156 }
157
158 retval = sos_fs_duplicate_opened_file(myself->root,
159 proc,
160 & proc->root);
161 if (SOS_OK != retval)
162 goto end_create_proc;
163
164 retval = sos_fs_duplicate_opened_file(myself->cwd,
165 proc,
166 & proc->cwd);
167 if (SOS_OK != retval)
168 goto end_create_proc;
169 }
170
171 if (do_copy_current_process)
172 proc->address_space = sos_umem_vmm_duplicate_current_thread_as(proc);
173 else
174 proc->address_space = sos_umem_vmm_create_empty_as(proc);
175
176 if (NULL == proc->address_space)
177 {
178
179 retval = -SOS_ENOMEM;
180 goto end_create_proc;
181 }
182
183 if (!name)
184 {
185 struct sos_thread * cur_thr = sos_thread_get_current();
186 if (do_copy_current_process)
187 name = cur_thr->process->name;
188 else
189 name = "[UNNAMED]";
190 }
191
192 strzcpy(proc->name, name, SOS_PROCESS_MAX_NAMELEN);
193
194
195 sos_disable_IRQs(flags);
196 list_add_tail(process_list, proc);
197 sos_restore_IRQs(flags);
198
199
200 proc->ref_cnt = 1;
201
202 end_create_proc:
203 if (SOS_OK != retval)
204 {
205 int fd;
206
207
208 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
209 if (NULL != proc->fds[fd])
210 sos_fs_close(proc->fds[fd]);
211
212 if (proc->root)
213 sos_fs_close(proc->root);
214 if (proc->cwd)
215 sos_fs_close(proc->cwd);
216
217 sos_kmem_cache_free((sos_vaddr_t) proc);
218 proc = NULL;
219 }
220
221 return proc;
222 }
223
224
225 inline
226 sos_ret_t sos_process_ref(struct sos_process *proc)
227 {
228 sos_ui32_t flags;
229 sos_disable_IRQs(flags);
230 proc->ref_cnt ++;
231 sos_restore_IRQs(flags);
232 return SOS_OK;
233 }
234
235
236 sos_count_t sos_process_get_nb_threads(const struct sos_process *proc)
237 {
238 sos_count_t retval;
239 sos_ui32_t flags;
240 sos_disable_IRQs(flags);
241 retval = proc->nb_threads;
242 sos_restore_IRQs(flags);
243 return retval;
244 }
245
246
247 struct sos_mm_context *
248 sos_process_get_mm_context(const struct sos_process *proc)
249 {
250 return sos_umem_vmm_get_mm_context(proc->address_space);
251 }
252
253
254 struct sos_umem_vmm_as *
255 sos_process_get_address_space(const struct sos_process *proc)
256 {
257 return proc->address_space;
258 }
259
260
261 sos_ret_t sos_process_set_address_space(struct sos_process *proc,
262 struct sos_umem_vmm_as *new_as)
263 {
264 int fd;
265
266
267 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
268 if ( (NULL != proc->fds[fd])
269 && (! (proc->fds[fd]->open_flags & SOS_FS_OPEN_KEEPONEXEC)) )
270 sos_fs_close(proc->fds[fd]);
271
272 if (proc->address_space)
273 {
274 sos_ret_t retval = sos_umem_vmm_delete_as(proc->address_space);
275 if (SOS_OK != retval)
276 return retval;
277 }
278
279 proc->address_space = new_as;
280 return SOS_OK;
281 }
282
283
284 struct sos_fs_opened_file *
285 sos_process_get_root(const struct sos_process *proc)
286 {
287 return proc->root;
288 }
289
290
291 struct sos_fs_opened_file *
292 sos_process_get_cwd(const struct sos_process *proc)
293 {
294 return proc->cwd;
295 }
296
297
298 struct sos_fs_opened_file *
299 sos_process_get_opened_file(const struct sos_process *proc,
300 int fd)
301 {
302 if ((fd < 0) || (fd >= SOS_PROCESS_MAX_OPENED_FILES))
303 return NULL;
304 return proc->fds[fd];
305 }
306
307
308 sos_ret_t
309 sos_process_chroot(struct sos_process *proc,
310 struct sos_fs_opened_file * new_root,
311 struct sos_fs_opened_file ** old_root)
312 {
313 *old_root = proc->root;
314 proc->root = new_root;
315
316 return SOS_OK;
317 }
318
319
320 sos_ret_t
321 sos_process_chdir(struct sos_process *proc,
322 struct sos_fs_opened_file * new_cwd,
323 struct sos_fs_opened_file ** old_cwd)
324 {
325 *old_cwd = proc->cwd;
326 proc->cwd = new_cwd;
327
328 return SOS_OK;
329 }
330
331
332 sos_ret_t
333 sos_process_register_opened_file(struct sos_process *proc,
334 struct sos_fs_opened_file * of)
335 {
336 int i;
337 for (i = 0 ; i < SOS_PROCESS_MAX_OPENED_FILES ; i++)
338 if (NULL == proc->fds[i])
339 {
340 proc->fds[i] = of;
341 return i;
342 }
343
344 return -SOS_EMFILE;
345 }
346
347
348 sos_ret_t
349 sos_process_unregister_opened_file(struct sos_process *proc,
350 int fd)
351 {
352 if ((fd < 0) || (fd >= SOS_PROCESS_MAX_OPENED_FILES))
353 return -SOS_EBADF;
354
355 proc->fds[fd] = NULL;
356 return SOS_OK;
357 }
358
359
360
361
362
363
364
365
366 sos_ret_t sos_process_register_thread(struct sos_process *in_proc,
367 struct sos_thread *thr)
368 {
369 sos_ui32_t flags;
370
371
372 SOS_ASSERT_FATAL(in_proc->ref_cnt > 0);
373
374
375
376 SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED);
377
378
379 thr->process = in_proc;
380
381
382 sos_process_ref(in_proc);
383
384
385 sos_disable_IRQs(flags);
386 list_add_tail_named(in_proc->thread_list, thr,
387 prev_in_process, next_in_process);
388 in_proc->nb_threads ++;
389 sos_restore_IRQs(flags);
390
391 return SOS_OK;
392 }
393
394
395
396
397 sos_ret_t sos_process_unref(struct sos_process *proc)
398 {
399 sos_ui32_t flags;
400 sos_ret_t retval;
401 int fd;
402
403 SOS_ASSERT_FATAL(proc->ref_cnt > 0);
404
405 sos_disable_IRQs(flags);
406 proc->ref_cnt --;
407 if (proc->ref_cnt > 0)
408 {
409 sos_restore_IRQs(flags);
410 return -SOS_EBUSY;
411 }
412 list_delete(process_list, proc);
413 sos_restore_IRQs(flags);
414
415
416 for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++)
417 if (NULL != proc->fds[fd])
418 sos_fs_close(proc->fds[fd]);
419
420 sos_fs_close(proc->root);
421 sos_fs_close(proc->cwd);
422
423
424 retval = sos_umem_vmm_delete_as(proc->address_space);
425 SOS_ASSERT_FATAL(SOS_OK == retval);
426
427
428 sos_kmem_cache_free((sos_vaddr_t)proc);
429
430 return SOS_OK;
431 }
432
433
434 sos_ret_t sos_process_unregister_thread(struct sos_thread *thr)
435 {
436 sos_ui32_t flags;
437 struct sos_process * in_proc = thr->process;
438
439 SOS_ASSERT_FATAL(thr->state == SOS_THR_ZOMBIE);
440
441
442 thr->process = NULL;
443 sos_disable_IRQs(flags);
444 list_delete_named(in_proc->thread_list, thr,
445 prev_in_process, next_in_process);
446 SOS_ASSERT_FATAL(in_proc->nb_threads > 0);
447 in_proc->nb_threads --;
448 sos_restore_IRQs(flags);
449
450
451 sos_process_unref(in_proc);
452
453 return SOS_OK;
454 }
455
456
457 sos_ret_t sos_process_set_name(struct sos_process * proc,
458 const char * new_name)
459 {
460 strzcpy(proc->name, new_name, SOS_PROCESS_MAX_NAMELEN);
461 return SOS_OK;
462 }