Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751375AbbEYRpg (ORCPT ); Mon, 25 May 2015 13:45:36 -0400 Received: from relay.parallels.com ([195.214.232.42]:44219 "EHLO relay.parallels.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750903AbbEYRpc (ORCPT ); Mon, 25 May 2015 13:45:32 -0400 Message-ID: <1432575925.6866.40.camel@odin.com> Subject: [PATCH RFC 07/13] kin_lock: Implement helpers for kin_lock locking. From: Kirill Tkhai To: CC: Oleg Nesterov , Andrew Morton , Ingo Molnar , "Peter Zijlstra" , Michal Hocko , "Rik van Riel" , Ionut Alexa , Peter Hurley , Kirill Tkhai Date: Mon, 25 May 2015 20:45:25 +0300 In-Reply-To: <20150525162722.5171.15901.stgit@pro> References: <20150525162722.5171.15901.stgit@pro> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.12.9-1+b1 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Originating-IP: [10.30.16.109] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8109 Lines: 326 Signed-off-by: Kirill Tkhai --- include/linux/sched.h | 302 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 58dc09f..6a810f3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1835,6 +1835,308 @@ static inline bool should_numa_migrate_memory(struct task_struct *p, } #endif +static inline void write_real_parent_lock(struct task_struct *p) +{ + struct task_struct *real_parent; + rcu_read_lock(); +again: + real_parent = p->real_parent; + write_lock(&real_parent->kin_lock); + if (real_parent != p->real_parent) { + write_unlock(&real_parent->kin_lock); + goto again; + } + rcu_read_unlock(); +} + +static inline void write_real_parent_lock_irq(struct task_struct *p) +{ + local_irq_disable(); + write_real_parent_lock(p); +} + +static inline void write_real_parent_unlock(struct task_struct *p) +{ + write_unlock(&p->real_parent->kin_lock); +} + +static inline void write_real_parent_unlock_irq(struct task_struct *p) +{ + write_unlock_irq(&p->real_parent->kin_lock); +} + +static inline void read_parent_lock(struct task_struct *p) +{ + struct task_struct *parent; + rcu_read_lock(); +again: + parent = p->parent; + read_lock(&parent->kin_lock); + if (parent != p->parent) { + read_unlock(&parent->kin_lock); + goto again; + } + rcu_read_unlock(); + +} + +static inline void read_parent_unlock(struct task_struct *p) +{ + read_unlock(&p->parent->kin_lock); +} + +static inline void read_real_parent_lock(struct task_struct *p) +{ + struct task_struct *real_parent; + rcu_read_lock(); +again: + real_parent = p->real_parent; + read_lock(&real_parent->kin_lock); + if (real_parent != p->real_parent) { + read_unlock(&real_parent->kin_lock); + goto again; + } + rcu_read_unlock(); + +} + +static inline void read_real_parent_unlock(struct task_struct *p) +{ + read_unlock(&p->real_parent->kin_lock); +} + +static inline void write_parent_lock(struct task_struct *p) +{ + struct task_struct *parent; + rcu_read_lock(); +again: + parent = p->parent; + write_lock(&parent->kin_lock); + if (parent != p->parent) { + write_unlock(&parent->kin_lock); + goto again; + } + rcu_read_unlock(); +} + +static inline void write_parent_lock_irq(struct task_struct *p) +{ + local_irq_disable(); + write_parent_lock(p); +} + +static inline void write_parent_unlock(struct task_struct *p) +{ + write_unlock(&p->parent->kin_lock); +} + +static inline void write_parent_unlock_irq(struct task_struct *p) +{ + write_unlock_irq(&p->parent->kin_lock); +} + +static inline void write_parent_and_given_lock(struct task_struct *child, + struct task_struct *given) +{ + struct task_struct *parent; + rcu_read_lock(); +again: + parent = child->parent; + if (parent <= given) { + write_lock(&parent->kin_lock); + if (parent != child->parent) { + write_unlock(&parent->kin_lock); + goto again; + } + if (parent != given) + write_lock(&given->kin_lock); + } else { + write_lock(&given->kin_lock); + write_lock(&parent->kin_lock); + if (parent != child->parent) { + write_unlock(&given->kin_lock); + write_unlock(&parent->kin_lock); + goto again; + } + } + rcu_read_unlock(); +} + +static inline void write_parent_and_given_lock_irq(struct task_struct *child, + struct task_struct *given) +{ + local_irq_disable(); + write_parent_and_given_lock(child, given); +} + +static inline void read_parent_and_given_lock(struct task_struct *child, + struct task_struct *given) +{ + struct task_struct *parent; + rcu_read_lock(); +again: + parent = child->parent; + if (parent <= given) { + read_lock(&parent->kin_lock); + if (parent != child->parent) { + read_unlock(&parent->kin_lock); + goto again; + } + if (parent != given) + read_lock(&given->kin_lock); + } else { + read_lock(&given->kin_lock); + read_lock(&parent->kin_lock); + if (parent != child->parent) { + read_unlock(&given->kin_lock); + read_unlock(&parent->kin_lock); + goto again; + } + } + rcu_read_unlock(); +} + +static inline void read_real_parent_and_given_lock(struct task_struct *child, + struct task_struct *given) +{ + struct task_struct *real_parent; + rcu_read_lock(); +again: + real_parent = child->real_parent; + if (real_parent <= given) { + read_lock(&real_parent->kin_lock); + if (real_parent != child->real_parent) { + read_unlock(&real_parent->kin_lock); + goto again; + } + if (real_parent != given) + read_lock(&given->kin_lock); + } else { + read_lock(&given->kin_lock); + read_lock(&real_parent->kin_lock); + if (real_parent != child->real_parent) { + read_unlock(&given->kin_lock); + read_unlock(&real_parent->kin_lock); + goto again; + } + } + rcu_read_unlock(); +} + +static inline void read_real_parent_and_given_unlock(struct task_struct *child, + struct task_struct *given) +{ + struct task_struct *real_parent = child->real_parent; + + if (real_parent != given) + read_unlock(&real_parent->kin_lock); + read_unlock(&given->kin_lock); +} +static inline void write_parent_and_real_parent_lock(struct task_struct *child) +{ + struct task_struct *parent, *real_parent; + rcu_read_lock(); +again: + parent = child->parent; + real_parent = child->real_parent; + if (parent <= real_parent) { + write_lock(&parent->kin_lock); + if (parent != child->parent) { + write_unlock(&parent->kin_lock); + goto again; + } + if (parent != real_parent) { + write_lock(&real_parent->kin_lock); + if (real_parent != child->real_parent) { + write_unlock(&parent->kin_lock); + write_unlock(&real_parent->kin_lock); + goto again; + } + } + } else { + write_lock(&real_parent->kin_lock); + write_lock(&parent->kin_lock); + if (real_parent != child->real_parent || + parent != child->parent) { + write_unlock(&real_parent->kin_lock); + write_unlock(&parent->kin_lock); + goto again; + } + } + rcu_read_unlock(); +} + +static inline void write_parent_and_real_parent_lock_irq(struct task_struct *child) +{ + local_irq_disable(); + write_parent_and_real_parent_lock(child); +} + +static inline void write_parent_and_real_parent_unlock(struct task_struct *child) +{ + struct task_struct *parent, *real_parent; + + parent = child->parent; + real_parent = child->real_parent; + + write_unlock(&real_parent->kin_lock); + if (parent != real_parent) + write_unlock(&parent->kin_lock); +} + +static inline void write_parent_and_real_parent_unlock_irq(struct task_struct *child) +{ + write_parent_and_real_parent_unlock(child); + local_irq_enable(); +} + +static inline void read_parent_and_real_parent_lock(struct task_struct *child) +{ + struct task_struct *parent, *real_parent; + rcu_read_lock(); +again: + parent = child->parent; + real_parent = child->real_parent; + if (parent <= real_parent) { + read_lock(&parent->kin_lock); + if (parent != child->parent) { + read_unlock(&parent->kin_lock); + goto again; + } + if (parent != real_parent) { + read_lock(&real_parent->kin_lock); + if (real_parent != child->real_parent) { + read_unlock(&parent->kin_lock); + read_unlock(&real_parent->kin_lock); + goto again; + } + } + } else { + read_lock(&real_parent->kin_lock); + read_lock(&parent->kin_lock); + if (real_parent != child->real_parent || + parent != child->parent) { + read_unlock(&real_parent->kin_lock); + read_unlock(&parent->kin_lock); + goto again; + } + } + rcu_read_unlock(); +} + +static inline void read_parent_and_real_parent_unlock(struct task_struct *child) +{ + struct task_struct *parent, *real_parent; + + parent = child->parent; + real_parent = child->real_parent; + + read_unlock(&real_parent->kin_lock); + if (parent != real_parent) + read_unlock(&parent->kin_lock); +} + + static inline struct pid *task_pid(struct task_struct *task) { return task->pids[PIDTYPE_PID].pid; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/