![Thomas Gleixner](/assets/img/avatar_default.png)
Instead of relying on PF_EXITING use an explicit state for the futex exit and set it in the futex exit function. This moves the smp barrier and the lock/unlock serialization into the futex code. As with the DEAD state this is restricted to the exit path as exec continues to use the same task struct. This allows to simplify that logic in a next step. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Ingo Molnar <mingo@kernel.org> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/20191106224556.539409004@linutronix.de
90 lines
2.4 KiB
C
90 lines
2.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_FUTEX_H
|
|
#define _LINUX_FUTEX_H
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/ktime.h>
|
|
|
|
#include <uapi/linux/futex.h>
|
|
|
|
struct inode;
|
|
struct mm_struct;
|
|
struct task_struct;
|
|
|
|
/*
|
|
* Futexes are matched on equal values of this key.
|
|
* The key type depends on whether it's a shared or private mapping.
|
|
* Don't rearrange members without looking at hash_futex().
|
|
*
|
|
* offset is aligned to a multiple of sizeof(u32) (== 4) by definition.
|
|
* We use the two low order bits of offset to tell what is the kind of key :
|
|
* 00 : Private process futex (PTHREAD_PROCESS_PRIVATE)
|
|
* (no reference on an inode or mm)
|
|
* 01 : Shared futex (PTHREAD_PROCESS_SHARED)
|
|
* mapped on a file (reference on the underlying inode)
|
|
* 10 : Shared futex (PTHREAD_PROCESS_SHARED)
|
|
* (but private mapping on an mm, and reference taken on it)
|
|
*/
|
|
|
|
#define FUT_OFF_INODE 1 /* We set bit 0 if key has a reference on inode */
|
|
#define FUT_OFF_MMSHARED 2 /* We set bit 1 if key has a reference on mm */
|
|
|
|
union futex_key {
|
|
struct {
|
|
unsigned long pgoff;
|
|
struct inode *inode;
|
|
int offset;
|
|
} shared;
|
|
struct {
|
|
unsigned long address;
|
|
struct mm_struct *mm;
|
|
int offset;
|
|
} private;
|
|
struct {
|
|
unsigned long word;
|
|
void *ptr;
|
|
int offset;
|
|
} both;
|
|
};
|
|
|
|
#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } }
|
|
|
|
#ifdef CONFIG_FUTEX
|
|
enum {
|
|
FUTEX_STATE_OK,
|
|
FUTEX_STATE_EXITING,
|
|
FUTEX_STATE_DEAD,
|
|
};
|
|
|
|
static inline void futex_init_task(struct task_struct *tsk)
|
|
{
|
|
tsk->robust_list = NULL;
|
|
#ifdef CONFIG_COMPAT
|
|
tsk->compat_robust_list = NULL;
|
|
#endif
|
|
INIT_LIST_HEAD(&tsk->pi_state_list);
|
|
tsk->pi_state_cache = NULL;
|
|
tsk->futex_state = FUTEX_STATE_OK;
|
|
}
|
|
|
|
void futex_exit_recursive(struct task_struct *tsk);
|
|
void futex_exit_release(struct task_struct *tsk);
|
|
void futex_exec_release(struct task_struct *tsk);
|
|
|
|
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
|
|
u32 __user *uaddr2, u32 val2, u32 val3);
|
|
#else
|
|
static inline void futex_init_task(struct task_struct *tsk) { }
|
|
static inline void futex_exit_recursive(struct task_struct *tsk) { }
|
|
static inline void futex_exit_release(struct task_struct *tsk) { }
|
|
static inline void futex_exec_release(struct task_struct *tsk) { }
|
|
static inline long do_futex(u32 __user *uaddr, int op, u32 val,
|
|
ktime_t *timeout, u32 __user *uaddr2,
|
|
u32 val2, u32 val3)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
#endif
|