]> git.hungrycats.org Git - linux/commitdiff
[PATCH] threading enhancements, tid-2.5.48-C0
authorIngo Molnar <mingo@elte.hu>
Thu, 21 Nov 2002 04:25:03 +0000 (20:25 -0800)
committerIngo Molnar <mingo@elte.hu>
Thu, 21 Nov 2002 04:25:03 +0000 (20:25 -0800)
Support more flexible child pid set/clear operations for NPTL.

there's one more improvement in the interface: set the parent-TID prior
doing the copy_mm() - this helps cfork() to pass the TID to the child as
well.

arch/i386/kernel/entry.S
arch/i386/kernel/process.c
arch/i386/kernel/smpboot.c
include/linux/sched.h
kernel/fork.c
kernel/sched.c

index 830c84025de1329cc44bfbb41c71cc39ecf8f248..6a9b0de4421c6f6bf8114bfacdd22af23ab912f5 100644 (file)
@@ -170,10 +170,8 @@ ENTRY(lcall27)
 
 
 ENTRY(ret_from_fork)
-#if CONFIG_SMP || CONFIG_PREEMPT
        # NOTE: this function takes a parameter but it's unused on x86.
        call schedule_tail
-#endif
        GET_THREAD_INFO(%ebx)
        jmp syscall_exit
 
index d6640642ae3db4b8b1113bcc9509fad77873efdb..253f08d92da3044a02349a79bd62ef0536c8805c 100644 (file)
@@ -226,7 +226,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        regs.eflags = 0x286;
 
        /* Ok, create the new process.. */
-       p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL);
+       p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
        return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -288,7 +288,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
        struct_cpy(childregs, regs);
        childregs->eax = 0;
        childregs->esp = esp;
-       p->user_tid = NULL;
+       p->set_child_tid = p->clear_child_tid = NULL;
 
        p->thread.esp = (unsigned long) childregs;
        p->thread.esp0 = (unsigned long) (childregs+1);
@@ -503,7 +503,7 @@ asmlinkage int sys_fork(struct pt_regs regs)
 {
        struct task_struct *p;
 
-       p = do_fork(SIGCHLD, regs.esp, &regs, 0, NULL);
+       p = do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
        return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -512,14 +512,15 @@ asmlinkage int sys_clone(struct pt_regs regs)
        struct task_struct *p;
        unsigned long clone_flags;
        unsigned long newsp;
-       int *user_tid;
+       int *parent_tidptr, *child_tidptr;
 
        clone_flags = regs.ebx;
        newsp = regs.ecx;
-       user_tid = (int *)regs.edx;
+       parent_tidptr = (int *)regs.edx;
+       child_tidptr = (int *)regs.edi;
        if (!newsp)
                newsp = regs.esp;
-       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, user_tid);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, parent_tidptr, child_tidptr);
        return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -537,7 +538,7 @@ asmlinkage int sys_vfork(struct pt_regs regs)
 {
        struct task_struct *p;
 
-       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL);
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
        return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
index 876e95fd57ce54629ff619d338e1cf7437108e67..66c93c67d7dbc17cd5a9420bb43ec3b3874f617f 100644 (file)
@@ -499,7 +499,7 @@ static struct task_struct * __init fork_by_hand(void)
         * don't care about the eip and regs settings since
         * we'll never reschedule the forked task.
         */
-       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
 }
 
 /* which physical APIC ID maps to which logical CPU number */
index afc7c0462ccd743a59c6a461bdfe7145177365a7..7946bd8cb0ad67b6742c23ef78d6621f2fc604a5 100644 (file)
@@ -46,10 +46,11 @@ struct exec_domain;
 #define CLONE_NEWNS    0x00020000      /* New namespace group? */
 #define CLONE_SYSVSEM  0x00040000      /* share system V SEM_UNDO semantics */
 #define CLONE_SETTLS   0x00080000      /* create a new TLS for the child */
-#define CLONE_SETTID   0x00100000      /* write the TID back to userspace */
-#define CLONE_CLEARTID 0x00200000      /* clear the userspace TID */
-#define CLONE_DETACHED 0x00400000      /* parent wants no child-exit signal */
-#define CLONE_UNTRACED  0x00800000     /* set if the tracing process can't force CLONE_PTRACE on this clone */
+#define CLONE_PARENT_SETTID    0x00100000      /* set the TID in the parent */
+#define CLONE_CHILD_CLEARTID   0x00200000      /* clear the TID in the child */
+#define CLONE_DETACHED         0x00400000      /* parent wants no child-exit signal */
+#define CLONE_UNTRACED         0x00800000      /* set if the tracing process can't force CLONE_PTRACE on this clone */
+#define CLONE_CHILD_SETTID     0x01000000      /* set the TID in the child */
 
 /*
  * List of flags we want to share for kernel threads,
@@ -332,7 +333,8 @@ struct task_struct {
 
        wait_queue_head_t wait_chldexit;        /* for wait4() */
        struct completion *vfork_done;          /* for vfork() */
