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()
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   proc = (struct sos_process*) sos_kmem_cache_alloc(cache_struct_process, 0);
136   if (! proc)
137     return NULL;
138 
139   /* proc is already filled with 0 (cache has SOS_KSLAB_CREATE_ZERO
140      flag) */
141 
142   /* Copy the file descriptors when needed */
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       /* Error */
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   /* Add it to the global list of processes */
195   sos_disable_IRQs(flags);
196   list_add_tail(process_list, proc);
197   sos_restore_IRQs(flags);
198 
199   /* Mark the process as referenced */
200   proc->ref_cnt = 1;
201 
202  end_create_proc:
203   if (SOS_OK != retval)
204     {
205       int fd;
206 
207       /* Close the file descriptors */
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   /* Close the FD that are not allowed to be duplicated */
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  * Restricted functions
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   /* The process is assumed to be referenced by somebody */
372   SOS_ASSERT_FATAL(in_proc->ref_cnt > 0);
373 
374   /* Only threads that are being created are allowed to be attached to
375      a process */
376   SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED);
377 
378   /* Update the list of the threads in the process */
379   thr->process = in_proc;
380 
381   /* Increment the reference count for the process */
382   sos_process_ref(in_proc);
383 
384   /* Add the thread to the process thread's list */
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 /** The function responsible for releasing the resources held by the
396     process. */
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   /* Close the file descriptors */
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   /* First: free the user address space */
424   retval = sos_umem_vmm_delete_as(proc->address_space);
425   SOS_ASSERT_FATAL(SOS_OK == retval);
426 
427   /* Free the process structure */
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   /* Update the list of the threads in the process */
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   /* Unreference the process */
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 }

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