From: Huw Davies Subject: [PATCH 4/5] server: Add a sequence number to the shared data. Message-Id: <20201119130931.89653-4-huw@codeweavers.com> Date: Thu, 19 Nov 2020 13:09:30 +0000 The client should check that the lower SEQUENCE_MASK_BITS are zero before reading the data and confirm that the number is unchanged when it's finished. Signed-off-by: Huw Davies --- server/protocol.def | 5 +++++ server/queue.c | 46 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/server/protocol.def b/server/protocol.def index d61d7f3c549..007e712ccbc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -805,9 +805,14 @@ struct shared_cursor struct desktop_shared_memory { + unsigned int seq; /* sequence number - server updating if (seq_no & SEQUENCE_MASK) != 0 */ struct shared_cursor cursor; /* global cursor information */ }; +/* Bits that must be clear for client to read */ +#define SEQUENCE_MASK_BITS 4 +#define SEQUENCE_MASK ((1UL << SEQUENCE_MASK_BITS) - 1) + /****************************************************************/ /* Request declarations */ diff --git a/server/queue.c b/server/queue.c index f6664509ee3..7bf4ea2dea4 100644 --- a/server/queue.c +++ b/server/queue.c @@ -371,16 +371,60 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour return msg; } +#if defined(__i386__) || defined(__x86_64__) + +#define SHARED_WRITE_BEGIN( x ) \ + do { \ + volatile unsigned int __seq = *(x); \ + assert( (__seq & SEQUENCE_MASK) != SEQUENCE_MASK ); \ + *(x) = ++__seq; \ + } while(0) + +#define SHARED_WRITE_END( x ) \ + do { \ + volatile unsigned int __seq = *(x); \ + assert( (__seq & SEQUENCE_MASK) != 0 ); \ + if ((__seq & SEQUENCE_MASK) > 1) __seq--; \ + else __seq += SEQUENCE_MASK; \ + *(x) = __seq; \ + } while(0) + +#else + +#define SHARED_WRITE_BEGIN( x ) \ + do { \ + assert( (*(x) & SEQUENCE_MASK) != SEQUENCE_MASK ); \ + if ((__atomic_add_fetch( x, 1, __ATOMIC_RELAXED ) & SEQUENCE_MASK) == 1) \ + __atomic_thread_fence( __ATOMIC_RELEASE ); \ + } while(0) + +#define SHARED_WRITE_END( x ) \ + do { \ + assert( (*(x) & SEQUENCE_MASK) != 0 ); \ + if ((*(x) & SEQUENCE_MASK) > 1) \ + __atomic_sub_fetch( x, 1, __ATOMIC_RELAXED ); \ + else { \ + __atomic_thread_fence( __ATOMIC_RELEASE ); \ + __atomic_add_fetch( x, SEQUENCE_MASK, __ATOMIC_RELAXED ); \ + } \ + } while(0) + +#endif + static int update_desktop_cursor_pos( struct desktop *desktop, int x, int y ) { int updated; + unsigned int time = get_tick_count(); x = max( min( x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left ); y = max( min( y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top ); updated = (desktop->shared->cursor.x != x || desktop->shared->cursor.y != y); + + SHARED_WRITE_BEGIN( &desktop->shared->seq ); desktop->shared->cursor.x = x; desktop->shared->cursor.y = y; - desktop->shared->cursor.last_change = get_tick_count(); + desktop->shared->cursor.last_change = time; + SHARED_WRITE_END( &desktop->shared->seq ); return updated; } -- 2.23.0