Messages in this thread Patch in this message | | | Subject | [PATCH RFC 07/13] kin_lock: Implement helpers for kin_lock locking. | From | Kirill Tkhai <> | Date | Mon, 25 May 2015 20:45:25 +0300 |
| |
Signed-off-by: Kirill Tkhai <ktkhai@odin.com> --- 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;
| |