Source code of Windows XP (NT5)
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.

728 lines
17 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. //
  44. // We check to see if the idle task we asked to run is really running
  45. // (i.e. it is using the disk and CPU) every this many ms. This is our
  46. // mechanism for cleaning up after unregistered/orphaned tasks. This
  47. // should be greater than IT_USER_INPUT_POLL_PERIOD_WHEN_IDLE.
  48. //
  49. #define IT_DEFAULT_IDLE_TASK_RUNNING_CHECK_PERIOD (5 * 60 * 1000) // 5 min.
  50. //
  51. // If the CPU is not idle more than this percent over a time interval,
  52. // the system is not considered idle.
  53. //
  54. #define IT_DEFAULT_MIN_CPU_IDLE_PERCENTAGE 90
  55. //
  56. // If a disk is not idle more than this percent over a time interval,
  57. // the system is not considered idle.
  58. //
  59. #define IT_DEFAULT_MIN_DISK_IDLE_PERCENTAGE 90
  60. //
  61. // We will not try to run our tasks if there is only this many seconds
  62. // left before the system will enter hibernate or standby automatically.
  63. // Note that the time remaining is updated every so many seconds (e.g.
  64. // 15) so this number should not be very small.
  65. //
  66. #define IT_DEFAULT_MAX_TIME_REMAINING_TO_SLEEP 60
  67. //
  68. // This is the maximum number of registered idle tasks. This is a
  69. // sanity check. It also protects against evil callers.
  70. //
  71. #define IT_DEFAULT_MAX_REGISTERED_TASKS 512
  72. //
  73. // We set timer period for idle detection callback to this while the
  74. // callback is running to prevent new callbacks from firing. We end up
  75. // having to do this because you cannot requeue/change a timer for
  76. // which you don't specify a period. If a callback fires while another
  77. // one is already running, it simply returns without doing anything.
  78. //
  79. #define IT_VERYLONG_TIMER_PERIOD 0x7FFFFFFF
  80. //
  81. // This is the number of recent server statuses that we keep track
  82. // of. Do not make this number smaller without revisiting the logic &
  83. // code that uses the LastStatus history.
  84. //
  85. #define ITSRV_GLOBAL_STATUS_HISTORY_SIZE 8
  86. //
  87. // Hints for the number of outstanding RPC call-ins we will have.
  88. //
  89. #define ITSRV_RPC_MIN_CALLS 1
  90. #define ITSRV_RPC_MAX_CALLS 1
  91. //
  92. // Define useful macros.
  93. //
  94. #define IT_ALLOC(NumBytes) (HeapAlloc(GetProcessHeap(),0,(NumBytes)))
  95. #define IT_REALLOC(Buffer,NumBytes) (HeapReAlloc(GetProcessHeap(),0,(Buffer),(NumBytes)))
  96. #define IT_FREE(Buffer) (HeapFree(GetProcessHeap(),0,(Buffer)))
  97. //
  98. // These macros are used to acquire/release a mutex.
  99. //
  100. #define IT_ACQUIRE_LOCK(Lock) \
  101. WaitForSingleObject((Lock), INFINITE); \
  102. #define IT_RELEASE_LOCK(Lock) \
  103. ReleaseMutex((Lock)); \
  104. //
  105. // This macro is used in the idle detection callback (while holding
  106. // the global lock of the input global context) to determine if the
  107. // idle detection callback should just exit/go away.
  108. //
  109. #define ITSP_SHOULD_STOP_IDLE_DETECTION(GlobalContext) \
  110. ((GlobalContext->Status == ItSrvStatusStoppingIdleDetection) || \
  111. (GlobalContext->Status == ItSrvStatusUninitializing)) \
  112. //
  113. // Status of a server global context. It also acts as a magic to
  114. // identify/verify the global context, as it starts from Df00. There
  115. // is not a full-blown state machine, although the state is used as a
  116. // critical hint for making decisions when registering an idle
  117. // task. This is more for informative and verification purposes. If
  118. // you add a new status without updating everything that needs to be
  119. // updated, you may hit several asserts, especially in the idle
  120. // detection callback. Frankly, don't add a new state without a very
  121. // good reason.
  122. //
  123. typedef enum _ITSRV_GLOBAL_CONTEXT_STATUS {
  124. ItSrvStatusMinStatus = 'Df00',
  125. ItSrvStatusInitializing,
  126. ItSrvStatusWaitingForIdleTasks,
  127. ItSrvStatusDetectingIdle,
  128. ItSrvStatusRunningIdleTasks,
  129. ItSrvStatusStoppingIdleDetection,
  130. ItSrvStatusUninitializing,
  131. ItSrvStatusUninitialized,
  132. ItSrvStatusMaxStatus
  133. } ITSRV_GLOBAL_CONTEXT_STATUS, *PITSRV_GLOBAL_CONTEXT_STATUS;
  134. //
  135. // These are the various types of idle detection overrides. Multiple
  136. // overrides can be specified by OR'ing them (i.e. these are bits!)
  137. //
  138. // If you are adding an override here, check whether you need to specify
  139. // it when force-processing all idle tasks.
  140. //
  141. typedef enum _ITSRV_IDLE_DETECTION_OVERRIDE {
  142. ItSrvOverrideIdleDetection = 0x00000001,
  143. ItSrvOverrideIdleVerification = 0x00000002,
  144. ItSrvOverrideUserInputCheckToStopTask = 0x00000004,
  145. ItSrvOverrideTaskRunningCheck = 0x00000008,
  146. ItSrvOverridePostTaskIdleCheck = 0x00000010,
  147. ItSrvOverrideLongRequeueTime = 0x00000020,
  148. ItSrvOverrideBatteryCheckToStopTask = 0x00000040,
  149. ItSrvOverrideAutoPowerCheckToStopTask = 0x00000080,
  150. } ITSRV_IDLE_DETECTION_OVERRIDE, *PITSRV_IDLE_DETECTION_OVERRIDE;
  151. //
  152. // These are the various reasons why ItSpIsSystemIdle function may be
  153. // called.
  154. //
  155. typedef enum _ITSRV_IDLE_CHECK_REASON {
  156. ItSrvInitialIdleCheck,
  157. ItSrvIdleVerificationCheck,
  158. ItSrvIdleTaskRunningCheck,
  159. ItSrvMaxIdleCheckReason
  160. }ITSRV_IDLE_CHECK_REASON, *PITSRV_IDLE_CHECK_REASON;
  161. //
  162. // This structure is used to keep context for a registered task for
  163. // the server.
  164. //
  165. typedef struct _ITSRV_IDLE_TASK_CONTEXT {
  166. //
  167. // Link in the list of idle tasks.
  168. //
  169. LIST_ENTRY IdleTaskLink;
  170. //
  171. // Status of the idle task.
  172. //
  173. IT_IDLE_TASK_STATUS Status;
  174. //
  175. // Idle task properties the client specified.
  176. //
  177. IT_IDLE_TASK_PROPERTIES Properties;
  178. //
  179. // Event to be notified when the task should start running
  180. // (e.g. the system is idle).
  181. //
  182. HANDLE StartEvent;
  183. //
  184. // Event to be notified when the task should stop running.
  185. //
  186. HANDLE StopEvent;
  187. } ITSRV_IDLE_TASK_CONTEXT, *PITSRV_IDLE_TASK_CONTEXT;
  188. //
  189. // This structure contains disk performance information we are
  190. // interested in.
  191. //
  192. typedef struct _ITSRV_DISK_PERFORMANCE_DATA {
  193. //
  194. // How long the disk was idle in ms.
  195. //
  196. ULONG DiskIdleTime;
  197. } ITSRV_DISK_PERFORMANCE_DATA, *PITSRV_DISK_PERFORMANCE_DATA;
  198. //
  199. // Define structure to contain system resource information & state at
  200. // a specific time.
  201. //
  202. typedef struct _ITSRV_SYSTEM_SNAPSHOT {
  203. //
  204. // When this snapshot was taken, in ms elapsed since system was
  205. // started (i.e. GetTickCount)
  206. //
  207. DWORD SnapshotTime;
  208. //
  209. // Whether we were able to get the specified data in this snapshot.
  210. //
  211. ULONG GotLastInputInfo:1;
  212. ULONG GotSystemPerformanceInfo:1;
  213. ULONG GotDiskPerformanceInfo:1;
  214. ULONG GotSystemPowerStatus:1;
  215. ULONG GotSystemPowerInfo:1;
  216. ULONG GotSystemExecutionState:1;
  217. ULONG GotDisplayPowerStatus:1;
  218. //
  219. // This is when the last user input happened before the snapshot
  220. // was taken.
  221. //
  222. LASTINPUTINFO LastInputInfo;
  223. //
  224. // System performance information when the snapshot was taken.
  225. //
  226. SYSTEM_PERFORMANCE_INFORMATION SystemPerformanceInfo;
  227. //
  228. // Disk performance data on registered harddisks when the snapshot
  229. // was taken.
  230. //
  231. ULONG NumPhysicalDisks;
  232. ITSRV_DISK_PERFORMANCE_DATA *DiskPerfData;
  233. //
  234. // System power status (e.g. are we running on battery etc.)
  235. //
  236. SYSTEM_POWER_STATUS SystemPowerStatus;
  237. //
  238. // System power information (e.g. how long till system turns itself
  239. // off & goes to sleep.)
  240. //
  241. SYSTEM_POWER_INFORMATION PowerInfo;
  242. //
  243. // System execution state (e.g. is somebody running a presentation?)
  244. //
  245. EXECUTION_STATE ExecutionState;
  246. //
  247. // Whether the screen saver is running.
  248. //
  249. BOOL ScreenSaverIsRunning;
  250. } ITSRV_SYSTEM_SNAPSHOT, *PITSRV_SYSTEM_SNAPSHOT;
  251. //
  252. // Type for the routine that is called to notify that forced processing of
  253. // idle tasks have been requested.
  254. //
  255. typedef VOID (*PIT_PROCESS_IDLE_TASKS_NOTIFY_ROUTINE)(VOID);
  256. //
  257. // Define structure to contain server global context for idle
  258. // detection and keeping track of registered idle tasks.
  259. //
  260. typedef struct _ITSRV_GLOBAL_CONTEXT {
  261. //
  262. // Status of the server and its history, LastStatus[0] being the
  263. // most recent. The status version is incremented each time the
  264. // status is updated.
  265. //
  266. ITSRV_GLOBAL_CONTEXT_STATUS Status;
  267. ITSRV_GLOBAL_CONTEXT_STATUS LastStatus[ITSRV_GLOBAL_STATUS_HISTORY_SIZE];
  268. LONG StatusVersion;
  269. //
  270. // Nearly all operations involve the idle tasks list and instead
  271. // of having a lock for the list and seperate synchronization
  272. // mechanisms for other operations on the structure, we have a
  273. // single global lock to make life simpler.
  274. //
  275. HANDLE GlobalLock;
  276. //
  277. // This is the list and number of idle tasks that have been
  278. // scheduled.
  279. //
  280. LIST_ENTRY IdleTasksList;
  281. ULONG NumIdleTasks;
  282. //
  283. // Handle to the timer queue timer that is used to periodically
  284. // check for system idleness.
  285. //
  286. HANDLE IdleDetectionTimerHandle;
  287. //
  288. // This manual reset event gets signaled when idle detection
  289. // should stop (e.g. because there are no more idle tasks, the
  290. // server is shutting down etc.) It signals a running idle
  291. // detection callback to quickly exit.
  292. //
  293. HANDLE StopIdleDetection;
  294. //
  295. // This manual reset event gets signaled when idle detection has
  296. // fully stopped (i.e. no callback is running, the timer is not in
  297. // the queue etc.
  298. //
  299. HANDLE IdleDetectionStopped;
  300. //
  301. // This manual reset event is signaled when an idle task that was
  302. // running is unregistered/removed. This would happen usually
  303. // after an idle task that was told to run completes and has no
  304. // more to do. It unregisters itself, and this event is set to
  305. // notify the idle detection callback to move on to other idle
  306. // tasks.
  307. //
  308. HANDLE RemovedRunningIdleTask;
  309. //
  310. // This manual-reset event is reset while ItSrvServiceHandler is
  311. // running. It is signaled when the function is done. It is used
  312. // to synchronize shutdown with ItSrvServiceHandler call ins.
  313. //
  314. HANDLE ServiceHandlerNotRunning;
  315. //
  316. // If it is set, this routine is called to notify that
  317. // forced processing of idle tasks have been requested.
  318. //
  319. PIT_PROCESS_IDLE_TASKS_NOTIFY_ROUTINE ProcessIdleTasksNotifyRoutine;
  320. //
  321. // These are the parameters that control idle detection.
  322. //
  323. IT_IDLE_DETECTION_PARAMETERS Parameters;
  324. //
  325. // This is the WMI handle used in disk performance queries.
  326. //
  327. WMIHANDLE DiskPerfWmiHandle;
  328. //
  329. // Number of processors on the system. Used to calculate CPU
  330. // utilization.
  331. //
  332. UCHAR NumProcessors;
  333. //
  334. // This buffer is used to make Wmi queries. It is maintained here
  335. // so we don't have to allocate a new one each time.
  336. //
  337. PVOID WmiQueryBuffer;
  338. ULONG WmiQueryBufferSize;
  339. //
  340. // The last system resource / activity snapshot we took.
  341. //
  342. ITSRV_SYSTEM_SNAPSHOT LastSystemSnapshot;
  343. //
  344. // Is an idle detection callback already running? This is used to
  345. // protect us from idle detection callbacks being fired while
  346. // there is already one active.
  347. //
  348. BOOLEAN IsIdleDetectionCallbackRunning;
  349. //
  350. // Various phases of idle detection can be overriden by setting
  351. // this.
  352. //
  353. ITSRV_IDLE_DETECTION_OVERRIDE IdleDetectionOverride;
  354. //
  355. // RPC binding vector used to register ourselves in the local
  356. // endpoint-map database.
  357. //
  358. RPC_BINDING_VECTOR *RpcBindingVector;
  359. //
  360. // Whether we actually registered our endpoint and interface.
  361. //
  362. BOOLEAN RegisteredRPCEndpoint;
  363. BOOLEAN RegisteredRPCInterface;
  364. } ITSRV_GLOBAL_CONTEXT, *PITSRV_GLOBAL_CONTEXT;
  365. //
  366. // Reference count structure.
  367. //
  368. typedef struct _ITSRV_REFCOUNT {
  369. //
  370. // This is set when somebody wants to gain exclusive access to the
  371. // protected structure.
  372. //
  373. LONG Exclusive;
  374. //
  375. // When initialized or reset, this reference count starts from
  376. // 1. When exclusive access is granted it stays at 0: even if it
  377. // may get bumped by an AddRef by mistake, it will return to 0.
  378. //
  379. LONG RefCount;
  380. //
  381. // The thread that got exclusive access.
  382. //
  383. HANDLE ExclusiveOwner;
  384. } ITSRV_REFCOUNT, *PITSRV_REFCOUNT;
  385. //
  386. // Server function declarations. They should be only used by the
  387. // server host and the client functions.
  388. //
  389. DWORD
  390. ItSrvInitialize (
  391. VOID
  392. );
  393. VOID
  394. ItSrvUninitialize (
  395. VOID
  396. );
  397. BOOLEAN
  398. ItSrvServiceHandler(
  399. IN DWORD ControlCode,
  400. IN DWORD EventType,
  401. IN LPVOID EventData,
  402. IN LPVOID Context,
  403. OUT PDWORD ErrorCode
  404. );
  405. DWORD
  406. ItSrvRegisterIdleTask (
  407. ITRPC_HANDLE Reserved,
  408. IT_HANDLE *ItHandle,
  409. PIT_IDLE_TASK_PROPERTIES IdleTaskProperties
  410. );
  411. VOID
  412. ItSrvUnregisterIdleTask (
  413. ITRPC_HANDLE Reserved,
  414. IT_HANDLE *ItHandle
  415. );
  416. DWORD
  417. ItSrvSetDetectionParameters (
  418. ITRPC_HANDLE Reserved,
  419. PIT_IDLE_DETECTION_PARAMETERS Parameters
  420. );
  421. DWORD
  422. ItSrvProcessIdleTasks (
  423. ITRPC_HANDLE Reserved
  424. );
  425. VOID
  426. __RPC_USER
  427. IT_HANDLE_rundown (
  428. IT_HANDLE ItHandle
  429. );
  430. //
  431. // Local support function prototypes for the server.
  432. //
  433. RPC_STATUS
  434. __stdcall
  435. ItSpRpcSecurityCallback (
  436. IN PVOID Interface,
  437. IN PVOID Context
  438. );
  439. VOID
  440. ItSpUnregisterIdleTask (
  441. ITRPC_HANDLE Reserved,
  442. IT_HANDLE *ItHandle,
  443. BOOLEAN CalledInternally
  444. );
  445. VOID
  446. ItSpUpdateStatus (
  447. PITSRV_GLOBAL_CONTEXT GlobalContext,
  448. ITSRV_GLOBAL_CONTEXT_STATUS NewStatus
  449. );
  450. VOID
  451. ItSpCleanupGlobalContext (
  452. PITSRV_GLOBAL_CONTEXT GlobalContext
  453. );
  454. VOID
  455. ItSpCleanupIdleTask (
  456. PITSRV_IDLE_TASK_CONTEXT IdleTask
  457. );
  458. ULONG
  459. ItpVerifyIdleTaskProperties (
  460. PIT_IDLE_TASK_PROPERTIES IdleTaskProperties
  461. );
  462. DWORD
  463. ItSpStartIdleDetection (
  464. PITSRV_GLOBAL_CONTEXT GlobalContext
  465. );
  466. VOID
  467. ItSpStopIdleDetection (
  468. PITSRV_GLOBAL_CONTEXT GlobalContext
  469. );
  470. VOID
  471. CALLBACK
  472. ItSpIdleDetectionCallbackRoutine (
  473. PVOID Parameter,
  474. BOOLEAN TimerOrWaitFired
  475. );
  476. PITSRV_IDLE_TASK_CONTEXT
  477. ItSpFindRunningIdleTask (
  478. PITSRV_GLOBAL_CONTEXT GlobalContext
  479. );
  480. PITSRV_IDLE_TASK_CONTEXT
  481. ItSpFindIdleTask (
  482. PITSRV_GLOBAL_CONTEXT GlobalContext,
  483. IT_HANDLE ItHandle
  484. );
  485. VOID
  486. ItSpInitializeSystemSnapshot (
  487. PITSRV_SYSTEM_SNAPSHOT SystemSnapshot
  488. );
  489. VOID
  490. ItSpCleanupSystemSnapshot (
  491. PITSRV_SYSTEM_SNAPSHOT SystemSnapshot
  492. );
  493. DWORD
  494. ItSpCopySystemSnapshot (
  495. PITSRV_SYSTEM_SNAPSHOT DestSnapshot,
  496. PITSRV_SYSTEM_SNAPSHOT SourceSnapshot
  497. );
  498. DWORD
  499. ItSpGetSystemSnapshot (
  500. PITSRV_GLOBAL_CONTEXT GlobalContext,
  501. PITSRV_SYSTEM_SNAPSHOT SystemSnapshot
  502. );
  503. BOOLEAN
  504. ItSpIsSystemIdle (
  505. PITSRV_GLOBAL_CONTEXT GlobalContext,
  506. PITSRV_SYSTEM_SNAPSHOT CurrentSnapshot,
  507. PITSRV_SYSTEM_SNAPSHOT LastSnapshot,
  508. ITSRV_IDLE_CHECK_REASON IdleCheckReason
  509. );
  510. DWORD
  511. ItSpGetLastInputInfo (
  512. PLASTINPUTINFO LastInputInfo
  513. );
  514. DWORD
  515. ItSpGetWmiDiskPerformanceData(
  516. IN WMIHANDLE DiskPerfWmiHandle,
  517. OUT PITSRV_DISK_PERFORMANCE_DATA *DiskPerfData,
  518. OUT ULONG *NumPhysicalDisks,
  519. OPTIONAL IN OUT PVOID *InputQueryBuffer,
  520. OPTIONAL IN OUT ULONG *InputQueryBufferSize
  521. );
  522. BOOLEAN
  523. ItSpIsPhysicalDrive (
  524. PDISK_PERFORMANCE DiskPerformanceData
  525. );
  526. DWORD
  527. ItSpGetDisplayPowerStatus(
  528. PBOOL ScreenSaverIsRunning
  529. );
  530. //
  531. // Reference count functions.
  532. //
  533. VOID
  534. ItSpInitializeRefCount(
  535. PITSRV_REFCOUNT RefCount
  536. );
  537. DWORD
  538. FASTCALL
  539. ItSpAddRef(
  540. PITSRV_REFCOUNT RefCount
  541. );
  542. VOID
  543. FASTCALL
  544. ItSpDecRef(
  545. PITSRV_REFCOUNT RefCount
  546. );
  547. DWORD
  548. ItSpAcquireExclusiveRef(
  549. PITSRV_REFCOUNT RefCount
  550. );
  551. #endif // _IDLETSKS_H_