lkml.org 
[lkml]   [2023]   [Jul]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[RFC][PATCH 03/10] futex: Flag conversion
    Futex has 3 sets of flags:

    - legacy futex op bits
    - futex2 flags
    - internal flags

    Add a few helpers to convert from the API flags into the internal
    flags.

    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    ---
    kernel/futex/futex.h | 48 +++++++++++++++++++++++++++++++++++++++++++++---
    kernel/futex/syscalls.c | 21 +++++++++++++--------
    kernel/futex/waitwake.c | 4 ++--
    3 files changed, 60 insertions(+), 13 deletions(-)

    --- a/kernel/futex/futex.h
    +++ b/kernel/futex/futex.h
    @@ -16,8 +16,15 @@
    * Futex flags used to encode options to functions and preserve them across
    * restarts.
    */
    +#define FLAGS_SIZE_8 0x00
    +#define FLAGS_SIZE_16 0x01
    +#define FLAGS_SIZE_32 0x02
    +#define FLAGS_SIZE_64 0x03
    +
    +#define FLAGS_SIZE_MASK 0x03
    +
    #ifdef CONFIG_MMU
    -# define FLAGS_SHARED 0x01
    +# define FLAGS_SHARED 0x10
    #else
    /*
    * NOMMU does not have per process address space. Let the compiler optimize
    @@ -25,8 +32,43 @@
    */
    # define FLAGS_SHARED 0x00
    #endif
    -#define FLAGS_CLOCKRT 0x02
    -#define FLAGS_HAS_TIMEOUT 0x04
    +#define FLAGS_CLOCKRT 0x20
    +#define FLAGS_HAS_TIMEOUT 0x40
    +#define FLAGS_NUMA 0x80
    +
    +/* FUTEX_ to FLAGS_ */
    +static inline unsigned int futex_to_flags(unsigned int op)
    +{
    + unsigned int flags = FLAGS_SIZE_32;
    +
    + if (!(op & FUTEX_PRIVATE_FLAG))
    + flags |= FLAGS_SHARED;
    +
    + if (op & FUTEX_CLOCK_REALTIME)
    + flags |= FLAGS_CLOCKRT;
    +
    + return flags;
    +}
    +
    +/* FUTEX2_ to FLAGS_ */
    +static inline unsigned int futex2_to_flags(unsigned int flags2)
    +{
    + unsigned int flags = flags2 & FUTEX2_64;
    +
    + if (!(flags2 & FUTEX2_PRIVATE))
    + flags |= FLAGS_SHARED;
    +
    + if (flags2 & FUTEX2_NUMA)
    + flags |= FLAGS_NUMA;
    +
    + return flags;
    +}
    +
    +static inline unsigned int futex_size(unsigned int flags)
    +{
    + unsigned int size = flags & FLAGS_SIZE_MASK;
    + return 1 << size; /* {0,1,2,3} -> {1,2,4,8} */
    +}

    #ifdef CONFIG_FAIL_FUTEX
    extern bool should_fail_futex(bool fshared);
    --- a/kernel/futex/syscalls.c
    +++ b/kernel/futex/syscalls.c
    @@ -85,15 +85,12 @@ SYSCALL_DEFINE3(get_robust_list, int, pi
    long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
    u32 __user *uaddr2, u32 val2, u32 val3)
    {
    + unsigned int flags = futex_to_flags(op);
    int cmd = op & FUTEX_CMD_MASK;
    - unsigned int flags = 0;

    - if (!(op & FUTEX_PRIVATE_FLAG))
    - flags |= FLAGS_SHARED;
    -
    - if (op & FUTEX_CLOCK_REALTIME) {
    - flags |= FLAGS_CLOCKRT;
    - if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI &&
    + if (flags & FLAGS_CLOCKRT) {
    + if (cmd != FUTEX_WAIT_BITSET &&
    + cmd != FUTEX_WAIT_REQUEUE_PI &&
    cmd != FUTEX_LOCK_PI2)
    return -ENOSYS;
    }
    @@ -201,6 +198,8 @@ static int futex_parse_waitv(struct fute
    unsigned int i;

    for (i = 0; i < nr_futexes; i++) {
    + unsigned int bits, flags;
    +
    if (copy_from_user(&aux, &uwaitv[i], sizeof(aux)))
    return -EFAULT;

    @@ -210,7 +209,13 @@ static int futex_parse_waitv(struct fute
    if ((aux.flags & FUTEX2_64) != FUTEX2_32)
    return -EINVAL;

    - futexv[i].w.flags = aux.flags;
    + flags = futex2_to_flags(aux.flags);
    + bits = 8 * futex_size(flags);
    +
    + if (bits < 64 && aux.val >> bits)
    + return -EINVAL;
    +
    + futexv[i].w.flags = flags;
    futexv[i].w.val = aux.val;
    futexv[i].w.uaddr = aux.uaddr;
    futexv[i].q = futex_q_init;
    --- a/kernel/futex/waitwake.c
    +++ b/kernel/futex/waitwake.c
    @@ -419,11 +419,11 @@ static int futex_wait_multiple_setup(str
    */
    retry:
    for (i = 0; i < count; i++) {
    - if ((vs[i].w.flags & FUTEX_PRIVATE_FLAG) && retry)
    + if (!(vs[i].w.flags & FLAGS_SHARED) && retry)
    continue;

    ret = get_futex_key(u64_to_user_ptr(vs[i].w.uaddr),
    - !(vs[i].w.flags & FUTEX_PRIVATE_FLAG),
    + vs[i].w.flags & FLAGS_SHARED,
    &vs[i].q.key, FUTEX_READ);

    if (unlikely(ret))

    \
     
     \ /
      Last update: 2023-07-16 20:50    [W:6.798 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site