lkml.org 
[lkml]   [2019]   [Sep]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip: sched/urgent] tasks: Add a count of task RCU users
    The following commit has been merged into the sched/urgent branch of tip:

    Commit-ID: 3fbd7ee285b2bbc6eebd15a3c8786d9776a402a8
    Gitweb: https://git.kernel.org/tip/3fbd7ee285b2bbc6eebd15a3c8786d9776a402a8
    Author: Eric W. Biederman <ebiederm@xmission.com>
    AuthorDate: Sat, 14 Sep 2019 07:33:34 -05:00
    Committer: Ingo Molnar <mingo@kernel.org>
    CommitterDate: Wed, 25 Sep 2019 17:42:29 +02:00

    tasks: Add a count of task RCU users

    Add a count of the number of RCU users (currently 1) of the task
    struct so that we can later add the scheduler case and get rid of the
    very subtle task_rcu_dereference(), and just use rcu_dereference().

    As suggested by Oleg have the count overlap rcu_head so that no
    additional space in task_struct is required.

    Inspired-by: Linus Torvalds <torvalds@linux-foundation.org>
    Inspired-by: Oleg Nesterov <oleg@redhat.com>
    Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Chris Metcalf <cmetcalf@ezchip.com>
    Cc: Christoph Lameter <cl@linux.com>
    Cc: Davidlohr Bueso <dave@stgolabs.net>
    Cc: Kirill Tkhai <tkhai@yandex.ru>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Mike Galbraith <efault@gmx.de>
    Cc: Paul E. McKenney <paulmck@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Russell King - ARM Linux admin <linux@armlinux.org.uk>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Link: https://lkml.kernel.org/r/87woebdplt.fsf_-_@x220.int.ebiederm.org
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    ---
    include/linux/sched.h | 5 ++++-
    include/linux/sched/task.h | 1 +
    kernel/exit.c | 7 ++++++-
    kernel/fork.c | 7 +++----
    4 files changed, 14 insertions(+), 6 deletions(-)

    diff --git a/include/linux/sched.h b/include/linux/sched.h
    index e2e9196..8e43e54 100644
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -1147,7 +1147,10 @@ struct task_struct {

    struct tlbflush_unmap_batch tlb_ubc;

    - struct rcu_head rcu;
    + union {
    + refcount_t rcu_users;
    + struct rcu_head rcu;
    + };

    /* Cache last used pipe for splice(): */
    struct pipe_inode_info *splice_pipe;
    diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
    index 3d90ed8..153a683 100644
    --- a/include/linux/sched/task.h
    +++ b/include/linux/sched/task.h
    @@ -120,6 +120,7 @@ static inline void put_task_struct(struct task_struct *t)
    }

    struct task_struct *task_rcu_dereference(struct task_struct **ptask);
    +void put_task_struct_rcu_user(struct task_struct *task);

    #ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT
    extern int arch_task_struct_size __read_mostly;
    diff --git a/kernel/exit.c b/kernel/exit.c
    index 22ab6a4..3bcaec2 100644
    --- a/kernel/exit.c
    +++ b/kernel/exit.c
    @@ -182,6 +182,11 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
    put_task_struct(tsk);
    }

    +void put_task_struct_rcu_user(struct task_struct *task)
    +{
    + if (refcount_dec_and_test(&task->rcu_users))
    + call_rcu(&task->rcu, delayed_put_task_struct);
    +}

    void release_task(struct task_struct *p)
    {
    @@ -222,7 +227,7 @@ repeat:

    write_unlock_irq(&tasklist_lock);
    release_thread(p);
    - call_rcu(&p->rcu, delayed_put_task_struct);
    + put_task_struct_rcu_user(p);

    p = leader;
    if (unlikely(zap_leader))
    diff --git a/kernel/fork.c b/kernel/fork.c
    index 1d1cd06..7eefe33 100644
    --- a/kernel/fork.c
    +++ b/kernel/fork.c
    @@ -902,10 +902,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
    if (orig->cpus_ptr == &orig->cpus_mask)
    tsk->cpus_ptr = &tsk->cpus_mask;

    - /*
    - * One for us, one for whoever does the "release_task()" (usually
    - * parent)
    - */
    + /* One for the user space visible state that goes away when reaped. */
    + refcount_set(&tsk->rcu_users, 1);
    + /* One for the rcu users, and one for the scheduler */
    refcount_set(&tsk->usage, 2);
    #ifdef CONFIG_BLK_DEV_IO_TRACE
    tsk->btrace_seq = 0;
    \
     
     \ /
      Last update: 2019-09-27 10:11    [W:4.763 / U:0.100 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site