summaryrefslogtreecommitdiff
path: root/datapath-windows
diff options
context:
space:
mode:
authorShashank Ram <rams@vmware.com>2016-11-22 17:32:54 -0800
committerGurucharan Shetty <guru@ovn.org>2016-12-12 10:57:50 -0800
commit278d07c46eecf9e0c4b503df2cd00d0571ebb3cd (patch)
tree97be55baa2e9ebd7510044b75d3dc9f5089dda03 /datapath-windows
parent1585ff634569ea37f92061b33733fd9a24c9b92a (diff)
downloadopenvswitch-278d07c46eecf9e0c4b503df2cd00d0571ebb3cd.tar.gz
datapath-windows: Avoid busy wait in OvsStartIpHelper
Previously, the IP Helper thread would wait for an event but with a timeout of 0, which resulted in the thread busy waiting causing high CPU usage by the kernel. Since the IP Helper thread is only required based on certain events, it makes sense to wait indefinitely till we receieve such an event notification to wake up the thread. This change aims to address this issue. When OvsEnqueueIpHelperRequest() or OvsInternalAdapterUp() is called, the ovsNumIpHelperRequests counter is incremented, but upon consumption of the request, is not decremented. Since the wakeup logic for the thread is determined by this counter value, we need to reset the counter back correctly once the request has been consumed by the IP Helper thread. Signed-off-by: Shashank Ram <rams@vmware.com> Acked-by: Yin Lin <linyi@vmware.com> Signed-off-by: Gurucharan Shetty <guru@ovn.org>
Diffstat (limited to 'datapath-windows')
-rw-r--r--datapath-windows/ovsext/IpHelper.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c
index d747e8c2e..636cf9526 100644
--- a/datapath-windows/ovsext/IpHelper.c
+++ b/datapath-windows/ovsext/IpHelper.c
@@ -1091,9 +1091,11 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId)
InsertHeadList(&ovsIpHelperRequestList, &request->link);
ovsNumIpHelperRequests++;
if (ovsNumIpHelperRequests == 1) {
+ NdisReleaseSpinLock(&ovsIpHelperLock);
OvsWakeupIPHelper();
+ } else {
+ NdisReleaseSpinLock(&ovsIpHelperLock);
}
- NdisReleaseSpinLock(&ovsIpHelperLock);
}
@@ -1455,12 +1457,14 @@ OvsStartIpHelper(PVOID data)
POVS_IPNEIGH_ENTRY ipn;
PLIST_ENTRY link;
UINT64 timeVal, timeout;
+ PLARGE_INTEGER threadSleepTimeout;
OVS_LOG_INFO("Start the IP Helper Thread, context: %p", context);
NdisAcquireSpinLock(&ovsIpHelperLock);
while (!context->exit) {
+ threadSleepTimeout = NULL;
timeout = 0;
while (!IsListEmpty(&ovsIpHelperRequestList)) {
if (context->exit) {
@@ -1468,6 +1472,7 @@ OvsStartIpHelper(PVOID data)
}
link = ovsIpHelperRequestList.Flink;
RemoveEntryList(link);
+ ovsNumIpHelperRequests--;
NdisReleaseSpinLock(&ovsIpHelperLock);
req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
switch (req->command) {
@@ -1497,6 +1502,7 @@ OvsStartIpHelper(PVOID data)
KeQuerySystemTime((LARGE_INTEGER *)&timeVal);
if (ipn->timeout > timeVal) {
timeout = ipn->timeout;
+ threadSleepTimeout = (PLARGE_INTEGER)&timeout;
break;
}
ipAddr = ipn->ipAddr;
@@ -1519,8 +1525,13 @@ ip_helper_wait:
KeClearEvent(&context->event);
NdisReleaseSpinLock(&ovsIpHelperLock);
+ /*
+ * Wait indefinitely for the thread to be woken up.
+ * Passing NULL as the Timeout value in the below
+ * call to KeWaitForSingleObject achieves this.
+ */
KeWaitForSingleObject(&context->event, Executive, KernelMode,
- FALSE, (LARGE_INTEGER *)&timeout);
+ FALSE, threadSleepTimeout);
NdisAcquireSpinLock(&ovsIpHelperLock);
}
NdisReleaseSpinLock(&ovsIpHelperLock);