SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2005 David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007    
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012    
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA. 
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  * Definition of a process in SOS. A process is basically the
035  * collection of all the resources requested by a user program. The
036  * threads are one of these resources, the mm_context is one other
037  * example of such resources.
038  */
039 struct sos_process
040 {
041   char name[SOS_PROCESS_MAX_NAMELEN];
042 
043   /** First important resource: the address space */
044   struct sos_umem_vmm_as *address_space;
045 
046   /** Second important resource: the CPU execution contexts, aka the
047       threads executing in the context of this process. */
048   struct sos_thread      *thread_list;
049   sos_count_t            nb_threads;
050 
051   /** Reference counter, including threads */
052   sos_count_t            ref_cnt;
053 
054   /** The array of opened file descriptors */
055   struct sos_fs_opened_file * fds[SOS_PROCESS_MAX_OPENED_FILES];
056 
057   /** Where the root of the process is (for chroot support). May be NULL */
058   struct sos_fs_opened_file * root;
059 
060   /** Where the current working dir of the process is */
061   struct sos_fs_opened_file * cwd;
062 
063   struct sos_process     *prev, *next;
064 };
065 
066 
067 /** The list of processes in the system */
068 static struct sos_process *process_list = NULL;
069 
070 
071 /** The cache for the sos_process structures */
072 struct sos_kslab_cache *cache_struct_process;
073 
074 
075 /**
076  * Helper function for debugging purposes
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   /* Create the cache for the process structures */
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   /* proc is already filled with 0 (cache has SOS_KSLAB_CREATE_ZERO
141      flag) */
142 
143   /* Copy the file descriptors when needed */
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       /* Error */
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   /* Add it to the global list of processes */
196   sos_disable_IRQs(flags);
197   list_add_tail(process_list, proc);
198   sos_restore_IRQs(flags);
199 
200   /* Mark the process as referenced */
201   proc->ref_cnt = 1;
202 
203  end_create_proc:
204   if (SOS_OK != retval)
205     {
206       int fd;
207 
208       /* Close the file descriptors */
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   /* Close the FD that are not allowed to be duplicated */
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  * Restricted functions
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   /* The process is assumed to be referenced by somebody */
380   SOS_ASSERT_FATAL(in_proc->ref_cnt > 0);
381 
382   /* Only threads that are being created are allowed to be attached to
383      a process */
384   SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED);
385 
386   /* Update the list of the threads in the process */
387   thr->process = in_proc;
388 
389   /* Increment the reference count for the process */
390   sos_process_ref(in_proc);
391 
392   /* Add the thread to the process thread's list */
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 /** The function responsible for releasing the resources held by the
404     process. */
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   /* Close the file descriptors */
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   /* First: free the user address space */
436   retval = sos_umem_vmm_delete_as(proc->address_space);
437   SOS_ASSERT_FATAL(SOS_OK == retval);
438 
439   /* Free the process structure */
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   /* Update the list of the threads in the process */
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   /* Unreference the process */
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 }

source navigation ] diff markup ] identifier search ] general search ]