-       int *user_tid;                          /* for CLONE_CLEARTID */
+       int *set_child_tid;                     /* CLONE_CHILD_SETTID */
+       int *clear_child_tid;                   /* CLONE_CHILD_CLEARTID */
 
        unsigned long rt_priority;
        unsigned long it_real_value, it_prof_value, it_virt_value;
@@ -585,7 +587,7 @@ extern void daemonize(void);
 extern task_t *child_reaper;
 
 extern int do_execve(char *, char **, char **, struct pt_regs *);
-extern struct task_struct *do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int *);
+extern struct task_struct *do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int *, int *);
 
 #ifdef CONFIG_SMP
 extern void wait_task_inactive(task_t * p);
index f89734b831ac984ab4cb66a9dd417d8047f6d1bc..27cf572cedf867d747e8966341a6b9045ab016b6 100644 (file)
@@ -408,16 +408,16 @@ void mm_release(void)
                tsk->vfork_done = NULL;
                complete(vfork_done);
        }
-       if (tsk->user_tid) {
-               int * user_tid = tsk->user_tid;
-               tsk->user_tid = NULL;
+       if (tsk->clear_child_tid) {
+               int * tidptr = tsk->clear_child_tid;
+               tsk->clear_child_tid = NULL;
 
                /*
                 * We dont check the error code - if userspace has
                 * not set up a proper pointer then tough luck.
                 */
-               put_user(0, user_tid);
-               sys_futex((unsigned long)user_tid, FUTEX_WAKE, 1, NULL);
+               put_user(0, tidptr);
+               sys_futex((unsigned long)tidptr, FUTEX_WAKE, 1, NULL);
        }
 }
 
@@ -680,9 +680,9 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
        p->flags = new_flags;
 }
 
-asmlinkage int sys_set_tid_address(int *user_tid)
+asmlinkage int sys_set_tid_address(int *tidptr)
 {
-       current->user_tid = user_tid;
+       current->clear_child_tid = tidptr;
 
        return current->pid;
 }
@@ -699,7 +699,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                            unsigned long stack_start,
                            struct pt_regs *regs,
                            unsigned long stack_size,
-                           int *user_tid)
+                           int *parent_tidptr,
+                           int *child_tidptr)
 {
        int retval;
        struct task_struct *p = NULL;
@@ -766,6 +767,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                if (p->pid == -1)
                        goto bad_fork_cleanup;
        }
+       retval = -EFAULT;
+       if (clone_flags & CLONE_PARENT_SETTID)
+               if (put_user(p->pid, parent_tidptr))
+                       goto bad_fork_cleanup;
+
        p->proc_dentry = NULL;
 
        INIT_LIST_HEAD(&p->run_list);
@@ -823,19 +829,14 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
        if (retval)
                goto bad_fork_cleanup_namespace;
-       /*
-        * Notify the child of the TID?
-        */
-       retval = -EFAULT;
-       if (clone_flags & CLONE_SETTID)
-               if (put_user(p->pid, user_tid))
-                       goto bad_fork_cleanup_namespace;
 
+       if (clone_flags & CLONE_CHILD_SETTID)
+               p->set_child_tid = child_tidptr;
        /*
-        * Does the userspace VM want the TID cleared on mm_release()?
+        * Clear TID on mm_release()?
         */
-       if (clone_flags & CLONE_CLEARTID)
-               p->user_tid = user_tid;
+       if (clone_flags & CLONE_CHILD_CLEARTID)
+               p->clear_child_tid = child_tidptr;
 
        /*
         * Syscall tracing should be turned off in the child regardless
@@ -1004,7 +1005,8 @@ struct task_struct *do_fork(unsigned long clone_flags,
                            unsigned long stack_start,
                            struct pt_regs *regs,
                            unsigned long stack_size,
-                           int *user_tid)
+                           int *parent_tidptr,
+                           int *child_tidptr)
 {
        struct task_struct *p;
        int trace = 0;
@@ -1015,7 +1017,7 @@ struct task_struct *do_fork(unsigned long clone_flags,
                        clone_flags |= CLONE_PTRACE;
        }
 
-       p = copy_process(clone_flags, stack_start, regs, stack_size, user_tid);
+       p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr);
        if (!IS_ERR(p)) {
                struct completion vfork;
 
index 6d0ac320bcbc86eb2e9bab3e4202f75503381601..b446ce8eecc1b4e2ad4b480f9b0e5afc54662f43 100644 (file)
@@ -503,12 +503,12 @@ void sched_exit(task_t * p)
  * schedule_tail - first thing a freshly forked thread must call.
  * @prev: the thread we just switched away from.
  */
-#if CONFIG_SMP || CONFIG_PREEMPT
 asmlinkage void schedule_tail(task_t *prev)
 {
        finish_arch_switch(this_rq(), prev);
+       if (current->set_child_tid)
+               put_user(current->pid, current->set_child_tid);
 }
-#endif
 
 /*
  * context_switch - switch to the new MM and the new