diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-18 17:17:51 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-18 17:17:51 +0000 |
commit | f1382dc4850bb459d24a81c6cb0ef93ea7bd4a79 (patch) | |
tree | 225271a3d5dcd4e9dea5ee393556abd754c964b1 /kernel/fork.c | |
parent | 135b00fc2e90e605ac2a96b20b0ebd93851a3f89 (diff) |
o Merge with Linux 2.1.90.
o Divide L1 cache sizes by 1024 before printing, makes the numbers a
bit more credible ...
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 38c98b0a8..a08aa2c64 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -41,7 +41,6 @@ kmem_cache_t *mm_cachep; kmem_cache_t *files_cachep; struct task_struct *pidhash[PIDHASH_SZ]; -spinlock_t pidhash_lock = SPIN_LOCK_UNLOCKED; struct task_struct **tarray_freelist = NULL; spinlock_t taskslot_lock = SPIN_LOCK_UNLOCKED; @@ -263,6 +262,9 @@ fail_nomem: /* * Allocate and initialize an mm_struct. + * + * NOTE! The mm mutex will be locked until the + * caller decides that all systems are go.. */ struct mm_struct * mm_alloc(void) { @@ -275,7 +277,7 @@ struct mm_struct * mm_alloc(void) mm->count = 1; mm->map_count = 0; mm->def_flags = 0; - mm->mmap_sem = MUTEX; + mm->mmap_sem = MUTEX_LOCKED; /* * Leave mm->pgd set to the parent's pgd * so that pgd_offset() is always valid. @@ -328,6 +330,7 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk) retval = dup_mmap(mm); if (retval) goto free_pt; + up(&mm->mmap_sem); return 0; free_mm: @@ -375,44 +378,66 @@ static inline int copy_fdset(fd_set *dst, fd_set *src) return __copy_fdset(dst->fds_bits, src->fds_bits); } -static inline int copy_files(unsigned long clone_flags, struct task_struct * tsk) +static int copy_files(unsigned long clone_flags, struct task_struct * tsk) { - int i; struct files_struct *oldf, *newf; struct file **old_fds, **new_fds; + int size, i, error = 0; /* * A background process may not have any files ... */ oldf = current->files; if (!oldf) - return 0; + goto out; if (clone_flags & CLONE_FILES) { oldf->count++; - return 0; + goto out; } + tsk->files = NULL; + error = -ENOMEM; newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); - tsk->files = newf; if (!newf) - return -1; + goto out; + + /* + * Allocate the fd array, using get_free_page() if possible. + * Eventually we want to make the array size variable ... + */ + size = NR_OPEN * sizeof(struct file *); + if (size == PAGE_SIZE) + new_fds = (struct file **) __get_free_page(GFP_KERNEL); + else + new_fds = (struct file **) kmalloc(size, GFP_KERNEL); + if (!new_fds) + goto out_release; + memset((void *) new_fds, 0, size); newf->count = 1; + newf->max_fds = NR_OPEN; + newf->fd = new_fds; newf->close_on_exec = oldf->close_on_exec; - i = copy_fdset(&newf->open_fds,&oldf->open_fds); + i = copy_fdset(&newf->open_fds, &oldf->open_fds); old_fds = oldf->fd; - new_fds = newf->fd; for (; i != 0; i--) { struct file * f = *old_fds; old_fds++; *new_fds = f; - new_fds++; if (f) f->f_count++; + new_fds++; } - return 0; + tsk->files = newf; + error = 0; +out: + return error; + +out_release: + kmem_cache_free(files_cachep, newf); + goto out; } static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk) @@ -495,8 +520,15 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) p->start_time = jiffies; p->tarray_ptr = &task[nr]; *p->tarray_ptr = p; - SET_LINKS(p); - hash_pid(p); + + { + unsigned long flags; + write_lock_irqsave(&tasklist_lock, flags); + SET_LINKS(p); + hash_pid(p); + write_unlock_irqrestore(&tasklist_lock, flags); + } + nr_tasks++; error = -ENOMEM; @@ -553,8 +585,15 @@ bad_fork_cleanup: if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); add_free_taskslot(p->tarray_ptr); - unhash_pid(p); - REMOVE_LINKS(p); + + { + unsigned long flags; + write_lock_irqsave(&tasklist_lock, flags); + unhash_pid(p); + REMOVE_LINKS(p); + write_unlock_irqrestore(&tasklist_lock, flags); + } + nr_tasks--; bad_fork_free: free_task_struct(p); |