From 6de65ddcea0c33887e86fd3dac02998b2967681e Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 15 Apr 2017 10:33:29 +0000 Subject: [PATCH] [SCHEDSVC] Insert a job into the start list when it is loaded or added. Remove it from the start list when it gets deleted. The start list is sorted by start time. svn path=/trunk/; revision=74317 --- reactos/base/services/schedsvc/job.c | 97 ++++++++++++++++++++-- reactos/base/services/schedsvc/precomp.h | 16 +++- reactos/base/services/schedsvc/rpcserver.c | 30 +++++-- 3 files changed, 124 insertions(+), 19 deletions(-) diff --git a/reactos/base/services/schedsvc/job.c b/reactos/base/services/schedsvc/job.c index 8e7a90c8805..89bd28daa34 100644 --- a/reactos/base/services/schedsvc/job.c +++ b/reactos/base/services/schedsvc/job.c @@ -276,19 +276,25 @@ LoadJobs(VOID) pJob->JobId = dwNextJobId++; dwJobCount++; + // Cancel the start timer + /* Append the new job to the job list */ InsertTailList(&JobListHead, &pJob->JobEntry); - /* Release the job list lock */ - RtlReleaseResource(&JobListLock); - /* Calculate the next start time */ CalculateNextStartTime(pJob); - // Insert job into the start list + /* Insert the job into the start list */ + InsertJobIntoStartList(&StartListHead, pJob); +#if 0 + DumpStartList(&StartListHead); +#endif // Update the start timer + /* Release the job list lock */ + RtlReleaseResource(&JobListLock); + pJob = NULL; } } @@ -330,8 +336,11 @@ VOID CalculateNextStartTime(PJOB pJob) { SYSTEMTIME StartTime; + FILETIME FileTime; DWORD_PTR Now; + TRACE("CalculateNextStartTime(%p)\n", pJob); + GetLocalTime(&StartTime); Now = (DWORD_PTR)StartTime.wHour * 3600000 + @@ -365,8 +374,82 @@ CalculateNextStartTime(PJOB pJob) } } - ERR("Next start: %02hu:%02hu %02hu.%02hu.%hu\n", StartTime.wHour, - StartTime.wMinute, StartTime.wDay, StartTime.wMonth, StartTime.wYear); + TRACE("Next start: %02hu:%02hu %02hu.%02hu.%hu\n", StartTime.wHour, + StartTime.wMinute, StartTime.wDay, StartTime.wMonth, StartTime.wYear); - SystemTimeToFileTime(&StartTime, &pJob->StartTime); + SystemTimeToFileTime(&StartTime, &FileTime); + pJob->StartTime.u.LowPart = FileTime.dwLowDateTime; + pJob->StartTime.u.HighPart = FileTime.dwHighDateTime; } + + +VOID +InsertJobIntoStartList( + _In_ PLIST_ENTRY StartListHead, + _In_ PJOB pJob) +{ + PLIST_ENTRY CurrentEntry, PreviousEntry; + PJOB CurrentJob; + + if (IsListEmpty(StartListHead)) + { + InsertHeadList(StartListHead, &pJob->StartEntry); + return; + } + + 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; + } +} + + +VOID +DumpStartList( + _In_ PLIST_ENTRY StartListHead) +{ + PLIST_ENTRY CurrentEntry; + PJOB CurrentJob; + + CurrentEntry = StartListHead->Flink; + while (CurrentEntry != StartListHead) + { + CurrentJob = CONTAINING_RECORD(CurrentEntry, JOB, StartEntry); + + TRACE("%3lu: %016I64x\n", CurrentJob->JobId, CurrentJob->StartTime.QuadPart); + + CurrentEntry = CurrentEntry->Flink; + } +} + +/* EOF */ diff --git a/reactos/base/services/schedsvc/precomp.h b/reactos/base/services/schedsvc/precomp.h index 0da85a0d450..5d472d3fe75 100644 --- a/reactos/base/services/schedsvc/precomp.h +++ b/reactos/base/services/schedsvc/precomp.h @@ -4,6 +4,7 @@ #define WIN32_NO_STATUS #define _INC_WINDOWS #define COM_NO_WINDOWS_H +#include #include #include #include @@ -28,7 +29,7 @@ typedef struct _JOB LIST_ENTRY JobEntry; LIST_ENTRY StartEntry; - FILETIME StartTime; + ULARGE_INTEGER StartTime; WCHAR Name[9]; DWORD JobId; @@ -39,7 +40,6 @@ typedef struct _JOB WCHAR Command[1]; } JOB, *PJOB; -#define DWORD_MAX 0xffffffffUL extern DWORD dwNextJobId; extern DWORD dwJobCount; @@ -66,7 +66,17 @@ LoadJobs(VOID); VOID CalculateNextStartTime( - PJOB pJob); + _In_ PJOB pJob); + +VOID +InsertJobIntoStartList( + _In_ PLIST_ENTRY StartListHead, + _In_ PJOB pJob); + +VOID +DumpStartList( + _In_ PLIST_ENTRY StartListHead); + /* rpcserver.c */ diff --git a/reactos/base/services/schedsvc/rpcserver.c b/reactos/base/services/schedsvc/rpcserver.c index e23371ec65a..1ca2b353ee2 100644 --- a/reactos/base/services/schedsvc/rpcserver.c +++ b/reactos/base/services/schedsvc/rpcserver.c @@ -112,22 +112,28 @@ NetrJobAdd( pJob->JobId = dwNextJobId++; dwJobCount++; + // Cancel the start timer + /* Append the new job to the job list */ InsertTailList(&JobListHead, &pJob->JobEntry); - /* Release the job list lock */ - RtlReleaseResource(&JobListLock); - /* Save the job in the registry */ SaveJob(pJob); /* Calculate the next start time */ CalculateNextStartTime(pJob); - // Insert job into the start list + /* Insert the job into the start list */ + InsertJobIntoStartList(&StartListHead, pJob); +#if 0 + DumpStartList(&StartListHead); +#endif // Update the start timer + /* Release the job list lock */ + RtlReleaseResource(&JobListLock); + /* Return the new job ID */ *pJobId = pJob->JobId; @@ -156,6 +162,8 @@ NetrJobDel( /* Acquire the job list lock exclusively */ RtlAcquireResourceExclusive(&JobListLock, TRUE); + // Cancel the start timer + JobEntry = JobListHead.Flink; while (JobEntry != &JobListHead) { @@ -163,9 +171,11 @@ NetrJobDel( if ((CurrentJob->JobId >= MinJobId) && (CurrentJob->JobId <= MaxJobId)) { - // Remove job from the start list - - // Update the start timer + /* Remove the job from the start list */ + RemoveEntryList(&CurrentJob->StartEntry); +#if 0 + DumpStartList(&StartListHead); +#endif /* Remove the job from the registry */ DeleteJob(CurrentJob); @@ -183,6 +193,8 @@ NetrJobDel( JobEntry = JobEntry->Flink; } + // Update the start timer + /* Release the job list lock */ RtlReleaseResource(&JobListLock); @@ -245,7 +257,7 @@ NetrJobEnum( (wcslen(CurrentJob->Command) + 1) * sizeof(WCHAR); TRACE("dwEntrySize: %lu\n", dwEntrySize); - if ((PreferedMaximumLength != DWORD_MAX) && + if ((PreferedMaximumLength != ULONG_MAX) && (dwRequiredSize + dwEntrySize > PreferedMaximumLength)) break; @@ -259,7 +271,7 @@ NetrJobEnum( TRACE("dwEntriesToRead: %lu\n", dwEntriesToRead); TRACE("dwRequiredSize: %lu\n", dwRequiredSize); - if (PreferedMaximumLength != DWORD_MAX) + if (PreferedMaximumLength != ULONG_MAX) dwRequiredSize = PreferedMaximumLength; TRACE("Allocating dwRequiredSize: %lu\n", dwRequiredSize);