home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / kernel / fork.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-04  |  5.9 KB  |  234 lines

  1. /*
  2.  *  linux/kernel/fork.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /*
  8.  *  'fork.c' contains the help-routines for the 'fork' system call
  9.  * (see also system_call.s).
  10.  * Fork is rather simple, once you get the hang of it, but the memory
  11.  * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
  12.  */
  13.  
  14. #include <linux/errno.h>
  15. #include <linux/sched.h>
  16. #include <linux/kernel.h>
  17. #include <linux/mm.h>
  18. #include <linux/stddef.h>
  19. #include <linux/unistd.h>
  20. #include <linux/segment.h>
  21. #include <linux/ptrace.h>
  22. #include <linux/malloc.h>
  23. #include <linux/ldt.h>
  24.  
  25. #include <asm/segment.h>
  26. #include <asm/system.h>
  27.  
  28. asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
  29.  
  30. /* These should maybe be in <linux/tasks.h> */
  31.  
  32. #define MAX_TASKS_PER_USER (NR_TASKS/2)
  33. #define MIN_TASKS_LEFT_FOR_ROOT 4
  34.  
  35. extern int shm_fork(struct task_struct *, struct task_struct *);
  36. long last_pid=0;
  37.  
  38. static int find_empty_process(void)
  39. {
  40.     int free_task;
  41.     int i, tasks_free;
  42.     int this_user_tasks;
  43.  
  44. repeat:
  45.     if ((++last_pid) & 0xffff8000)
  46.         last_pid=1;
  47.     this_user_tasks = 0;
  48.     tasks_free = 0;
  49.     free_task = -EAGAIN;
  50.     i = NR_TASKS;
  51.     while (--i > 0) {
  52.         if (!task[i]) {
  53.             free_task = i;
  54.             tasks_free++;
  55.             continue;
  56.         }
  57.         if (task[i]->uid == current->uid)
  58.             this_user_tasks++;
  59.         if (task[i]->pid == last_pid || task[i]->pgrp == last_pid ||
  60.             task[i]->session == last_pid)
  61.             goto repeat;
  62.     }
  63.     if (tasks_free <= MIN_TASKS_LEFT_FOR_ROOT ||
  64.         this_user_tasks > MAX_TASKS_PER_USER)
  65.         if (current->uid)
  66.             return -EAGAIN;
  67.     return free_task;
  68. }
  69.  
  70. static struct file * copy_fd(struct file * old_file)
  71. {
  72.     struct file * new_file = get_empty_filp();
  73.     int error;
  74.  
  75.     if (new_file) {
  76.         memcpy(new_file,old_file,sizeof(struct file));
  77.         new_file->f_count = 1;
  78.         if (new_file->f_inode)
  79.             new_file->f_inode->i_count++;
  80.         if (new_file->f_op && new_file->f_op->open) {
  81.             error = new_file->f_op->open(new_file->f_inode,new_file);
  82.             if (error) {
  83.                 iput(new_file->f_inode);
  84.                 new_file->f_count = 0;
  85.                 new_file = NULL;
  86.             }
  87.         }
  88.     }
  89.     return new_file;
  90. }
  91.  
  92. int dup_mmap(struct task_struct * tsk)
  93. {
  94.     struct vm_area_struct * mpnt, **p, *tmp;
  95.  
  96.     tsk->mmap = NULL;
  97.     tsk->stk_vma = NULL;
  98.     p = &tsk->mmap;
  99.     for (mpnt = current->mmap ; mpnt ; mpnt = mpnt->vm_next) {
  100.         tmp = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
  101.         if (!tmp)
  102.             return -ENOMEM;
  103.         *tmp = *mpnt;
  104.         tmp->vm_task = tsk;
  105.         tmp->vm_next = NULL;
  106.         if (tmp->vm_inode)
  107.             tmp->vm_inode->i_count++;
  108.         *p = tmp;
  109.         p = &tmp->vm_next;
  110.         if (current->stk_vma == mpnt)
  111.             tsk->stk_vma = tmp;
  112.     }
  113.     return 0;
  114. }
  115.  
  116. #define IS_CLONE (regs.orig_eax == __NR_clone)
  117. #define copy_vm(p) ((clone_flags & COPYVM)?copy_page_tables(p):clone_page_tables(p))
  118.  
  119. /*
  120.  *  Ok, this is the main fork-routine. It copies the system process
  121.  * information (task[nr]) and sets up the necessary registers. It
  122.  * also copies the data segment in its entirety.
  123.  */
  124. asmlinkage int sys_fork(struct pt_regs regs)
  125. {
  126.     struct pt_regs * childregs;
  127.     struct task_struct *p;
  128.     int i,nr;
  129.     struct file *f;
  130.     unsigned long clone_flags = COPYVM | SIGCHLD;
  131.  
  132.     if(!(p = (struct task_struct*)__get_free_page(GFP_KERNEL)))
  133.         goto bad_fork;
  134.     nr = find_empty_process();
  135.     if (nr < 0)
  136.         goto bad_fork_free;
  137.     task[nr] = p;
  138.     *p = *current;
  139.     p->did_exec = 0;
  140.     p->kernel_stack_page = 0;
  141.     p->state = TASK_UNINTERRUPTIBLE;
  142.     p->flags &= ~(PF_PTRACED|PF_TRACESYS);
  143.     p->pid = last_pid;
  144.     p->swappable = 1;
  145.     p->p_pptr = p->p_opptr = current;
  146.     p->p_cptr = NULL;
  147.     SET_LINKS(p);
  148.     p->signal = 0;
  149.     p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
  150.     p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
  151.     p->leader = 0;        /* process leadership doesn't inherit */
  152.     p->utime = p->stime = 0;
  153.     p->cutime = p->cstime = 0;
  154.     p->min_flt = p->maj_flt = 0;
  155.     p->cmin_flt = p->cmaj_flt = 0;
  156.     p->start_time = jiffies;
  157. /*
  158.  * set up new TSS and kernel stack
  159.  */
  160.     if (!(p->kernel_stack_page = __get_free_page(GFP_KERNEL)))
  161.         goto bad_fork_cleanup;
  162.     p->tss.es = KERNEL_DS;
  163.     p->tss.cs = KERNEL_CS;
  164.     p->tss.ss = KERNEL_DS;
  165.     p->tss.ds = KERNEL_DS;
  166.     p->tss.fs = USER_DS;
  167.     p->tss.gs = KERNEL_DS;
  168.     p->tss.ss0 = KERNEL_DS;
  169.     p->tss.esp0 = p->kernel_stack_page + PAGE_SIZE;
  170.     p->tss.tr = _TSS(nr);
  171.     childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
  172.     p->tss.esp = (unsigned long) childregs;
  173.     p->tss.eip = (unsigned long) ret_from_sys_call;
  174.     *childregs = regs;
  175.     childregs->eax = 0;
  176.     p->tss.back_link = 0;
  177.     p->tss.eflags = regs.eflags & 0xffffcfff;    /* iopl is always 0 for a new process */
  178.     if (IS_CLONE) {
  179.         if (regs.ebx)
  180.             childregs->esp = regs.ebx;
  181.         clone_flags = regs.ecx;
  182.         if (childregs->esp == regs.esp)
  183.             clone_flags |= COPYVM;
  184.     }
  185.     p->exit_signal = clone_flags & CSIGNAL;
  186.     p->tss.ldt = _LDT(nr);
  187.     if (p->ldt) {
  188.         p->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
  189.         if (p->ldt != NULL)
  190.             memcpy(p->ldt, current->ldt, LDT_ENTRIES*LDT_ENTRY_SIZE);
  191.     }
  192.     p->tss.bitmap = offsetof(struct tss_struct,io_bitmap);
  193.     for (i = 0; i < IO_BITMAP_SIZE+1 ; i++) /* IO bitmap is actually SIZE+1 */
  194.         p->tss.io_bitmap[i] = ~0;
  195.     if (last_task_used_math == current)
  196.         __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387));
  197.     p->semun = NULL; p->shm = NULL;
  198.     if (copy_vm(p) || shm_fork(current, p))
  199.         goto bad_fork_cleanup;
  200.     if (clone_flags & COPYFD) {
  201.         for (i=0; i<NR_OPEN;i++)
  202.             if ((f = p->filp[i]) != NULL)
  203.                 p->filp[i] = copy_fd(f);
  204.     } else {
  205.         for (i=0; i<NR_OPEN;i++)
  206.             if ((f = p->filp[i]) != NULL)
  207.                 f->f_count++;
  208.     }
  209.     if (current->pwd)
  210.         current->pwd->i_count++;
  211.     if (current->root)
  212.         current->root->i_count++;
  213.     if (current->executable)
  214.         current->executable->i_count++;
  215.     dup_mmap(p);
  216.     set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
  217.     if (p->ldt)
  218.         set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,p->ldt, 512);
  219.     else
  220.         set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&default_ldt, 1);
  221.  
  222.     p->counter = current->counter >> 1;
  223.     p->state = TASK_RUNNING;    /* do this last, just in case */
  224.     return p->pid;
  225. bad_fork_cleanup:
  226.     task[nr] = NULL;
  227.     REMOVE_LINKS(p);
  228.     free_page(p->kernel_stack_page);
  229. bad_fork_free:
  230.     free_page((long) p);
  231. bad_fork:
  232.     return -EAGAIN;
  233. }
  234.