patch-1.3.22 linux/kernel/fork.c
Next file: linux/kernel/ksyms.c
Previous file: linux/kernel/exit.c
Back to the patch index
Back to the overall index
- Lines: 202
- Date:
Thu Aug 31 13:56:20 1995
- Orig file:
v1.3.21/linux/kernel/fork.c
- Orig date:
Tue Jul 25 18:21:23 1995
diff -u --recursive --new-file v1.3.21/linux/kernel/fork.c linux/kernel/fork.c
@@ -24,6 +24,25 @@
#include <asm/segment.h>
#include <asm/system.h>
+/*
+ * This is how a process data structure is allocated. In most
+ * cases, the "tsk" pointers point to the same allocation unit
+ * substructures, but if the new process shares part (or all)
+ * of the sub-units with the parent process, the tsk pointers
+ * may point to the parent instead.
+ *
+ * Regardless, we always allocate the full allocation unit, as
+ * the normal fork() semantics require all of them and doing
+ * suballocations would be wasteful.
+ */
+struct allocation_struct {
+ struct task_struct tsk;
+ struct sigaction sigaction[32];
+ struct fs_struct fs;
+ struct files_struct files;
+ struct mm_struct mm;
+};
+
int nr_tasks=1;
int nr_running=1;
long last_pid=0;
@@ -60,28 +79,6 @@
return free_task;
}
-static struct file * copy_fd(struct file * old_file)
-{
- struct file * new_file = get_empty_filp();
- int error;
-
- if (new_file) {
- memcpy(new_file,old_file,sizeof(struct file));
- new_file->f_count = 1;
- if (new_file->f_inode)
- new_file->f_inode->i_count++;
- if (new_file->f_op && new_file->f_op->open) {
- error = new_file->f_op->open(new_file->f_inode,new_file);
- if (error) {
- iput(new_file->f_inode);
- new_file->f_count = 0;
- new_file = NULL;
- }
- }
- }
- return new_file;
-}
-
static int dup_mmap(struct task_struct * tsk)
{
struct vm_area_struct * mpnt, **p, *tmp;
@@ -113,50 +110,74 @@
return 0;
}
-/*
- * SHAREFD not yet implemented..
- */
-static void copy_files(unsigned long clone_flags, struct task_struct * p)
+static int copy_mm(unsigned long clone_flags, struct allocation_struct * u)
{
- int i;
- struct file * f;
+ if (clone_flags & CLONE_VM) {
+ if (clone_page_tables(&u->tsk))
+ return -1;
+ current->mm->count++;
+ mem_map[MAP_NR(current->mm)]++;
+ return 0;
+ }
+ u->tsk.mm = &u->mm;
+ u->mm = *current->mm;
+ u->mm.count = 1;
+ u->mm.min_flt = u->mm.maj_flt = 0;
+ u->mm.cmin_flt = u->mm.cmaj_flt = 0;
+ if (copy_page_tables(&u->tsk))
+ return -1;
+ if (dup_mmap(&u->tsk))
+ return -1;
+ mem_map[MAP_NR(u)]++;
+ return 0;
+}
- if (clone_flags & COPYFD) {
- for (i=0; i<NR_OPEN;i++)
- if ((f = p->files->fd[i]) != NULL)
- p->files->fd[i] = copy_fd(f);
- } else {
- for (i=0; i<NR_OPEN;i++)
- if ((f = p->files->fd[i]) != NULL)
- f->f_count++;
+static void copy_fs(unsigned long clone_flags, struct allocation_struct * u)
+{
+ if (clone_flags & CLONE_FS) {
+ current->fs->count++;
+ mem_map[MAP_NR(current->fs)]++;
+ return;
}
+ u->tsk.fs = &u->fs;
+ u->fs = *current->fs;
+ u->fs.count = 1;
+ if (u->fs.pwd)
+ u->fs.pwd->i_count++;
+ if (u->fs.root)
+ u->fs.root->i_count++;
+ mem_map[MAP_NR(u)]++;
}
-/*
- * CLONEVM not yet correctly implemented: needs to clone the mmap
- * instead of duplicating it..
- */
-static int copy_mm(unsigned long clone_flags, struct task_struct * p)
+static void copy_files(unsigned long clone_flags, struct allocation_struct * u)
{
- if (clone_flags & COPYVM) {
- p->mm->min_flt = p->mm->maj_flt = 0;
- p->mm->cmin_flt = p->mm->cmaj_flt = 0;
- if (copy_page_tables(p))
- return 1;
- return dup_mmap(p);
- } else {
- if (clone_page_tables(p))
- return 1;
- return dup_mmap(p); /* wrong.. */
+ int i;
+
+ if (clone_flags & CLONE_FILES) {
+ current->files->count++;
+ mem_map[MAP_NR(current->files)]++;
+ return;
+ }
+ u->tsk.files = &u->files;
+ u->files = *current->files;
+ u->files.count = 1;
+ for (i = 0; i < NR_OPEN; i++) {
+ struct file * f = u->files.fd[i];
+ if (f)
+ f->f_count++;
}
+ mem_map[MAP_NR(u)]++;
}
-static void copy_fs(unsigned long clone_flags, struct task_struct * p)
-{
- if (current->fs->pwd)
- current->fs->pwd->i_count++;
- if (current->fs->root)
- current->fs->root->i_count++;
+static void copy_sighand(unsigned long clone_flags, struct allocation_struct * u)
+{
+ if (clone_flags & CLONE_SIGHAND) {
+ mem_map[MAP_NR(current->sigaction)]++;
+ return;
+ }
+ u->tsk.sigaction = u->sigaction;
+ memcpy(u->sigaction, current->sigaction, sizeof(u->sigaction));
+ mem_map[MAP_NR(u)]++;
}
/*
@@ -169,9 +190,12 @@
int nr;
unsigned long new_stack;
struct task_struct *p;
+ struct allocation_struct *alloc;
- if(!(p = (struct task_struct*)__get_free_page(GFP_KERNEL)))
+ alloc = (struct allocation_struct *) __get_free_page(GFP_KERNEL);
+ if (!alloc)
goto bad_fork;
+ p = &alloc->tsk;
new_stack = get_free_page(GFP_KERNEL);
if (!new_stack)
goto bad_fork_free;
@@ -206,18 +230,18 @@
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
p->start_time = jiffies;
- p->mm->swappable = 0; /* don't try to swap it out before it's set up */
task[nr] = p;
SET_LINKS(p);
nr_tasks++;
/* copy all the process information */
copy_thread(nr, clone_flags, usp, p, regs);
- if (copy_mm(clone_flags, p))
+ if (copy_mm(clone_flags, alloc))
goto bad_fork_cleanup;
p->semundo = NULL;
- copy_files(clone_flags, p);
- copy_fs(clone_flags, p);
+ copy_files(clone_flags, alloc);
+ copy_fs(clone_flags, alloc);
+ copy_sighand(clone_flags, alloc);
/* ok, now we should be set up.. */
p->mm->swappable = 1;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this