https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fa607733cb063d233ca04c...
commit fa607733cb063d233ca04c090b03e328d8645be7 Author: Eric Kohl eric.kohl@reactos.org AuthorDate: Sat Dec 25 14:18:53 2021 +0100 Commit: Eric Kohl eric.kohl@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);