]> xenbits.xensource.com Git - people/pauldu/xenbus.git/commitdiff
Avoid a small race window that can lead to stuck EvtchnWait() calls
authorPaul Durrant <pdurrant@amazon.com>
Fri, 15 Nov 2019 14:02:28 +0000 (14:02 +0000)
committerPaul Durrant <pdurrant@amazon.com>
Wed, 4 Dec 2019 14:18:27 +0000 (14:18 +0000)
Make sure an event is ack-ed before Channel->Count is incremented
otherwise EvtchnGetCount() could sample the incremented value whilst new
events would be missed. Thus EvtchnWait() could end up waiting for a
Count value that my never be reached.

Signed-off-by: Paul Durrant <pdurrant@amazon.com>
src/xenbus/evtchn.c

index 0748e50083548892b80cbfa26c8732f20f3108b1..8a819f35de2dbcffd13176c3d2d66fa29d6551c6 100644 (file)
@@ -507,8 +507,6 @@ EvtchnPoll(
 
         KeMemoryBarrier();
         if (!Channel->Closed) {
-            Channel->Count++;
-
             RemoveEntryList(&Channel->PendingListEntry);
             InitializeListHead(&Channel->PendingListEntry);
 
@@ -521,6 +519,16 @@ EvtchnPoll(
                               &Context->EvtchnAbi,
                               Channel->LocalPort);
 
+           /*
+            * Make sure the event is ack-ed before Count is incremented
+            * otherwise there is a small window where EvtchnWait() could
+            * end up waiting on the incremented value whilst new events
+            * would be missed (hence Count would not be further
+            * incremented to wake the waiter).
+            */
+           KeMemoryBarrier();
+            Channel->Count++;
+
 #pragma warning(suppress:6387)  // NULL argument
             DoneSomething |= Channel->Callback(NULL, Channel->Argument);
         } else if (List != NULL) {
@@ -923,6 +931,8 @@ EvtchnGetCount(
 {
     UNREFERENCED_PARAMETER(Interface);
 
+    KeMemoryBarrier();
+
     return Channel->Count;
 }