Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

653 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. idletsks.h
  5. Abstract:
  6. This module contains private declarations for the idle task & detection
  7. server.
  8. Author:
  9. Dave Fields (davidfie) 26-July-1998
  10. Cenk Ergan (cenke) 14-June-2000
  11. Revision History:
  12. --*/
  13. #ifndef _IDLETSKS_H_
  14. #define _IDLETSKS_H_
  15. //
  16. // Include public and common definitions.
  17. //
  18. #include <wmium.h>
  19. #include <ntdddisk.h>
  20. #include "idlrpc.h"
  21. #include "idlecomn.h"
  22. //
  23. // Define the default period in ms for checking if the system is idle.
  24. //
  25. #define IT_DEFAULT_IDLE_DETECTION_PERIOD (12 * 60 * 1000) // 12 minutes.
  26. //
  27. // If the system has been idle over the idle detection period, we
  28. // verify that it is really idle by checking frequently over a shorter
  29. // period for a number of times. This helps us know when there were
  30. // 100 disk I/O's in the last second of idle detection period, but
  31. // over 15 minutes it does not look a lot.
  32. //
  33. #define IT_DEFAULT_IDLE_VERIFICATION_PERIOD (30 * 1000) // 30 seconds.
  34. #define IT_DEFAULT_NUM_IDLE_VERIFICATIONS 5 // 5 times.
  35. //
  36. // We will be polling for user input when running idle tasks every
  37. // this many ms. We want to catch user input and notify the idle task
  38. // to stop running as soon as possible. Even though the system is
  39. // idle, we don't want to create too much overhead which may mislead
  40. // ourself.
  41. //
  42. #define IT_DEFAULT_IDLE_USER_INPUT_CHECK_PERIOD 250 // 4 times a sec.
  43. // FUTURE-2002/03/26-ScottMa -- The constant (below) is not used, except
  44. // to initialize the [unused] IdleTaskRunningCheckPeriod parameter.
  45. //
  46. // We check to see if the idle task we asked to run is really running
  47. // (i.e. it is using the disk and CPU) every this many ms. This is our
  48. // mechanism for cleaning up after unregistered/orphaned tasks. This
  49. // should be greater than IT_USER_INPUT_POLL_PERIOD_WHEN_IDLE.
  50. //
  51. #define IT_DEFAULT_IDLE_TASK_RUNNING_CHECK_PERIOD (5 * 60 * 1000) // 5 min.
  52. //
  53. // If the CPU is not idle more than this percent over a time interval,
  54. // the system is not considered idle.
  55. //
  56. #define IT_DEFAULT_MIN_CPU_IDLE_PERCENTAGE 90
  57. //
  58. // If a disk is not idle more than this percent over a time interval,
  59. // the system is not considered idle.
  60. //
  61. #define IT_DEFAULT_MIN_DISK_IDLE_PERCENTAGE 90
  62. //
  63. // We will not try to run our tasks if there is only this many seconds
  64. // left before the system will enter hibernate or standby automatically.
  65. // Note that the time remaining is updated every so many seconds (e.g.
  66. // 15) so this number should not be very small.
  67. //
  68. // FUTURE-2002/03/26-ScottMa -- This constant doesn't have a corresponding
  69. // parameter in the IT_IDLE_DETECTION_PARAMETERS structure. Should it
  70. // be added to the structure like the others?
  71. #define IT_DEFAULT_MAX_TIME_REMAINING_TO_SLEEP 60
  72. //
  73. // This is the maximum number of registered idle tasks. This is a
  74. // sanity check. It also protects against evil callers.
  75. //
  76. #define IT_DEFAULT_MAX_REGISTERED_TASKS 512
  77. //
  78. // We set timer period for idle detection callback to this while the
  79. // callback is running to prevent new callbacks from firing. We end up
  80. // having to do this because you cannot requeue/change a timer for
  81. // which you don't specify a period. If a callback fires while another
  82. // one is already running, it simply returns without doing anything.
  83. //
  84. #define IT_VERYLONG_TIMER_PERIOD 0x7FFFFFFF
  85. //
  86. // This is the number of recent server statuses that we keep track
  87. // of. Do not make this number smaller without revisiting the logic &
  88. // code that uses the LastStatus history.
  89. //
  90. #define ITSRV_GLOBAL_STATUS_HISTORY_SIZE 8
  91. //
  92. // Hints for the number of outstanding RPC call-ins we will have.
  93. //
  94. #define ITSRV_RPC_MIN_CALLS 1
  95. #define ITSRV_RPC_MAX_CALLS 1
  96. //
  97. // Define useful macros.
  98. //
  99. #define IT_ALLOC(NumBytes) (HeapAlloc(GetProcessHeap(),0,(NumBytes)))
  100. #define IT_FREE(Buffer) (HeapFree(GetProcessHeap(),0,(Buffer)))
  101. //
  102. // These macros are used to acquire/release a mutex.
  103. //
  104. #define IT_ACQUIRE_LOCK(Lock) \
  105. WaitForSingleObject((Lock), INFINITE); \
  106. #define IT_RELEASE_LOCK(Lock) \
  107. ReleaseMutex((Lock)); \
  108. //
  109. // This macro is used in the idle detection callback (while holding
  110. // the global lock of the input global context) to determine if the
  111. // idle detection callback should just exit/go away.
  112. //
  113. #define ITSP_SHOULD_STOP_IDLE_DETECTION(GlobalContext) \
  114. ((GlobalContext->Status == ItSrvStatusStoppingIdleDetection) || \
  115. (GlobalContext->Status == ItSrvStatusUninitializing)) \
  116. //
  117. // Status of a server global context. It also acts as a magic to
  118. // identify/verify the global context, as it starts from Df00. There
  119. // is not a full-blown state machine, although the state is used as a
  120. // critical hint for making decisions when registering an idle
  121. // task. This is more for informative and verification purposes. If
  122. // you add a new status without updating everything that needs to be
  123. // updated, you may hit several asserts, especially in the idle
  124. // detection callback. Frankly, don't add a new state without a very
  125. // good reason.
  126. //
  127. typedef enum _ITSRV_GLOBAL_CONTEXT_STATUS {
  128. ItSrvStatusMinStatus = 'Df00',
  129. ItSrvStatusInitializing,
  130. ItSrvStatusWaitingForIdleTasks,
  131. ItSrvStatusDetectingIdle,
  132. ItSrvStatusRunningIdleTasks,
  133. ItSrvStatusStoppingIdleDetection,
  134. ItSrvStatusUninitializing,
  135. ItSrvStatusUninitialized,
  136. ItSrvStatusMaxStatus
  137. } ITSRV_GLOBAL_CONTEXT_STATUS, *PITSRV_GLOBAL_CONTEXT_STATUS;
  138. //
  139. // These are the various types of idle detection overrides. Multiple
  140. // overrides can be specified by OR'ing them (i.e. these are bits!)
  141. //
  142. // If you are adding an override here, check whether you need to specify
  143. // it when force-processing all idle tasks.
  144. //
  145. typedef enum _ITSRV_IDLE_DETECTION_OVERRIDE {
  146. ItSrvOverrideIdleDetection = 0x00000001,
  147. ItSrvOverrideIdleVerification = 0x00000002,
  148. ItSrvOverrideUserInputCheckToStopTask = 0x00000004,
  149. // FUTURE-2002/03/26-ScottMa -- The ItSrvOverrideTaskRunningCheck value
  150. // is never used, presumably because some code was removed.
  151. ItSrvOverrideTaskRunningCheck = 0x00000008,
  152. ItSrvOverridePostTaskIdleCheck = 0x00000010,
  153. ItSrvOverrideLongRequeueTime = 0x00000020,
  154. ItSrvOverrideBatteryCheckToStopTask = 0x00000040,
  155. ItSrvOverrideAutoPowerCheckToStopTask = 0x00000080,
  156. } ITSRV_IDLE_DETECTION_OVERRIDE, *PITSRV_IDLE_DETECTION_OVERRIDE;
  157. //
  158. // These are the various reasons why ItSpIsSystemIdle function may be
  159. // called.
  160. //
  161. // FUTURE-2002/03/26-ScottMa -- The ItSrvIdleTaskRunningCheck is never passed
  162. // to the ItSpIsSystemIdle function, presumably because the call was removed.
  163. // to initialize the [unused] IdleTaskRunningCheckPeriod parameter. Further,
  164. // there is no difference between the other two reasons -- is it needed?
  165. typedef enum _ITSRV_IDLE_CHECK_REASON {
  166. ItSrvInitialIdleCheck,
  167. ItSrvIdleVerificationCheck,
  168. ItSrvIdleTaskRunningCheck,
  169. ItSrvMaxIdleCheckReason
  170. }ITSRV_IDLE_CHECK_REASON, *PITSRV_IDLE_CHECK_REASON;
  171. //
  172. // This structure is used to keep context for a registered task for
  173. // the server.
  174. //
  175. typedef struct _ITSRV_IDLE_TASK_CONTEXT {
  176. //
  177. // Link in the list of idle tasks.
  178. //
  179. LIST_ENTRY IdleTaskLink;
  180. //
  181. // Status of the idle task.
  182. //
  183. IT_IDLE_TASK_STATUS Status;
  184. //
  185. // Idle task properties the client specified.
  186. //
  187. IT_IDLE_TASK_PROPERTIES Properties;
  188. //
  189. // Event to be notified when the task should start running
  190. // (e.g. the system is idle).
  191. //
  192. HANDLE StartEvent;
  193. //
  194. // Event to be notified when the task should stop running.
  195. //
  196. HANDLE StopEvent;
  197. } ITSRV_IDLE_TASK_CONTEXT, *PITSRV_IDLE_TASK_CONTEXT;
  198. //
  199. // This structure contains disk performance information we are
  200. // interested in.
  201. //
  202. typedef struct _ITSRV_DISK_PERFORMANCE_DATA {
  203. //
  204. // How long the disk was idle in ms.
  205. //
  206. ULONG DiskIdleTime;
  207. } ITSRV_DISK_PERFORMANCE_DATA, *PITSRV_DISK_PERFORMANCE_DATA;
  208. //
  209. // Define structure to contain system resource information & state at
  210. // a specific time.
  211. //
  212. typedef struct _ITSRV_SYSTEM_SNAPSHOT {
  213. //
  214. // When this snapshot was taken, in ms elapsed since system was
  215. // started (i.e. GetTickCount)
  216. //
  217. DWORD SnapshotTime;
  218. //
  219. // Whether we were able to get the specified data in this snapshot.
  220. //
  221. ULONG GotLastInputInfo:1;
  222. ULONG GotSystemPerformanceInfo:1;
  223. ULONG GotDiskPerformanceInfo:1;
  224. ULONG GotSystemPowerStatus:1;
  225. ULONG GotSystemPowerInfo:1;
  226. ULONG GotSystemExecutionState:1;
  227. ULONG GotDisplayPowerStatus:1;
  228. //
  229. // This is when the last user input happened before the snapshot
  230. // was taken.
  231. //
  232. LASTINPUTINFO LastInputInfo;
  233. //
  234. // System performance information when the snapshot was taken.
  235. //
  236. SYSTEM_PERFORMANCE_INFORMATION SystemPerformanceInfo;
  237. //
  238. // Disk performance data on registered harddisks when the snapshot
  239. // was taken.
  240. //
  241. ULONG NumPhysicalDisks;
  242. ITSRV_DISK_PERFORMANCE_DATA *DiskPerfData;
  243. //
  244. // System power status (e.g. are we running on battery etc.)
  245. //
  246. SYSTEM_POWER_STATUS SystemPowerStatus;
  247. //
  248. // System power information (e.g. how long till system turns itself
  249. // off & goes to sleep.)
  250. //
  251. SYSTEM_POWER_INFORMATION PowerInfo;
  252. //
  253. // System execution state (e.g. is somebody running a presentation?)
  254. //
  255. EXECUTION_STATE ExecutionState;
  256. //
  257. // Whether the screen saver is running.
  258. //
  259. BOOL ScreenSaverIsRunning;
  260. } ITSRV_SYSTEM_SNAPSHOT, *PITSRV_SYSTEM_SNAPSHOT;
  261. //
  262. // Type for the routine that is called to notify that forced processing of
  263. // idle tasks have been requested.
  264. //
  265. typedef VOID (*PIT_PROCESS_IDLE_TASKS_NOTIFY_ROUTINE)(VOID);
  266. //
  267. // Define structure to contain server global context for idle
  268. // detection and keeping track of registered idle tasks.
  269. //
  270. typedef struct _ITSRV_GLOBAL_CONTEXT {
  271. //
  272. // Status of the server and its history, LastStatus[0] being the
  273. // most recent. The status version is incremented each time the
  274. // status is updated.
  275. //
  276. ITSRV_GLOBAL_CONTEXT_STATUS Status;
  277. ITSRV_GLOBAL_CONTEXT_STATUS LastStatus[ITSRV_GLOBAL_STATUS_HISTORY_SIZE];
  278. LONG StatusVersion;
  279. //
  280. // Nearly all operations involve the idle tasks list and instead
  281. // of having a lock for the list and seperate synchronization
  282. // mechanisms for other operations on the structure, we have a
  283. // single global lock to make life simpler.
  284. //
  285. HANDLE GlobalLock;
  286. //
  287. // This is the list and number of idle tasks that have been
  288. // scheduled.
  289. //
  290. LIST_ENTRY IdleTasksList;
  291. ULONG NumIdleTasks;
  292. //
  293. // Handle to the timer queue timer that is used to periodically
  294. // check for system idleness.
  295. //
  296. HANDLE IdleDetectionTimerHandle;
  297. //
  298. // This manual reset event gets signaled when idle detection
  299. // should stop (e.g. because there are no more idle tasks, the
  300. // server is shutting down etc.) It signals a running idle
  301. // detection callback to quickly exit.
  302. //
  303. HANDLE StopIdleDetection;
  304. //
  305. // This manual reset event gets signaled when idle detection has
  306. // fully stopped (i.e. no callback is running, the timer is not in
  307. // the queue etc.
  308. //
  309. HANDLE IdleDetectionStopped;
  310. //
  311. // This manual reset event is signaled when an idle task that was
  312. // running is unregistered/removed. This would happen usually
  313. // after an idle task that was told to run completes and has no
  314. // more to do. It unregisters itself, and this event is set to
  315. // notify the idle detection callback to move on to other idle
  316. // tasks.
  317. //
  318. HANDLE RemovedRunningIdleTask;
  319. // FUTURE-2002/03/26-ScottMa -- The field (below) is never used as an
  320. // L-value, except in the [unused] ItSpSetProcessIdleTasksNotifyRoutine
  321. // function.
  322. //
  323. // If it is set, this routine is called to notify that
  324. // forced processing of idle tasks have been requested.
  325. //
  326. PIT_PROCESS_IDLE_TASKS_NOTIFY_ROUTINE ProcessIdleTasksNotifyRoutine;
  327. //
  328. // These are the parameters that control idle detection.
  329. //
  330. IT_IDLE_DETECTION_PARAMETERS Parameters;
  331. //
  332. // This is the WMI handle used in disk performance queries.
  333. //
  334. WMIHANDLE DiskPerfWmiHandle;
  335. //
  336. // Number of processors on the system. Used to calculate CPU
  337. // utilization.
  338. //
  339. UCHAR NumProcessors;
  340. //
  341. // This buffer is used to make Wmi queries. It is maintained here
  342. // so we don't have to allocate a new one each time.
  343. //
  344. PVOID WmiQueryBuffer;
  345. ULONG WmiQueryBufferSize;
  346. //
  347. // The last system resource / activity snapshot we took.
  348. //
  349. // FUTURE-2002/03/26-ScottMa -- Adding the CurrentSystemSnapshot to the
  350. // global context would remove the need to repeatedly initialize and
  351. // cleanup the stack variable in the ItSpIdleDetectionCallbackRoutine.
  352. // Since the calls to that function are already protected against
  353. // re-entrancy issues, adding it to the global context is safe.
  354. ITSRV_SYSTEM_SNAPSHOT LastSystemSnapshot;
  355. //
  356. // Is an idle detection callback already running? This is used to
  357. // protect us from idle detection callbacks being fired while
  358. // there is already one active.
  359. //
  360. BOOLEAN IsIdleDetectionCallbackRunning;
  361. //
  362. // Various phases of idle detection can be overriden by setting
  363. // this.
  364. //
  365. ITSRV_IDLE_DETECTION_OVERRIDE IdleDetectionOverride;
  366. //
  367. // RPC binding vector used to register ourselves in the local
  368. // endpoint-map database.
  369. //
  370. RPC_BINDING_VECTOR *RpcBindingVector;
  371. //
  372. // Whether we actually registered our endpoint and interface.
  373. //
  374. BOOLEAN RegisteredRPCEndpoint;
  375. BOOLEAN RegisteredRPCInterface;
  376. } ITSRV_GLOBAL_CONTEXT, *PITSRV_GLOBAL_CONTEXT;
  377. //
  378. // Server function declarations. They should be only used by the
  379. // server host and the client functions.
  380. //
  381. DWORD
  382. ItSrvInitialize (
  383. VOID
  384. );
  385. VOID
  386. ItSrvUninitialize (
  387. VOID
  388. );
  389. //
  390. // Local support function prototypes for the server.
  391. //
  392. RPC_STATUS
  393. RPC_ENTRY
  394. ItSpRpcSecurityCallback (
  395. IN RPC_IF_HANDLE *Interface,
  396. IN PVOID Context
  397. );
  398. VOID
  399. ItSpUnregisterIdleTask (
  400. ITRPC_HANDLE Reserved,
  401. IT_HANDLE *ItHandle,
  402. BOOLEAN CalledInternally
  403. );
  404. VOID
  405. ItSpUpdateStatus (
  406. PITSRV_GLOBAL_CONTEXT GlobalContext,
  407. ITSRV_GLOBAL_CONTEXT_STATUS NewStatus
  408. );
  409. VOID
  410. ItSpCleanupGlobalContext (
  411. PITSRV_GLOBAL_CONTEXT GlobalContext
  412. );
  413. VOID
  414. ItSpCleanupIdleTask (
  415. PITSRV_IDLE_TASK_CONTEXT IdleTask
  416. );
  417. ULONG
  418. ItpVerifyIdleTaskProperties (
  419. PIT_IDLE_TASK_PROPERTIES IdleTaskProperties
  420. );
  421. DWORD
  422. ItSpStartIdleDetection (
  423. PITSRV_GLOBAL_CONTEXT GlobalContext
  424. );
  425. VOID
  426. ItSpStopIdleDetection (
  427. PITSRV_GLOBAL_CONTEXT GlobalContext
  428. );
  429. VOID
  430. CALLBACK
  431. ItSpIdleDetectionCallbackRoutine (
  432. PVOID Parameter,
  433. BOOLEAN TimerOrWaitFired
  434. );
  435. PITSRV_IDLE_TASK_CONTEXT
  436. ItSpFindRunningIdleTask (
  437. PITSRV_GLOBAL_CONTEXT GlobalContext
  438. );
  439. PITSRV_IDLE_TASK_CONTEXT
  440. ItSpFindIdleTask (
  441. PITSRV_GLOBAL_CONTEXT GlobalContext,
  442. IT_HANDLE ItHandle
  443. );
  444. VOID
  445. ItSpInitializeSystemSnapshot (
  446. PITSRV_SYSTEM_SNAPSHOT SystemSnapshot
  447. );
  448. VOID
  449. ItSpCleanupSystemSnapshot (
  450. PITSRV_SYSTEM_SNAPSHOT SystemSnapshot
  451. );
  452. DWORD
  453. ItSpCopySystemSnapshot (
  454. PITSRV_SYSTEM_SNAPSHOT DestSnapshot,
  455. PITSRV_SYSTEM_SNAPSHOT SourceSnapshot
  456. );
  457. DWORD
  458. ItSpGetSystemSnapshot (
  459. PITSRV_GLOBAL_CONTEXT GlobalContext,
  460. PITSRV_SYSTEM_SNAPSHOT SystemSnapshot
  461. );
  462. // FUTURE-2002/03/26-ScottMa -- If the CurrentSystemSnapshot is added to the
  463. // global context, both parameters no longer need to be passed to this
  464. // function. It is only called from within ItSpIdleDetectionCallbackRoutine,
  465. // and always uses the same values for current & last snapshot.
  466. BOOLEAN
  467. ItSpIsSystemIdle (
  468. PITSRV_GLOBAL_CONTEXT GlobalContext,
  469. PITSRV_SYSTEM_SNAPSHOT CurrentSnapshot,
  470. PITSRV_SYSTEM_SNAPSHOT LastSnapshot,
  471. ITSRV_IDLE_CHECK_REASON IdleCheckReason
  472. );
  473. DWORD
  474. ItSpGetLastInputInfo (
  475. PLASTINPUTINFO LastInputInfo
  476. );
  477. DWORD
  478. ItSpGetWmiDiskPerformanceData(
  479. IN WMIHANDLE DiskPerfWmiHandle,
  480. OUT PITSRV_DISK_PERFORMANCE_DATA *DiskPerfData,
  481. OUT ULONG *NumPhysicalDisks,
  482. OPTIONAL IN OUT PVOID *InputQueryBuffer,
  483. OPTIONAL IN OUT ULONG *InputQueryBufferSize
  484. );
  485. BOOLEAN
  486. ItSpIsPhysicalDrive (
  487. PDISK_PERFORMANCE DiskPerformanceData
  488. );
  489. DWORD
  490. ItSpGetDisplayPowerStatus(
  491. PBOOL ScreenSaverIsRunning
  492. );
  493. #endif // _IDLETSKS_H_