Commit 7a69a3b2 authored by André Almeida's avatar André Almeida
Browse files

futex2

parent 2409bd1f
......@@ -61,14 +61,34 @@ static BOOL crit_section_has_debuginfo(const RTL_CRITICAL_SECTION *crit)
static int wait_op = 128; /*FUTEX_WAIT|FUTEX_PRIVATE_FLAG*/
static int wake_op = 129; /*FUTEX_WAKE|FUTEX_PRIVATE_FLAG*/
/*
* wait for uaddr if (*uaddr == val)
*/
static int __futex_wait(void *uaddr, unsigned int val, unsigned int flags,
void *timo)
{
return syscall(__NR_futex_wait, uaddr, val,
flags | FUTEX_32 | FUTEX_SHARED_FLAG, timo);
}
/*
* wake nr futexes waiting for uaddr
*/
static int __futex_wake(void *uaddr, unsigned int nr_wake, unsigned int flags)
{
return syscall(__NR_futex_wake, uaddr, nr_wake,
flags | FUTEX_32 | FUTEX_SHARED_FLAG);
}
static inline int futex_wait( int *addr, int val, struct timespec *timeout )
{
return syscall( __NR_futex, addr, wait_op, val, timeout, 0, 0 );
return __futex_wait(addr, val, 0, timeout);
}
static inline int futex_wake( int *addr, int val )
{
return syscall( __NR_futex, addr, wake_op, val, NULL, 0, 0 );
return __futex_wake(addr, val, 0);
}
static inline int use_futexes(void)
......
......@@ -53,14 +53,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(fsync);
#include "pshpack4.h"
struct futex_wait_block
{
int *addr;
struct futex_waitv {
void *uaddr;
#if __SIZEOF_POINTER__ == 4
int pad;
int pad;
#endif
int val;
int bitset;
unsigned int val;
unsigned int flags;
};
#include "poppack.h"
......@@ -73,20 +73,54 @@ static inline void small_pause(void)
#endif
}
static inline int futex_wait_multiple( const struct futex_wait_block *futexes,
#define FUTEX_32 2
#define FUTEX_SHARED_FLAG 8
#define __NR_futex_wait 440
#define __NR_futex_wake 441
#define __NR_futex_waitv 442
static int __futex_waitv(struct futex_waitv *waiters, unsigned int nr_waiters,
unsigned int flags, struct timespec *timo)
{
return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, timo);
}
/*
* wait for uaddr if (*uaddr == val)
*/
static int __futex_wait(void *uaddr, unsigned int val, unsigned int flags,
void *timo)
{
return syscall(__NR_futex_wait, uaddr, val,
flags | FUTEX_32 | FUTEX_SHARED_FLAG, timo);
}
/*
* wake nr futexes waiting for uaddr
*/
static int __futex_wake(void *uaddr, unsigned int nr_wake, unsigned int flags)
{
return syscall(__NR_futex_wake, uaddr, nr_wake,
flags | FUTEX_32 | FUTEX_SHARED_FLAG);
}
static inline int futex_wait_multiple( const struct futex_waitv *futexes,
int count, const struct timespec *timeout )
{
return syscall( __NR_futex, futexes, 31, count, timeout, 0, 0 );
return __futex_waitv(futexes, count, 0, timeout);
}
static inline int futex_wake( int *addr, int val )
{
return syscall( __NR_futex, addr, 1, val, NULL, 0, 0 );
return __futex_wake(addr, val, 0);
}
static inline int futex_wait( int *addr, int val, struct timespec *timeout )
{
return syscall( __NR_futex, addr, 0, val, timeout, 0, 0 );
return __futex_wait(addr, val, 0, timeout);
}
static unsigned int spincount = 100;
......@@ -109,7 +143,7 @@ int do_fsync(void)
#else
static int once;
if (!once++)
FIXME("futexes not supported on this platform.\n");
FIXME("futexes2 not supported on this platform.\n");
return 0;
#endif
}
......@@ -195,7 +229,7 @@ static void *get_shm( unsigned int idx )
* This is copied and adapted from the fd cache code. */
#define FSYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct fsync))
#define FSYNC_LIST_ENTRIES 256
#define FSYNC_LIST_ENTRIES 128
static struct fsync *fsync_list[FSYNC_LIST_ENTRIES];
static struct fsync fsync_list_initial_block[FSYNC_LIST_BLOCK_SIZE];
......@@ -688,19 +722,20 @@ static NTSTATUS do_single_wait( int *addr, int val, ULONGLONG *end, BOOLEAN aler
if (alertable)
{
int *apc_futex = ntdll_get_thread_data()->fsync_apc_futex;
struct futex_wait_block futexes[2];
struct futex_waitv futexes[2];
if (__atomic_load_n( apc_futex, __ATOMIC_SEQ_CST ))
return STATUS_USER_APC;
futexes[0].addr = addr;
futexes[0].uaddr = addr;
futexes[0].val = val;
futexes[1].addr = apc_futex;
futexes[1].uaddr = apc_futex;
futexes[1].val = 0;
#if __SIZEOF_POINTER__ == 4
futexes[0].pad = futexes[1].pad = 0;
#endif
futexes[0].bitset = futexes[1].bitset = ~0;
futexes[0].flags = futexes[1].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
if (end)
{
......@@ -743,7 +778,7 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
{
static const LARGE_INTEGER zero = {0};
struct futex_wait_block futexes[MAXIMUM_WAIT_OBJECTS + 1];
struct futex_waitv futexes[MAXIMUM_WAIT_OBJECTS + 1];
struct fsync *objs[MAXIMUM_WAIT_OBJECTS];
int has_fsync = 0, has_server = 0;
BOOL msgwait = FALSE;
......@@ -873,8 +908,10 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
small_pause();
}
futexes[i].addr = &semaphore->count;
futexes[i].uaddr = &semaphore->count;
futexes[i].val = 0;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
break;
}
case FSYNC_MUTEX:
......@@ -906,8 +943,10 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
small_pause();
}
futexes[i].addr = &mutex->tid;
futexes[i].uaddr = &mutex->tid;
futexes[i].val = tid;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
break;
}
case FSYNC_AUTO_EVENT:
......@@ -925,8 +964,10 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
small_pause();
}
futexes[i].addr = &event->signaled;
futexes[i].uaddr = &event->signaled;
futexes[i].val = 0;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
break;
}
case FSYNC_MANUAL_EVENT:
......@@ -945,8 +986,10 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
small_pause();
}
futexes[i].addr = &event->signaled;
futexes[i].uaddr = &event->signaled;
futexes[i].val = 0;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
break;
}
default:
......@@ -957,25 +1000,27 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
else
{
/* Avoid breaking things entirely. */
futexes[i].addr = &dummy_futex;
futexes[i].uaddr = &dummy_futex;
futexes[i].val = dummy_futex;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
}
#if __SIZEOF_POINTER__ == 4
futexes[i].pad = 0;
#endif
futexes[i].bitset = ~0;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
}
if (alertable)
{
/* We already checked if it was signaled; don't bother doing it again. */
futexes[i].addr = ntdll_get_thread_data()->fsync_apc_futex;
futexes[i].uaddr = ntdll_get_thread_data()->fsync_apc_futex;
futexes[i].val = 0;
#if __SIZEOF_POINTER__ == 4
futexes[i].pad = 0;
#endif
futexes[i].bitset = ~0;
futexes[i].flags = FUTEX_32 | FUTEX_SHARED_FLAG;
i++;
}
waitcount = i;
......
......@@ -47,20 +47,29 @@
#include "fsync.h"
#include "pshpack4.h"
struct futex_wait_block
{
int *addr;
struct futex_waitv {
void *uaddr;
#if __SIZEOF_POINTER__ == 4
int pad;
int pad;
#endif
int val;
unsigned int val;
unsigned int flags;
};
#include "poppack.h"
static inline int futex_wait_multiple( const struct futex_wait_block *futexes,
#define __NR_futex_waitv 442
static int __futex_waitv(struct futex_waitv *waiters, unsigned int nr_waiters,
unsigned int flags, struct timespec *timo)
{
return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, timo);
}
static inline int futex_wait_multiple( const struct futex_waitv *futexes,
int count, const struct timespec *timeout )
{
return syscall( __NR_futex, futexes, 31, count, timeout, 0, 0 );
return __futex_waitv(futexes, count, 0, timeout);
}
int do_fsync(void)
......@@ -325,9 +334,18 @@ struct fsync *create_fsync( struct object *root, const struct unicode_str *name,
#endif
}
/*
* wake nr futexes waiting for uaddr
*/
static int __futex_wake(void *uaddr, unsigned int nr_wake, unsigned int flags)
{
return syscall(__NR_futex_wake, uaddr, nr_wake,
flags | FUTEX_32 | FUTEX_SHARED_FLAG);
}
static inline int futex_wake( int *addr, int val )
{
return syscall( __NR_futex, addr, 1, val, NULL, 0, 0 );
return __futex_wake(addr, val, 0);
}
/* shm layout for events or event-like objects. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment