Skip to content

Commit

Permalink
Kernel / Library - Introduce thread & Memory poll to process and pull…
Browse files Browse the repository at this point in the history
… events

This is highly based on #307 without the async logic. The reason is to avoid using the kernel NotificationLoop that was dispatching requests to workers (userland thread) sequentially. It has a high cost to do a thread switch each time to wake up the workers.
The current logic is nice when you want workers to be async but as we have threads (and now a thread poll) dedicated to pull and process events, we can make them synchronously wait for new events and take them from the request list themself.
This commit introduces the logic of a single main thread that polls events by batch and dispatches them to other threads and keeps the last one for itself to process and send the response to the kernel. Each thread waken will do the same and pull new events at the same time. If none is returned, the thread goes back to sleep and otherwise does the same as the main thread (dispatch and process).
The difference is that the main thread waits indefinitely for new events while others wait 100ms in the kernel before returning back to userland.This and the memory poll also added, offer a great flexibility of resources especially on heavy load.

This CL is huge but the perf that comes with it are about 10-35% on sequential requests but in the real world with the thread poll the perf are way above.
@Corillian full rewrite of FindFiles improved the perf between 100-250%...
  • Loading branch information
Liryna committed Dec 29, 2021
1 parent 34dabb0 commit 1cc3478
Show file tree
Hide file tree
Showing 40 changed files with 2,803 additions and 1,769 deletions.
35 changes: 14 additions & 21 deletions dokan/cleanup.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,25 @@ with this program. If not, see <http://www.gnu.org/licenses/>.

#include "dokani.h"

VOID DispatchCleanup(HANDLE Handle, PEVENT_CONTEXT EventContext,
PDOKAN_INSTANCE DokanInstance) {
PEVENT_INFORMATION eventInfo;
DOKAN_FILE_INFO fileInfo;
PDOKAN_OPEN_INFO openInfo;
ULONG sizeOfEventInfo = DispatchGetEventInformationLength(0);
VOID DispatchCleanup(PDOKAN_IO_EVENT IoEvent) {
CheckFileName(IoEvent->EventContext->Operation.Cleanup.FileName);

CheckFileName(EventContext->Operation.Cleanup.FileName);
CreateDispatchCommon(IoEvent, 0);

eventInfo = DispatchCommon(EventContext, sizeOfEventInfo, DokanInstance,
&fileInfo, &openInfo);
IoEvent->EventResult->Status = STATUS_SUCCESS; // return success at any case

eventInfo->Status = STATUS_SUCCESS; // return success at any case
DbgPrint("###Cleanup file handle = 0x%p, eventID = %04d, event Info = 0x%p\n",
IoEvent->DokanOpenInfo,
IoEvent->DokanOpenInfo != NULL ? IoEvent->DokanOpenInfo->EventId
: -1,
IoEvent);

DbgPrint("###Cleanup %04d\n", openInfo != NULL ? openInfo->EventId : -1);

if (DokanInstance->DokanOperations->Cleanup) {
if (IoEvent->DokanInstance->DokanOperations->Cleanup) {
// ignore return value
DokanInstance->DokanOperations->Cleanup(
EventContext->Operation.Cleanup.FileName, &fileInfo);
IoEvent->DokanInstance->DokanOperations->Cleanup(
IoEvent->EventContext->Operation.Cleanup.FileName,
&IoEvent->DokanFileInfo);
}

if (openInfo != NULL)
openInfo->UserContext = fileInfo.Context;

SendEventInformation(Handle, eventInfo, sizeOfEventInfo);
ReleaseDokanOpenInfo(eventInfo, &fileInfo, DokanInstance);
free(eventInfo);
EventCompletion(IoEvent);
}
38 changes: 15 additions & 23 deletions dokan/close.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,27 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "dokani.h"
#include "dokan_pool.h"

VOID DispatchClose(HANDLE Handle, PEVENT_CONTEXT EventContext,
PDOKAN_INSTANCE DokanInstance) {
PEVENT_INFORMATION eventInfo;
DOKAN_FILE_INFO fileInfo;
PDOKAN_OPEN_INFO openInfo;
ULONG sizeOfEventInfo = DispatchGetEventInformationLength(0);
VOID DispatchClose(PDOKAN_IO_EVENT IoEvent) {
CheckFileName(IoEvent->EventContext->Operation.Close.FileName);

UNREFERENCED_PARAMETER(Handle);
DbgPrint("###Close file handle = 0x%p, eventID = %04d, event Info = 0x%p\n",
IoEvent->DokanOpenInfo,
IoEvent->DokanOpenInfo != NULL ? IoEvent->DokanOpenInfo->EventId
: -1,
IoEvent);

CheckFileName(EventContext->Operation.Close.FileName);

eventInfo = DispatchCommon(EventContext, sizeOfEventInfo, DokanInstance,
&fileInfo, &openInfo);

eventInfo->Status = STATUS_SUCCESS; // return success at any case

DbgPrint("###Close %04d\n", openInfo != NULL ? openInfo->EventId : -1);

// Driver has simply notifying us of the Close request which he has
// already completed at this stage. Driver is not expecting us
// to reply from this so there is no need to send an EVENT_INFORMATION.

if (openInfo != NULL) {
EnterCriticalSection(&DokanInstance->CriticalSection);
openInfo->FileName = _wcsdup(EventContext->Operation.Close.FileName);
openInfo->OpenCount--;
LeaveCriticalSection(&DokanInstance->CriticalSection);
if (IoEvent->DokanOpenInfo) {
EnterCriticalSection(&IoEvent->DokanOpenInfo->CriticalSection);
IoEvent->DokanOpenInfo->FileName =
_wcsdup(IoEvent->EventContext->Operation.Close.FileName);
IoEvent->DokanOpenInfo->OpenCount--;
LeaveCriticalSection(&IoEvent->DokanOpenInfo->CriticalSection);
ReleaseDokanOpenInfo(IoEvent);
}
ReleaseDokanOpenInfo(eventInfo, &fileInfo, DokanInstance);
free(eventInfo);
}
Loading

0 comments on commit 1cc3478

Please sign in to comment.