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.

320 lines
6.5 KiB

  1. /* Copyright 1999 American Power Conversion, All Rights Reserved
  2. *
  3. * Description:
  4. * Implements the native UPS sevice state machine. The various states executed
  5. * within the state machine are housed in separate files.
  6. *
  7. * Revision History:
  8. * dsmith 31Mar1999 Created
  9. *
  10. */
  11. #include <windows.h>
  12. #include "states.h"
  13. #include "events.h"
  14. #include "driver.h"
  15. #include "running_statmach.h"
  16. #include "upsreg.h"
  17. // Internal function Prototypes
  18. static void enter_state(DWORD aNewState, DWORD anEvent);
  19. static DWORD do_work(DWORD aCurrentState);
  20. static void exit_state(DWORD anOldState, DWORD anEvent);
  21. static DWORD change_state(DWORD aCurrentState, DWORD anEvent);
  22. static DWORD get_new_state(DWORD aCurrentState, DWORD anEvent);
  23. // State Machine Variables
  24. BOOL theIsStateMachineActive = TRUE;
  25. /**
  26. * RunStateMachine
  27. *
  28. * Description:
  29. * Starts the state machine. This method will not return until the state machine
  30. * exits.
  31. *
  32. * Parameters:
  33. * None
  34. *
  35. * Returns:
  36. * None
  37. */
  38. void RunStateMachine(){
  39. // Set the primary state to RUNNING
  40. DWORD new_state = RUNNING;
  41. DWORD current_state = new_state;
  42. DWORD event = NO_EVENT;
  43. enter_state(new_state, event);
  44. // Continue processing state changes until the state becomes the EXIT_NOW state
  45. while (new_state != EXIT_NOW){
  46. current_state = new_state;
  47. event = do_work(current_state);
  48. new_state = change_state(new_state, event);
  49. }
  50. }
  51. /**
  52. * StopStateMachine
  53. *
  54. * Description:
  55. * Stops the UPS service state machine if the service is not in the
  56. * middle of a shutdown sequence.
  57. *
  58. * Parameters:
  59. * None
  60. *
  61. * Returns:
  62. * None
  63. */
  64. void StopStateMachine(){
  65. theIsStateMachineActive = FALSE;
  66. // Wake up the main service thread
  67. UPSCancelWait();
  68. }
  69. /**
  70. * IsStateMachineActive
  71. *
  72. * Description:
  73. * Returns the running status of the state machine. If the state machine
  74. * has been commanded to exit, then the status will be FALSE, otherwise,
  75. * this method will return true.
  76. *
  77. * Parameters:
  78. * None
  79. *
  80. * Returns:
  81. * TRUE if the state machine is active
  82. * FALSE if the state machine is not active
  83. */
  84. BOOL IsStateMachineActive(){
  85. return theIsStateMachineActive;
  86. }
  87. /**
  88. * change_state
  89. *
  90. * Description:
  91. * Determines what the new state should be based upon the input parameters.
  92. * The current state is exited and the new state is initialized.
  93. *
  94. * Parameters:
  95. * anEvent The event that is causing the state transition.
  96. * aCurrentState The state before the transition.
  97. *
  98. * Returns:
  99. * The new state.
  100. */
  101. DWORD change_state(DWORD aCurrentState, DWORD anEvent){
  102. DWORD new_state;
  103. new_state = get_new_state(aCurrentState, anEvent);
  104. if (new_state != aCurrentState){
  105. exit_state(aCurrentState, anEvent);
  106. enter_state(new_state, anEvent);
  107. }
  108. return new_state;
  109. }
  110. /**
  111. * get_new_state
  112. *
  113. * Description:
  114. * Determines what the new state should be based upon the input parameters
  115. * and registry entries.
  116. *
  117. * Parameters:
  118. * anEvent The event that is causing the state transition.
  119. * aCurrentState The state before the transition.
  120. *
  121. * Returns:
  122. * The new state.
  123. */
  124. static DWORD get_new_state(DWORD aCurrentState, DWORD anEvent){
  125. DWORD new_state;
  126. switch (anEvent){
  127. case INITIALIZATION_COMPLETE:
  128. new_state = RUNNING;
  129. break;
  130. case LOST_COMM:
  131. case LOW_BATTERY:
  132. case ON_BATTERY_TIMER_EXPIRED:
  133. {
  134. DWORD shutdown_behavior = UPS_SHUTDOWN_SHUTDOWN;
  135. // Check the registry to determine if we shutdown or hibernate
  136. InitUPSConfigBlock();
  137. if ((GetUPSConfigCriticalPowerAction(&shutdown_behavior) == ERROR_SUCCESS)
  138. && (shutdown_behavior == UPS_SHUTDOWN_HIBERNATE)) {
  139. // Hibernate was selected as the CriticalPowerAction
  140. new_state = HIBERNATE;
  141. }
  142. else {
  143. // Shutdown was selected as the CriticalPowerAction
  144. new_state = WAITING_TO_SHUTDOWN;
  145. }
  146. // Free the UPS registry config block
  147. FreeUPSConfigBlock();
  148. }
  149. break;
  150. case SHUTDOWN_ACTIONS_COMPLETED:
  151. new_state = SHUTTING_DOWN;
  152. break;
  153. case SHUTDOWN_COMPLETE:
  154. new_state = STOPPING;
  155. break;
  156. case STOPPED:
  157. new_state = EXIT_NOW;
  158. break;
  159. case RETURN_FROM_HIBERNATION:
  160. new_state = INITIALIZING;
  161. break;
  162. case HIBERNATION_ERROR:
  163. new_state = SHUTTING_DOWN;
  164. break;
  165. default:
  166. new_state = aCurrentState;
  167. }
  168. // If the state machine has been commanded to exit, then return the
  169. // stopping state
  170. if (IsStateMachineActive() == FALSE){
  171. // Ignore this condition if the transition is into the shutting down state
  172. // Shutdowns in progress cannot be interrupted.
  173. if (new_state != SHUTTING_DOWN && new_state != EXIT_NOW){
  174. new_state = STOPPING;
  175. }
  176. }
  177. return new_state;
  178. }
  179. /**
  180. * enter_state
  181. *
  182. * Description:
  183. * Initializes the new state.
  184. *
  185. * Parameters:
  186. * anEvent The event that is causing the transition to a new state.
  187. * aNewState The state to enter.
  188. *
  189. * Returns:
  190. * None
  191. */
  192. static void enter_state(DWORD aNewState, DWORD anEvent){
  193. switch (aNewState){
  194. case INITIALIZING:
  195. Initializing_Enter(anEvent);
  196. break;
  197. case RUNNING:
  198. Running_Enter(anEvent);
  199. break;
  200. case WAITING_TO_SHUTDOWN:
  201. WaitingToShutdown_Enter(anEvent);
  202. break;
  203. case SHUTTING_DOWN:
  204. ShuttingDown_Enter(anEvent);
  205. break;
  206. case HIBERNATE:
  207. Hibernate_Enter(anEvent);
  208. break;
  209. case STOPPING:
  210. Stopping_Enter(anEvent);
  211. break;
  212. default:
  213. break;
  214. }
  215. }
  216. /**
  217. * do_work
  218. *
  219. * Description:
  220. * Transfers control to a state.
  221. *
  222. * Parameters:
  223. * aCurrentState The state to perform the work in.
  224. *
  225. * Returns:
  226. * The event that caused the transition from one of the states
  227. */
  228. static DWORD do_work(DWORD aCurrentState){
  229. DWORD event = NO_EVENT;
  230. switch (aCurrentState){
  231. case INITIALIZING:
  232. event = Initializing_DoWork();
  233. break;
  234. case RUNNING:
  235. event = Running_DoWork();
  236. break;
  237. case WAITING_TO_SHUTDOWN:
  238. event = WaitingToShutdown_DoWork();
  239. break;
  240. case SHUTTING_DOWN:
  241. event = ShuttingDown_DoWork();
  242. break;
  243. case HIBERNATE:
  244. event = Hibernate_DoWork();
  245. break;
  246. case STOPPING:
  247. event = Stopping_DoWork();
  248. break;
  249. default:
  250. break;
  251. }
  252. return event;
  253. }
  254. /**
  255. * exit_state
  256. *
  257. * Description:
  258. * Exits the currently executing state.
  259. *
  260. * Parameters:
  261. * anEvent The event that is causing the transition from the state.
  262. * anOldState The current state.
  263. *
  264. * Returns:
  265. * None
  266. */
  267. static void exit_state(DWORD anOldState, DWORD anEvent){
  268. switch (anOldState){
  269. case INITIALIZING:
  270. Initializing_Exit(anEvent);
  271. break;
  272. case RUNNING:
  273. Running_Exit(anEvent);
  274. break;
  275. case WAITING_TO_SHUTDOWN:
  276. WaitingToShutdown_Exit(anEvent);
  277. break;
  278. case SHUTTING_DOWN:
  279. ShuttingDown_Exit(anEvent);
  280. break;
  281. case HIBERNATE:
  282. Hibernate_Exit(anEvent);
  283. break;
  284. case STOPPING:
  285. Stopping_Exit(anEvent);
  286. break;
  287. default:
  288. break;
  289. }
  290. }