Skip to content
This repository has been archived by the owner on May 4, 2024. It is now read-only.

Commit

Permalink
ntdll: Cache the esync struct itself instead of a pointer to it.
Browse files Browse the repository at this point in the history
Now that the esync object has a constant size, we can perform this
optimization.
  • Loading branch information
zfigura committed Jul 7, 2018
1 parent bbaaf23 commit 7b583a3
Showing 1 changed file with 24 additions and 46 deletions.
70 changes: 24 additions & 46 deletions dlls/ntdll/esync.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ static void *get_shm( unsigned int idx )
/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
* This is copied and adapted from the fd cache code. */

#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync *))
#define ESYNC_LIST_ENTRIES 128
#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync))
#define ESYNC_LIST_ENTRIES 256

static struct esync * *esync_list[ESYNC_LIST_ENTRIES];
static struct esync * esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE];
static struct esync *esync_list[ESYNC_LIST_ENTRIES];
static struct esync esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE];

static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry )
{
Expand All @@ -169,7 +169,7 @@ static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry )
return idx % ESYNC_LIST_BLOCK_SIZE;
}

static BOOL add_to_list( HANDLE handle, struct esync *obj )
static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, void *shm )
{
UINT_PTR entry, idx = handle_to_index( handle, &entry );

Expand All @@ -191,18 +191,22 @@ static BOOL add_to_list( HANDLE handle, struct esync *obj )
}
}

obj = interlocked_xchg_ptr((void **)&esync_list[entry][idx], obj);
assert(!obj);
return TRUE;
if (!interlocked_cmpxchg((int *)&esync_list[entry][idx].type, type, 0))
{
esync_list[entry][idx].fd = fd;
esync_list[entry][idx].shm = shm;
}
return &esync_list[entry][idx];
}

static struct esync *get_cached_object( HANDLE handle )
{
UINT_PTR entry, idx = handle_to_index( handle, &entry );

if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL;
if (!esync_list[entry][idx].type) return NULL;

return esync_list[entry][idx];
return &esync_list[entry][idx];
}

/* Gets an object. This is either a proper esync object (i.e. an event,
Expand All @@ -214,19 +218,18 @@ static struct esync *get_cached_object( HANDLE handle )
* since we might be passed a duplicated or inherited handle. */
static NTSTATUS get_object( HANDLE handle, struct esync **obj )
{
NTSTATUS ret = STATUS_SUCCESS;
enum esync_type type = 0;
unsigned int shm_idx = 0;
obj_handle_t fd_handle;
enum esync_type type;
unsigned int shm_idx;
struct esync *esync;
sigset_t sigset;
NTSTATUS ret;
int fd;
int fd = -1;

if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS;

/* We need to try grabbing it from the server. */
server_enter_uninterrupted_section( &fd_cache_section, &sigset );
if (!(esync = get_cached_object( handle )))
if (!(*obj = get_cached_object( handle )))
{
SERVER_START_REQ( get_esync_fd )
{
Expand All @@ -243,10 +246,9 @@ static NTSTATUS get_object( HANDLE handle, struct esync **obj )
}
server_leave_uninterrupted_section( &fd_cache_section, &sigset );

if (esync)
if (*obj)
{
/* We managed to grab it while in the CS; return it. */
*obj = esync;
return STATUS_SUCCESS;
}

Expand All @@ -259,31 +261,21 @@ static NTSTATUS get_object( HANDLE handle, struct esync **obj )

TRACE("Got fd %d for handle %p.\n", fd, handle);

esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) );
esync->fd = fd;
esync->type = type;

esync->shm = shm_idx ? get_shm( shm_idx ) : 0;

add_to_list( handle, esync );

*obj = esync;
*obj = add_to_list( handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 );
return ret;
}

NTSTATUS esync_close( HANDLE handle )
{
UINT_PTR entry, idx = handle_to_index( handle, &entry );
struct esync *obj;

TRACE("%p.\n", handle);

if (entry < ESYNC_LIST_ENTRIES && esync_list[entry])
{
if ((obj = interlocked_xchg_ptr( (void **)&esync_list[entry][idx], 0 )))
if (interlocked_xchg((int *)&esync_list[entry][idx].type, 0))
{
close( obj->fd );
RtlFreeHeap( GetProcessHeap(), 0, obj );
close( esync_list[entry][idx].fd );
return STATUS_SUCCESS;
}
}
Expand Down Expand Up @@ -329,14 +321,7 @@ static NTSTATUS create_esync( enum esync_type type, HANDLE *handle,

if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
{
struct esync *obj = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*obj) );
if (!obj) return STATUS_NO_MEMORY;

obj->type = type;
obj->fd = fd;
obj->shm = shm_idx ? get_shm( shm_idx ) : 0;

add_to_list( *handle, obj );
add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 );

TRACE("-> handle %p, fd %d, shm index %d.\n", *handle, fd, shm_idx);
}
Expand Down Expand Up @@ -377,14 +362,7 @@ static NTSTATUS open_esync( enum esync_type type, HANDLE *handle,

if (!ret)
{
struct esync *obj = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*obj) );
if (!obj) return STATUS_NO_MEMORY;

obj->type = type;
obj->fd = fd;
obj->shm = shm_idx ? get_shm( shm_idx ) : 0;

add_to_list( *handle, obj );
add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 );

TRACE("-> handle %p, fd %d.\n", *handle, fd);
}
Expand Down

0 comments on commit 7b583a3

Please sign in to comment.