[PATCH 4/5] server: Add a sequence number to the shared data.

Huw Davies huw at codeweavers.com
Thu Nov 19 07:09:30 CST 2020


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 <huw at codeweavers.com>
---
 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




More information about the wine-devel mailing list