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

[win-pv-devel] [PATCH] Reduce time spent in the DbgPrint callback



Currently the log dispositions are serviced directly, meaning that all the
trapping for emulation is done synchronously, which is costly for
performance. This patch introduces a DPC to service the dispostions,
limiting the work done in the call back to simply copying the message
buffer and queuing the DPC.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xen/log.c | 196 +++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 125 insertions(+), 71 deletions(-)

diff --git a/src/xen/log.c b/src/xen/log.c
index 9b3a5e8..ed7e484 100644
--- a/src/xen/log.c
+++ b/src/xen/log.c
@@ -43,70 +43,81 @@
 
 #define LOG_BUFFER_SIZE 256
 
+typedef struct _LOG_SLOT {
+    LOG_LEVEL   Level;
+    CHAR        Buffer[LOG_BUFFER_SIZE];
+    ULONG       Offset;
+} LOG_SLOT, *PLOG_SLOT;
+
 struct _LOG_DISPOSITION {
     LOG_LEVEL   Mask;
     VOID        (*Function)(PVOID, PCHAR, ULONG);
     PVOID       Argument;
 };
 
-#define LOG_MAXIMUM_DISPOSITION 8
+#define LOG_NR_SLOTS 32
+#define LOG_NR_DISPOSITIONS 8
 
 typedef struct _LOG_CONTEXT {
     LONG            References;
     BOOLEAN         Enabled;
-    CHAR            Buffer[LOG_BUFFER_SIZE];
-    ULONG           Offset;
-    LOG_DISPOSITION Disposition[LOG_MAXIMUM_DISPOSITION];
+    LOG_SLOT        Slot[LOG_NR_SLOTS];
+    ULONG           Pending;
+    LOG_DISPOSITION Disposition[LOG_NR_DISPOSITIONS];
     HIGH_LOCK       Lock;
+    KDPC            Dpc;
 } LOG_CONTEXT, *PLOG_CONTEXT;
 
 static LOG_CONTEXT  LogContext;
 
