https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fa607733cb063d233ca04…
commit fa607733cb063d233ca04c090b03e328d8645be7
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Sat Dec 25 14:18:53 2021 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Sat Dec 25 14:18:53 2021 +0100
[SCHEDSVC] Use a timer to start jobs
This enables the service to start multiple jobs at the same time.
---
base/services/schedsvc/job.c | 220 +++++++++++++++----------------------
base/services/schedsvc/precomp.h | 12 +-
base/services/schedsvc/rpcserver.c | 4 -
base/services/schedsvc/schedsvc.c | 26 +++--
4 files changed, 110 insertions(+), 152 deletions(-)
diff --git a/base/services/schedsvc/job.c b/base/services/schedsvc/job.c
index 558ac3797dd..e29d2732716 100644
--- a/base/services/schedsvc/job.c
+++ b/base/services/schedsvc/job.c
@@ -31,60 +31,59 @@ RTL_RESOURCE JobListLock;
LIST_ENTRY StartListHead;
RTL_RESOURCE StartListLock;
+FILETIME NextJobStartTime;
+BOOL bValidNextJobStartTime = FALSE;
+
static WORD wDaysArray[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* FUNCTIONS *****************************************************************/
-DWORD
-GetNextJobTimeout(VOID)
+VOID
+GetNextJobTimeout(HANDLE hTimer)
{
- FILETIME FileTime;
- SYSTEMTIME SystemTime;
- ULARGE_INTEGER CurrentTime, Timeout;
- PJOB pNextJob;
+ PLIST_ENTRY CurrentEntry;
+ FILETIME DueTime;
+ PJOB CurrentJob;
- if (IsListEmpty(&StartListHead))
+ bValidNextJobStartTime = FALSE;
+ CurrentEntry = JobListHead.Flink;
+ while (CurrentEntry != &JobListHead)
{
- TRACE("No job in list! Wait until next update.\n");
- return INFINITE;
- }
-
- pNextJob = CONTAINING_RECORD((&StartListHead)->Flink, JOB, StartEntry);
-
- FileTime.dwLowDateTime = pNextJob->StartTime.u.LowPart;
- FileTime.dwHighDateTime = pNextJob->StartTime.u.HighPart;
- FileTimeToSystemTime(&FileTime, &SystemTime);
-
- TRACE("Start next job (%lu) at %02hu:%02hu %02hu.%02hu.%hu\n",
- pNextJob->JobId, SystemTime.wHour, SystemTime.wMinute,
- SystemTime.wDay, SystemTime.wMonth, SystemTime.wYear);
-
- GetLocalTime(&SystemTime);
- SystemTimeToFileTime(&SystemTime, &FileTime);
+ CurrentJob = CONTAINING_RECORD(CurrentEntry, JOB, JobEntry);
- CurrentTime.u.LowPart = FileTime.dwLowDateTime;
- CurrentTime.u.HighPart = FileTime.dwHighDateTime;
+ if (bValidNextJobStartTime == FALSE)
+ {
+ CopyMemory(&NextJobStartTime, &CurrentJob->StartTime,
sizeof(FILETIME));
+ bValidNextJobStartTime = TRUE;
+ }
+ else
+ {
+ if (CompareFileTime(&NextJobStartTime, &CurrentJob->StartTime)
> 0)
+ CopyMemory(&NextJobStartTime, &CurrentJob->StartTime,
sizeof(FILETIME));
+ }
- if (CurrentTime.QuadPart >= pNextJob->StartTime.QuadPart)
- {
- TRACE("Next event has already gone by!\n");
- return 0;
+ CurrentEntry = CurrentEntry->Flink;
}
- Timeout.QuadPart = (pNextJob->StartTime.QuadPart - CurrentTime.QuadPart) / 10000;
- if (Timeout.u.HighPart != 0)
+ if (bValidNextJobStartTime == FALSE)
{
- TRACE("Event happens too far in the future!\n");
- return INFINITE;
+ TRACE("No valid job!\n");
+ return;
}
- TRACE("Timeout: %lu\n", Timeout.u.LowPart);
- return Timeout.u.LowPart;
-}
+ LocalFileTimeToFileTime(&DueTime, &NextJobStartTime);
+ SetWaitableTimer(hTimer,
+ (PLARGE_INTEGER)&DueTime,
+ 0,
+ NULL,
+ NULL,
+ TRUE);
+}
+#if 0
static
VOID
ReScheduleJob(
@@ -117,59 +116,61 @@ ReScheduleJob(
DumpStartList(&StartListHead);
#endif
}
-
+#endif
VOID
-RunNextJob(VOID)
+RunCurrentJobs(VOID)
{
PROCESS_INFORMATION ProcessInformation;
STARTUPINFOW StartupInfo;
+ PLIST_ENTRY CurrentEntry;
+ PJOB CurrentJob;
BOOL bRet;
- PJOB pNextJob;
- if (IsListEmpty(&StartListHead))
+ CurrentEntry = JobListHead.Flink;
+ while (CurrentEntry != &JobListHead)
{
- ERR("No job in list!\n");
- return;
- }
+ CurrentJob = CONTAINING_RECORD(CurrentEntry, JOB, JobEntry);
- pNextJob = CONTAINING_RECORD((&StartListHead)->Flink, JOB, StartEntry);
+ if (CompareFileTime(&NextJobStartTime, &CurrentJob->StartTime) == 0)
+ {
+ TRACE("Run job %ld: %S\n", CurrentJob->JobId,
CurrentJob->Command);
- TRACE("Run job %ld: %S\n", pNextJob->JobId, pNextJob->Command);
+ ZeroMemory(&StartupInfo, sizeof(StartupInfo));
+ StartupInfo.cb = sizeof(StartupInfo);
+ StartupInfo.lpTitle = CurrentJob->Command;
+ StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
+ StartupInfo.wShowWindow = SW_SHOWDEFAULT;
- ZeroMemory(&StartupInfo, sizeof(StartupInfo));
- StartupInfo.cb = sizeof(StartupInfo);
- StartupInfo.lpTitle = pNextJob->Command;
- StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
- StartupInfo.wShowWindow = SW_SHOWDEFAULT;
+ if ((CurrentJob->Flags & JOB_NONINTERACTIVE) == 0)
+ {
+ StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
+ StartupInfo.lpDesktop = L"WinSta0\\Default";
+ }
- if ((pNextJob->Flags & JOB_NONINTERACTIVE) == 0)
- {
- StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
- StartupInfo.lpDesktop = L"WinSta0\\Default";
- }
+ bRet = CreateProcessW(NULL,
+ CurrentJob->Command,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_CONSOLE,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ if (bRet == FALSE)
+ {
+ ERR("CreateProcessW() failed (Error %lu)\n", GetLastError());
+ }
+ else
+ {
+ CloseHandle(ProcessInformation.hThread);
+ CloseHandle(ProcessInformation.hProcess);
+ }
+ }
- bRet = CreateProcessW(NULL,
- pNextJob->Command,
- NULL,
- NULL,
- FALSE,
- CREATE_NEW_CONSOLE,
- NULL,
- NULL,
- &StartupInfo,
- &ProcessInformation);
- if (bRet == FALSE)
- {
- ERR("CreateProcessW() failed (Error %lu)\n", GetLastError());
- }
- else
- {
- CloseHandle(ProcessInformation.hThread);
- CloseHandle(ProcessInformation.hProcess);
+ CurrentEntry = CurrentEntry->Flink;
}
-
- ReScheduleJob(pNextJob);
}
@@ -420,8 +421,6 @@ LoadJobs(VOID)
/* Calculate the next start time */
CalculateNextStartTime(pJob);
- /* Insert the job into the start list */
- InsertJobIntoStartList(&StartListHead, pJob);
#if 0
DumpStartList(&StartListHead);
#endif
@@ -473,6 +472,7 @@ CalculateNextStartTime(
WORD wDaysOffset, wTempOffset, i, wJobDayOfWeek, wJobDayOfMonth;
DWORD_PTR CurrentTimeMs;
BOOL bDaysOffsetValid;
+ ULARGE_INTEGER LocalStartTime;
TRACE("CalculateNextStartTime(%p)\n", pJob);
TRACE("JobTime: %lu\n", pJob->JobTime);
@@ -590,66 +590,18 @@ CalculateNextStartTime(
SystemTimeToFileTime(&StartSystemTime, &StartFileTime);
- pJob->StartTime.u.LowPart = StartFileTime.dwLowDateTime;
- pJob->StartTime.u.HighPart = StartFileTime.dwHighDateTime;
+ LocalStartTime.u.LowPart = StartFileTime.dwLowDateTime;
+ LocalStartTime.u.HighPart = StartFileTime.dwHighDateTime;
if (bDaysOffsetValid && wDaysOffset != 0)
{
- pJob->StartTime.QuadPart += ((ULONGLONG)wDaysOffset * 24 * 60 * 60 * 10000);
- }
-}
-
-
-VOID
-InsertJobIntoStartList(
- _In_ PLIST_ENTRY StartListHead,
- _In_ PJOB pJob)
-{
- PLIST_ENTRY CurrentEntry, PreviousEntry;
- PJOB CurrentJob;
-
- if (IsListEmpty(StartListHead))
- {
- InsertHeadList(StartListHead, &pJob->StartEntry);
- return;
+ LocalStartTime.QuadPart += ((ULONGLONG)wDaysOffset * 24 * 60 * 60 * 10000);
}
- CurrentEntry = StartListHead->Flink;
- while (CurrentEntry != StartListHead)
- {
- CurrentJob = CONTAINING_RECORD(CurrentEntry, JOB, StartEntry);
-
- if ((CurrentEntry == StartListHead->Flink) &&
- (pJob->StartTime.QuadPart < CurrentJob->StartTime.QuadPart))
- {
- /* Insert before the first entry */
- InsertHeadList(StartListHead, &pJob->StartEntry);
- return;
- }
-
- if (pJob->StartTime.QuadPart < CurrentJob->StartTime.QuadPart)
- {
- /* Insert between the previous and the current entry */
- PreviousEntry = CurrentEntry->Blink;
- pJob->StartEntry.Blink = PreviousEntry;
- pJob->StartEntry.Flink = CurrentEntry;
- PreviousEntry->Flink = &pJob->StartEntry;
- CurrentEntry->Blink = &pJob->StartEntry;
- return;
- }
-
- if ((CurrentEntry->Flink == StartListHead) &&
- (pJob->StartTime.QuadPart >= CurrentJob->StartTime.QuadPart))
- {
- /* Insert after the last entry */
- InsertTailList(StartListHead, &pJob->StartEntry);
- return;
- }
-
- CurrentEntry = CurrentEntry->Flink;
- }
+ pJob->StartTime.dwLowDateTime = LocalStartTime.u.LowPart;
+ pJob->StartTime.dwHighDateTime = LocalStartTime.u.HighPart;
}
-
+#if 0
VOID
DumpStartList(
_In_ PLIST_ENTRY StartListHead)
@@ -657,8 +609,8 @@ DumpStartList(
PLIST_ENTRY CurrentEntry;
PJOB CurrentJob;
- CurrentEntry = StartListHead->Flink;
- while (CurrentEntry != StartListHead)
+ CurrentEntry = JobListHead->Flink;
+ while (CurrentEntry != &JobListHead)
{
CurrentJob = CONTAINING_RECORD(CurrentEntry, JOB, StartEntry);
@@ -667,5 +619,5 @@ DumpStartList(
CurrentEntry = CurrentEntry->Flink;
}
}
-
+#endif
/* EOF */
diff --git a/base/services/schedsvc/precomp.h b/base/services/schedsvc/precomp.h
index 992e16796d8..f3c3e4255cf 100644
--- a/base/services/schedsvc/precomp.h
+++ b/base/services/schedsvc/precomp.h
@@ -32,8 +32,7 @@ typedef struct _JOB
{
LIST_ENTRY JobEntry;
- LIST_ENTRY StartEntry;
- ULARGE_INTEGER StartTime;
+ FILETIME StartTime;
WCHAR Name[JOB_NAME_LENGTH];
DWORD JobId;
@@ -54,16 +53,17 @@ extern RTL_RESOURCE JobListLock;
extern LIST_ENTRY StartListHead;
extern RTL_RESOURCE StartListLock;
-extern HANDLE Events[2];
+extern HANDLE Events[3];
/* job.c */
-DWORD
-GetNextJobTimeout(VOID);
+VOID
+GetNextJobTimeout(
+ HANDLE hTimer);
VOID
-RunNextJob(VOID);
+RunCurrentJobs(VOID);
LONG
SaveJob(
diff --git a/base/services/schedsvc/rpcserver.c b/base/services/schedsvc/rpcserver.c
index 4ae657f6a2a..ca3c8fd5b99 100644
--- a/base/services/schedsvc/rpcserver.c
+++ b/base/services/schedsvc/rpcserver.c
@@ -121,8 +121,6 @@ NetrJobAdd(
/* Calculate the next start time */
CalculateNextStartTime(pJob);
- /* Insert the job into the start list */
- InsertJobIntoStartList(&StartListHead, pJob);
#if 0
DumpStartList(&StartListHead);
#endif
@@ -169,8 +167,6 @@ NetrJobDel(
if ((CurrentJob->JobId >= MinJobId) && (CurrentJob->JobId <=
MaxJobId))
{
- /* Remove the job from the start list */
- RemoveEntryList(&CurrentJob->StartEntry);
#if 0
DumpStartList(&StartListHead);
#endif
diff --git a/base/services/schedsvc/schedsvc.c b/base/services/schedsvc/schedsvc.c
index ba96195839f..dea78455141 100644
--- a/base/services/schedsvc/schedsvc.c
+++ b/base/services/schedsvc/schedsvc.c
@@ -37,7 +37,7 @@ static WCHAR ServiceName[] = L"Schedule";
static SERVICE_STATUS_HANDLE ServiceStatusHandle;
static SERVICE_STATUS ServiceStatus;
-HANDLE Events[2] = {NULL, NULL}; // StopEvent, UpdateEvent
+HANDLE Events[3] = {NULL, NULL, NULL}; // StopEvent, UpdateEvent, Timer
/* FUNCTIONS *****************************************************************/
@@ -181,6 +181,15 @@ ServiceInit(VOID)
return GetLastError();
}
+ Events[2] = CreateWaitableTimerW(NULL, FALSE, NULL);
+ if (Events[2] == NULL)
+ {
+ ERR("Could not create the timer\n");
+ CloseHandle(Events[1]);
+ CloseHandle(Events[0]);
+ return GetLastError();
+ }
+
return ERROR_SUCCESS;
}
@@ -188,7 +197,7 @@ ServiceInit(VOID)
VOID WINAPI
SchedServiceMain(DWORD argc, LPTSTR *argv)
{
- DWORD dwWait, dwTimeout, dwError;
+ DWORD dwWait, dwError;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
@@ -216,13 +225,13 @@ SchedServiceMain(DWORD argc, LPTSTR *argv)
UpdateServiceStatus(SERVICE_RUNNING);
- dwTimeout = GetNextJobTimeout();
+ GetNextJobTimeout(Events[2]);
for (;;)
{
/* Wait for the next event */
TRACE("Wait for next event!\n");
- dwWait = WaitForMultipleObjects(2, Events, FALSE, dwTimeout);
+ dwWait = WaitForMultipleObjects(3, Events, FALSE, INFINITE);
if (dwWait == WAIT_OBJECT_0)
{
TRACE("Stop event signaled!\n");
@@ -233,16 +242,16 @@ SchedServiceMain(DWORD argc, LPTSTR *argv)
TRACE("Update event signaled!\n");
RtlAcquireResourceShared(&JobListLock, TRUE);
- dwTimeout = GetNextJobTimeout();
+ GetNextJobTimeout(Events[2]);
RtlReleaseResource(&JobListLock);
}
- else if (dwWait == WAIT_TIMEOUT)
+ else if (dwWait == WAIT_OBJECT_0 + 2)
{
TRACE("Timeout: Start the next job!\n");
RtlAcquireResourceExclusive(&JobListLock, TRUE);
- RunNextJob();
- dwTimeout = GetNextJobTimeout();
+ RunCurrentJobs();
+ GetNextJobTimeout(Events[2]);
RtlReleaseResource(&JobListLock);
}
}
@@ -250,6 +259,7 @@ SchedServiceMain(DWORD argc, LPTSTR *argv)
/* Close the start and update event handles */
CloseHandle(Events[0]);
CloseHandle(Events[1]);
+ CloseHandle(Events[2]);
/* Stop the service */
UpdateServiceStatus(SERVICE_STOPPED);