[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 2/2] Make the XENBUS_CONSOLE Write method properly synchronous



Have the method directly write into the console ring (and potentially
block). This removes a lot of complexity from the code and makes the
method safe to be called at IRQL > DISPATCH_LEVEL.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/console_interface.h |   4 +-
 src/xenbus/console.c        | 236 +++++++-------------------------------------
 2 files changed, 39 insertions(+), 201 deletions(-)

diff --git a/include/console_interface.h b/include/console_interface.h
index bcea6fb..ccbdd30 100644
--- a/include/console_interface.h
+++ b/include/console_interface.h
@@ -67,8 +67,10 @@ typedef VOID
     \param Buffer A character buffer
     \param Length The length of the buffer
     \param CRLF Substitute LF with CRLF
+
+    \return The number of characters written
 */
-typedef NTSTATUS
+typedef ULONG
 (*XENBUS_CONSOLE_WRITE)(
     IN  PINTERFACE  Interface,
     IN  PCHAR       Data,
diff --git a/src/xenbus/console.c b/src/xenbus/console.c
index 36e113e..15aea92 100644
--- a/src/xenbus/console.c
+++ b/src/xenbus/console.c
@@ -55,15 +55,11 @@ struct _XENBUS_CONSOLE_CONTEXT {
     KSPIN_LOCK                  Lock;
     LONG                        References;
     struct xencons_interface    *Shared;
-    LIST_ENTRY                  OutList;
-    HIGH_LOCK                   OutLock;
-    KDPC                        Dpc;
-    ULONG                       Polls;
-    ULONG                       Dpcs;
-    ULONG                       Events;
+    HIGH_LOCK                   RingLock;
     XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
     PHYSICAL_ADDRESS            Address;
     PXENBUS_EVTCHN_CHANNEL      Channel;
+    ULONG                       Events;
     XENBUS_SUSPEND_INTERFACE    SuspendInterface;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
     PXENBUS_SUSPEND_CALLBACK    SuspendCallbackEarly;
@@ -96,7 +92,8 @@ static ULONG
 ConsoleCopyToRing(
     IN  PXENBUS_CONSOLE_CONTEXT Context,
     IN  PCHAR                   Data,
-    IN  ULONG                   Length
+    IN  ULONG                   Length,
+    IN  BOOLEAN                 CRLF
     )
 {
     struct xencons_interface    *Shared;
@@ -115,26 +112,31 @@ ConsoleCopyToRing(
 
     Offset = 0;
     while (Length != 0) {
+        CHAR    Character = Data[Offset];
+        ULONG   Required;
         ULONG   Available;
         ULONG   Index;
-        ULONG   CopyLength;
 
+        Required = (CRLF && Character == '\n') ? 2 : 1;
         Available = cons + sizeof (Shared->out) - prod;
 
-        if (Available == 0)
+        if (Available < Required)
             break;
 
         Index = MASK_XENCONS_IDX(prod, Shared->out);
 
-        CopyLength = __min(Length, Available);
-        CopyLength = __min(CopyLength, sizeof (Shared->out) - Index);
+        if (CRLF && Character == '\n') {
+            Shared->out[Index] = '\r';
+            prod++;
 
-        RtlCopyMemory(&Shared->out[Index], Data + Offset, CopyLength);
+            Index = MASK_XENCONS_IDX(prod, Shared->out);
+        }
 
-        Offset += CopyLength;
-        Length -= CopyLength;
+        Shared->out[Index] = Character;
+        prod++;
 
-        prod += CopyLength;
+        Offset++;
+        Length--;
     }
 
     KeMemoryBarrier();
@@ -146,128 +148,6 @@ ConsoleCopyToRing(
     return Offset;
 }
 
-static FORCEINLINE PXENBUS_CONSOLE_BUFFER
-__ConsoleGetHeadBuffer(
-    IN  PXENBUS_CONSOLE_CONTEXT Context
-    )
-{
-    PLIST_ENTRY                 ListEntry;
-    PXENBUS_CONSOLE_BUFFER      Buffer;
-    KIRQL                       Irql;
-
-    AcquireHighLock(&Context->OutLock, &Irql);
-    ListEntry = (!IsListEmpty(&Context->OutList)) ?
-                Context->OutList.Flink :
-                NULL;
-    ReleaseHighLock(&Context->OutLock, Irql);
-
-    if (ListEntry == NULL)
-        return NULL;
-
-    Buffer = CONTAINING_RECORD(ListEntry,
-                               XENBUS_CONSOLE_BUFFER,
-                               ListEntry);
-
-    return Buffer;
-}
-
-static FORCEINLINE VOID
-__ConsoleRemoveHeadBuffer(
-    IN  PXENBUS_CONSOLE_CONTEXT Context
-    )
-{
-    KIRQL                       Irql;
-
-    AcquireHighLock(&Context->OutLock, &Irql);
-    (VOID) RemoveHeadList(&Context->OutList);
-    ReleaseHighLock(&Context->OutLock, Irql);
-}
-
-static FORCEINLINE VOID
-__ConsoleAddTailBuffer(
-    IN  PXENBUS_CONSOLE_CONTEXT Context,
-    IN  PXENBUS_CONSOLE_BUFFER  Buffer
-    )
-{
-    KIRQL                       Irql;
-
-    AcquireHighLock(&Context->OutLock, &Irql);
-    InsertTailList(&Context->OutList, &Buffer->ListEntry);
-    ReleaseHighLock(&Context->OutLock, Irql);
-}
-
-static BOOLEAN
-ConsoleOut(
-    IN  PXENBUS_CONSOLE_CONTEXT Context
-    )
-{
-    PXENBUS_CONSOLE_BUFFER      Buffer;
-    ULONG                       Written;
-
-    Buffer = __ConsoleGetHeadBuffer(Context);
-
-    if (Buffer == NULL)
-        return FALSE;
-
-    Written = ConsoleCopyToRing(Context,
-                                Buffer->Data + Buffer->Offset,
-                                Buffer->Length - Buffer->Offset);
-
-    Buffer->Offset += Written;
-
-    ASSERT3U(Buffer->Offset, <=, Buffer->Length);
-    if (Buffer->Offset == Buffer->Length) {
-        __ConsoleRemoveHeadBuffer(Context);
-        __ConsoleFree(Buffer);
-    }
-
-    if (Written != 0)
-        XENBUS_EVTCHN(Send,
-                      &Context->EvtchnInterface,
-                      Context->Channel);
-
-    return TRUE;
-}
-
-static VOID
-ConsoleFlush(
-    IN  PXENBUS_CONSOLE_CONTEXT Context
-    )
-{
-    for (;;) {
-        if (!ConsoleOut(Context))
-            break;
-    }
-}
-
-static
-_Function_class_(KDEFERRED_ROUTINE)
-_IRQL_requires_max_(DISPATCH_LEVEL)
-_IRQL_requires_min_(DISPATCH_LEVEL)
-_IRQL_requires_(DISPATCH_LEVEL)
-_IRQL_requires_same_
-VOID
-ConsoleDpc(
-    IN  PKDPC               Dpc,
-    IN  PVOID               _Context,
-    IN  PVOID               Argument1,
-    IN  PVOID               Argument2
-    )
-{
-    PXENBUS_CONSOLE_CONTEXT Context = _Context;
-
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(Argument1);
-    UNREFERENCED_PARAMETER(Argument2);
-
-    ASSERT(Context != NULL);
-
-    KeAcquireSpinLockAtDpcLevel(&Context->Lock);
-    if (Context->References != 0)
-        (VOID) ConsoleOut(Context);
-    KeReleaseSpinLockFromDpcLevel(&Context->Lock);
-}
-
 static
 _Function_class_(KSERVICE_ROUTINE)
 _IRQL_requires_(HIGH_LEVEL)
@@ -286,9 +166,6 @@ ConsoleEvtchnCallback(
 
     Context->Events++;
 
-    if (KeInsertQueueDpc(&Context->Dpc, NULL, NULL))
-        Context->Dpcs++;
-
     return TRUE;
 }
 
@@ -341,10 +218,6 @@ ConsoleEnable(
     LogPrintf(LOG_LEVEL_INFO,
               "CONSOLE: ENABLE (%u)\n",
               Port);
-
-    // Trigger an initial poll
-    if (KeInsertQueueDpc(&Context->Dpc, NULL, NULL))
-        Context->Dpcs++;
 }
 
 static PHYSICAL_ADDRESS
@@ -436,13 +309,11 @@ ConsoleDebugCallback(
 
     XENBUS_DEBUG(Printf,
                  &Context->DebugInterface,
-                 "Events = %lu Dpcs = %lu Polls = %lu\n",
-                 Context->Events,
-                 Context->Dpcs,
-                 Context->Polls);
+                 "Events = %lu\n",
+                 Context->Events);
 }
 
-static NTSTATUS
+static ULONG
 ConsoleWrite(
     IN  PINTERFACE          Interface,
     IN  PCHAR               Data,
@@ -451,50 +322,29 @@ ConsoleWrite(
     )
 {
     PXENBUS_CONSOLE_CONTEXT Context = Interface->Context;
-    ULONG                   Extra;
-    PXENBUS_CONSOLE_BUFFER  Buffer;
-    ULONG                   Index;
     KIRQL                   Irql;
+    ULONG                   Written;
     NTSTATUS                status;
 
-    Extra = 0;
-    if (CRLF) {
-        for (Index = 0; Index < Length; Index++) {
-            if (Data[Index] == '\n')
-                Extra++;
-        }
-    }
+    AcquireHighLock(&Context->RingLock, &Irql);
 
-    Buffer = __ConsoleAllocate(FIELD_OFFSET(XENBUS_CONSOLE_BUFFER, Data) +
-                               Length + Extra);
+    Written = 0;
 
-    status = STATUS_NO_MEMORY;
-    if (Buffer == NULL)
-        goto fail1;
-
-    Index = 0;
-    while (Index < Length + Extra) {
-        if (CRLF && *Data == '\n')
-            Buffer->Data[Index++] = '\r';
-
-        Buffer->Data[Index++] = *Data++;
-    }
-
-    Buffer->Length = Length + Extra;
-
-    AcquireHighLock(&Context->OutLock, &Irql);
-    InsertTailList(&Context->OutList, &Buffer->ListEntry);
-    ReleaseHighLock(&Context->OutLock, Irql);
+    status = STATUS_UNSUCCESSFUL;
+    if (!Context->Enabled)
+        goto done;
 
-    if (KeInsertQueueDpc(&Context->Dpc, NULL, NULL))
-        Context->Dpcs++;
+    Written += ConsoleCopyToRing(Context, Data, Length, CRLF);
 
-    return STATUS_SUCCESS;
+    if (Written != 0)
+        XENBUS_EVTCHN(Send,
+                      &Context->EvtchnInterface,
+                      Context->Channel);
 
-fail1:
-    Error("fail1 (%08x)\n", status);
+done:
+    ReleaseHighLock(&Context->RingLock, Irql);
 
-    return status;
+    return Written;
 }
 
 static NTSTATUS
@@ -635,8 +485,6 @@ ConsoleRelease(
 
     Trace("====>\n");
 
-    ConsoleFlush(Context);
-
     XENBUS_DEBUG(Deregister,
                  &Context->DebugInterface,
                  Context->DebugCallback);
@@ -716,11 +564,7 @@ ConsoleInitialize(
     ASSERT((*Context)->DebugInterface.Interface.Context != NULL);
 
     KeInitializeSpinLock(&(*Context)->Lock);
-
-    InitializeListHead(&(*Context)->OutList);
-    InitializeHighLock(&(*Context)->OutLock);
-
-    KeInitializeDpc(&(*Context)->Dpc, ConsoleDpc, *Context);
+    InitializeHighLock(&(*Context)->RingLock);
 
     (*Context)->Fdo = Fdo;
 
@@ -788,20 +632,12 @@ ConsoleTeardown(
     Trace("====>\n");
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-    KeFlushQueuedDpcs();
 
-    Context->Polls = 0;
-    Context->Dpcs = 0;
     Context->Events = 0;
 
     Context->Fdo = NULL;
 
-    RtlZeroMemory(&Context->Dpc, sizeof (KDPC));
-
-    RtlZeroMemory(&Context->OutLock, sizeof (HIGH_LOCK));
-    ASSERT(IsListEmpty(&Context->OutList));
-    RtlZeroMemory(&Context->OutList, sizeof (LIST_ENTRY));
-
+    RtlZeroMemory(&Context->RingLock, sizeof (HIGH_LOCK));
     RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
 
     RtlZeroMemory(&Context->DebugInterface,
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.