-static FORCEINLINE
-__drv_maxIRQL(HIGH_LEVEL)
-__drv_raisesIRQL(HIGH_LEVEL)
-__drv_savesIRQL
-KIRQL
-__LogAcquireBuffer(
-    IN  PLOG_CONTEXT    Context
+static FORCEINLINE VOID
+__LogFlushSlot(
+    IN  PLOG_CONTEXT    Context,
+    IN  PLOG_SLOT       Slot
     )
 {
-    return __AcquireHighLock(&Context->Lock);
+    ULONG               Index;
+
+    for (Index = 0; Index < LOG_NR_DISPOSITIONS; Index++) {
+        PLOG_DISPOSITION    Disposition = &Context->Disposition[Index];
+
+        if (Slot->Level & Disposition->Mask)
+            Disposition->Function(Disposition->Argument, Slot->Buffer,
+                                  Slot->Offset);
+    }
+
+    RtlZeroMemory(Slot->Buffer, Slot->Offset);
+    Slot->Offset = 0;
+    Slot->Level = 0;
 }
 
-static FORCEINLINE VOID
-__drv_maxIRQL(HIGH_LEVEL)
-__drv_requiresIRQL(HIGH_LEVEL)
-__LogReleaseBuffer(
-    IN  PLOG_CONTEXT                Context,
-    IN  LOG_LEVEL                   Level,
-    IN  __drv_restoresIRQL KIRQL    Irql
+static VOID
+LogFlush(
+    IN  PLOG_CONTEXT    Context
     )
 {
-    ULONG                           Index;
+    ULONG               Index;
 
-    for (Index = 0; Index < LOG_MAXIMUM_DISPOSITION; Index++) {
-        PLOG_DISPOSITION    Disposition = &Context->Disposition[Index];
+    for (Index = 0; Index < Context->Pending; Index++)
+    {
+        PLOG_SLOT   Slot = &Context->Slot[Index];
 
-        if (Level & Disposition->Mask)
-            Disposition->Function(Disposition->Argument, Context->Buffer, 
Context->Offset);
+        __LogFlushSlot(Context, Slot);
     }
 
-    RtlZeroMemory(Context->Buffer, Context->Offset);
-    Context->Offset = 0;
-
-    ReleaseHighLock(&Context->Lock, Irql);
+    Context->Pending = 0;
 }
 
 static FORCEINLINE VOID
 __LogPut(
-    IN  PLOG_CONTEXT    Context,
-    IN  CHAR            Character
+    IN  PLOG_SLOT   Slot,
+    IN  CHAR        Character
     )
 {
-    ASSERT(Context->Offset < LOG_BUFFER_SIZE);
+    if (Slot->Offset >= LOG_BUFFER_SIZE)
+        return;
 
-    Context->Buffer[Context->Offset++] = Character;
+    Slot->Buffer[Slot->Offset++] = Character;
 }
 
 static PCHAR
@@ -170,14 +181,14 @@ LogFormatNumber(
         } while (FALSE)
 
 static VOID
-LogWriteBuffer(
-    IN  PLOG_CONTEXT    Context, 
-    IN  LONG            Count,
-    IN  const CHAR      *Format,
-    IN  va_list         Arguments
+LogWriteSlot(
+    IN  PLOG_SLOT   Slot,
+    IN  LONG        Count,
+    IN  const CHAR  *Format,
+    IN  va_list     Arguments
     )
 {
-    CHAR                Character;
+    CHAR            Character;
 
     while ((Character = *Format++) != '\0') {
         UCHAR   Pad = 0;
@@ -187,7 +198,7 @@ LogWriteBuffer(
         BOOLEAN OppositeJustification = FALSE;
         
         if (Character != '%') {
-            __LogPut(Context, Character);
+            __LogPut(Slot, Character);
             goto loop;
         }
 
@@ -236,13 +247,13 @@ LogWriteBuffer(
                 WCHAR   Value;
                 Value = va_arg(Arguments, WCHAR);
 
-                __LogPut(Context, (CHAR)Value);
+                __LogPut(Slot, (CHAR)Value);
             } else { 
                 CHAR    Value;
 
                 Value = va_arg(Arguments, CHAR);
 
-                __LogPut(Context, Value);
+                __LogPut(Slot, Value);
             }
             break;
         }
@@ -269,15 +280,15 @@ LogWriteBuffer(
             Length = (ULONG)strlen(Buffer);
             if (!OppositeJustification) {
                 while (Pad > Length) {
-                    __LogPut(Context, (ZeroPrefix) ? '0' : ' ');
+                    __LogPut(Slot, (ZeroPrefix) ? '0' : ' ');
                     --Pad;
                 }
             }
             for (Index = 0; Index < Length; Index++)
-                __LogPut(Context, Buffer[Index]);
+                __LogPut(Slot, Buffer[Index]);
             if (OppositeJustification) {
                 while (Pad > Length) {
-                    __LogPut(Context, ' ');
+                    __LogPut(Slot, ' ');
                     --Pad;
                 }
             }
@@ -297,17 +308,17 @@ LogWriteBuffer(
 
                 if (OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
 
                 for (Index = 0; Index < Length; Index++)
-                    __LogPut(Context, (CHAR)Value[Index]);
+                    __LogPut(Slot, (CHAR)Value[Index]);
 
                 if (!OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
@@ -323,17 +334,17 @@ LogWriteBuffer(
 
                 if (OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
 
                 for (Index = 0; Index < Length; Index++)
-                    __LogPut(Context, Value[Index]);
+                    __LogPut(Slot, Value[Index]);
 
                 if (!OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
@@ -358,17 +369,17 @@ LogWriteBuffer(
 
                 if (OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
 
                 for (Index = 0; Index < Length; Index++)
-                    __LogPut(Context, (CHAR)Buffer[Index]);
+                    __LogPut(Slot, (CHAR)Buffer[Index]);
 
                 if (!OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
@@ -388,17 +399,17 @@ LogWriteBuffer(
 
                 if (OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
 
                 for (Index = 0; Index < Length; Index++)
-                    __LogPut(Context, Buffer[Index]);
+                    __LogPut(Slot, Buffer[Index]);
 
                 if (!OppositeJustification) {
                     while (Pad > Length) {
-                        __LogPut(Context, ' ');
+                        __LogPut(Slot, ' ');
                         --Pad;
                     }
                 }
@@ -407,7 +418,7 @@ LogWriteBuffer(
             break;
         }
         default:
-            __LogPut(Context, Character);
+            __LogPut(Slot, Character);
             break;
         }
 
@@ -427,16 +438,25 @@ LogCchVPrintf(
     )
 {
     PLOG_CONTEXT    Context = &LogContext;
+    PLOG_SLOT       Slot;
     KIRQL           Irql;
 
-    Irql = __LogAcquireBuffer(Context);
+    AcquireHighLock(&Context->Lock, &Irql);
 
-    LogWriteBuffer(Context,
-                   __min(Count, LOG_BUFFER_SIZE),
-                   Format,
-                   Arguments);
+    if (Context->Pending == ARRAYSIZE(Context->Slot))
+        LogFlush(Context);
 
-    __LogReleaseBuffer(Context, Level, Irql);
+    Slot = &Context->Slot[Context->Pending++];
+
+    Slot->Level = Level;
+    LogWriteSlot(Slot,
+                 __min(Count, LOG_BUFFER_SIZE),
+                 Format,
+                 Arguments);
+
+    LogFlush(Context);
+
+    ReleaseHighLock(&Context->Lock, Irql);
 }
 
 XEN_API
@@ -488,6 +508,33 @@ typedef VOID
     ULONG           Level
     );
 
+static
+_Function_class_(KDEFERRED_ROUTINE)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+_IRQL_requires_min_(DISPATCH_LEVEL)
+_IRQL_requires_(DISPATCH_LEVEL)
+_IRQL_requires_same_
+VOID
+LogDpc(
+    IN  PKDPC       Dpc,
+    IN  PVOID       _Context,
+    IN  PVOID       Argument1,
+    IN  PVOID       Argument2
+    )
+{
+    PLOG_CONTEXT    Context = &LogContext;
+    KIRQL           Irql;
+
+    UNREFERENCED_PARAMETER(_Context);
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    AcquireHighLock(&Context->Lock, &Irql);
+    LogFlush(Context);
+    ReleaseHighLock(&Context->Lock, Irql);
+}
+
 static VOID
 LogDebugPrint(
     IN  PANSI_STRING    Ansi,
@@ -497,7 +544,7 @@ LogDebugPrint(
 {
     PLOG_CONTEXT        Context = &LogContext;
     KIRQL               Irql;
-    ULONG               Index;
+    PLOG_SLOT           Slot;
 
     UNREFERENCED_PARAMETER(ComponentId);
 
@@ -518,14 +565,18 @@ LogDebugPrint(
 
     AcquireHighLock(&Context->Lock, &Irql);
 
-    for (Index = 0; Index < LOG_MAXIMUM_DISPOSITION; Index++) {
-        PLOG_DISPOSITION    Disposition = &Context->Disposition[Index];
+    if (Context->Pending == ARRAYSIZE(Context->Slot))
+        LogFlush(Context);
 
-        if ((1 << Level) & Disposition->Mask)
-            Disposition->Function(Disposition->Argument, Ansi->Buffer, 
Ansi->Length);
-    }
+    Slot = &Context->Slot[Context->Pending++];
+
+    Slot->Level = 1 << Level;
+    RtlCopyMemory(Slot->Buffer, Ansi->Buffer, Ansi->Length);
+    Slot->Offset = Ansi->Length;
 
     ReleaseHighLock(&Context->Lock, Irql);
+
+    KeInsertQueueDpc(&Context->Dpc, NULL, NULL);
 }
 
 VOID
@@ -540,6 +591,7 @@ LogTeardown(
         Context->Enabled = FALSE;
     }
 
+    RtlZeroMemory(&Context->Dpc, sizeof (KDPC));
     RtlZeroMemory(&Context->Lock, sizeof (HIGH_LOCK));
 
     (VOID) InterlockedDecrement(&Context->References);
@@ -567,7 +619,7 @@ LogAddDisposition(
     AcquireHighLock(&Context->Lock, &Irql);
 
     status = STATUS_UNSUCCESSFUL;
-    for (Index = 0; Index < LOG_MAXIMUM_DISPOSITION; Index++) {
+    for (Index = 0; Index < LOG_NR_DISPOSITIONS; Index++) {
         *Disposition = &Context->Disposition[Index];
 
         if ((*Disposition)->Mask == 0) {
@@ -612,7 +664,7 @@ LogRemoveDisposition(
 
     AcquireHighLock(&Context->Lock, &Irql);
 
-    for (Index = 0; Index < LOG_MAXIMUM_DISPOSITION; Index++) {
+    for (Index = 0; Index < LOG_NR_DISPOSITIONS; Index++) {
         if (&Context->Disposition[Index] != Disposition)
             continue;
 
@@ -749,6 +801,8 @@ LogInitialize(
 
     InitializeHighLock(&Context->Lock);
 
+    KeInitializeDpc(&Context->Dpc, LogDpc, NULL);
+
     if (__LogDbgPrintCallbackEnable()) {
         status = DbgSetDebugPrintCallback(LogDebugPrint, TRUE);
 
-- 
2.5.3


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

 


Rackspace

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