Skip to content

Commit

Permalink
server: Update the shared memory state when (re)setting an event.
Browse files Browse the repository at this point in the history
  • Loading branch information
zfigura authored and imaami committed Aug 17, 2019
1 parent 1590afb commit 2f89fc5
Showing 1 changed file with 98 additions and 6 deletions.
104 changes: 98 additions & 6 deletions server/esync.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ int do_esync(void)
static char shm_name[29];
static int shm_fd;
static off_t shm_size;
static void **shm_addrs;
static int shm_addrs_size; /* length of the allocated shm_addrs array */
static long pagesize;

static void shm_cleanup(void)
{
Expand All @@ -89,7 +92,12 @@ void esync_init(void)
if (shm_fd == -1)
perror( "shm_open" );

shm_size = sysconf( _SC_PAGESIZE );
pagesize = sysconf( _SC_PAGESIZE );

shm_addrs = calloc( 128, sizeof(shm_addrs[0]) );
shm_addrs_size = 128;

shm_size = pagesize;
if (ftruncate( shm_fd, shm_size ) == -1)
perror( "ftruncate" );

Expand Down Expand Up @@ -198,7 +206,7 @@ static struct esync *create_esync( struct object *root, const struct unicode_str
while (esync->shm_idx * 8 >= shm_size)
{
/* Better expand the shm section. */
shm_size += sysconf( _SC_PAGESIZE );
shm_size += pagesize;
if (ftruncate( shm_fd, shm_size ) == -1)
{
fprintf( stderr, "esync: couldn't expand %s to size %ld: ",
Expand Down Expand Up @@ -274,24 +282,108 @@ void esync_clear( int fd )
read( fd, &value, sizeof(value) );
}

/* Sadly, we need all of this infrastructure to keep the shm state in sync. */

static void *get_shm( unsigned int idx )
{
int entry = (idx * 8) / pagesize;
int offset = (idx * 8) % pagesize;

if (entry >= shm_addrs_size)
{
if (!(shm_addrs = realloc( shm_addrs, (entry + 1) * sizeof(shm_addrs[0]) )))
fprintf( stderr, "esync: couldn't expand shm_addrs array to size %d\n", entry + 1 );

memset( &shm_addrs[shm_addrs_size], 0, (entry + 1 - shm_addrs_size) * sizeof(shm_addrs[0]) );

shm_addrs_size = entry + 1;
}

if (!shm_addrs[entry])
{
void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize );
if (addr == (void *)-1)
{
fprintf( stderr, "esync: failed to map page %d (offset %#lx): ", entry, entry * pagesize );
perror( "mmap" );
}

if (debug_level)
fprintf( stderr, "esync: Mapping page %d at %p.\n", entry, addr );

if (interlocked_cmpxchg_ptr( &shm_addrs[entry], addr, 0 ))
munmap( addr, pagesize ); /* someone beat us to it */
}

return (void *)((unsigned long)shm_addrs[entry] + offset);
}

struct event
{
int signaled;
int locked;
};
C_ASSERT(sizeof(struct event) == 8);

static inline void small_pause(void)
{
#ifdef __i386__
__asm__ __volatile__( "rep;nop" : : : "memory" );
#else
__asm__ __volatile__( "" : : : "memory" );
#endif
}

/* Server-side event support. */
void esync_set_event( struct esync *esync )
{
static const uint64_t value = 1;
struct event *event = get_shm( esync->shm_idx );

assert( esync->obj.ops == &esync_ops );
if (write( esync->fd, &value, sizeof(value) ) == -1)
perror( "esync: write" );
assert( event != NULL );

if (debug_level)
fprintf( stderr, "esync_set_event() fd=%d\n", esync->fd );

/* Acquire the spinlock. */
while (interlocked_cmpxchg( &event->locked, 1, 0 ))
small_pause();

if (!interlocked_xchg( &event->signaled, 1 ))
{
if (write( esync->fd, &value, sizeof(value) ) == -1)
perror( "esync: write" );
}

/* Release the spinlock. */
event->locked = 0;
}

void esync_reset_event( struct esync *esync )
{
static uint64_t value = 1;
struct event *event = get_shm( esync->shm_idx );

assert( esync->obj.ops == &esync_ops );
assert( event != NULL );

/* we don't care about the return value */
read( esync->fd, &value, sizeof(value) );
if (debug_level)
fprintf( stderr, "esync_reset_event() fd=%d\n", esync->fd );

/* Acquire the spinlock. */
while (interlocked_cmpxchg( &event->locked, 1, 0 ))
small_pause();

/* Only bother signaling the fd if we weren't already signaled. */
if (interlocked_xchg( &event->signaled, 0 ))
{
/* we don't care about the return value */
read( esync->fd, &value, sizeof(value) );
}

/* Release the spinlock. */
event->locked = 0;
}

DECL_HANDLER(create_esync)
Expand Down

0 comments on commit 2f89fc5

Please sign in to comment.