ReactOS  0.4.15-dev-3187-ge372f2b
devicepwrreqstatemachine.cpp
Go to the documentation of this file.
1 /*++
2 Copyright (c) Microsoft. All rights reserved.
3 
4 Module Name:
5 
6  DevicePwrReq.cpp
7 
8 Abstract:
9 
10  This module implements the device power requirement logic in the framework.
11 
12 --*/
13 
14 #include "pnppriv.hpp"
15 
16 extern "C" {
17 #if defined(EVENT_TRACING)
18 #include "DevicePwrReqStateMachine.tmh"
19 #endif
20 }
21 
24 {
26 };
27 
30 {
34 };
35 
38 {
42 };
43 
46 {
49 };
50 
53 {
55 };
56 
59 {
63 };
64 
67 {
68  // DprUnregistered
69  { NULL,
72  },
73 
74  // DprDevicePowerRequiredD0
75  { NULL,
78  },
79 
80  // DprDevicePowerNotRequiredD0
84  },
85 
86  // DprDevicePowerNotRequiredDx
87  { NULL,
90  },
91 
92  // DprDevicePowerRequiredDx
96  },
97 
98  // DprReportingDevicePowerAvailable
100  NULL,
101  0,
102  },
103 
104  // DprWaitingForDevicePowerRequiredD0
105  { NULL,
108  },
109 };
110 
112  __in FxPoxInterface * PoxInterface
114 {
115  //
116  // Make sure we can fit the state into a byte
117  //
118  C_ASSERT(DprMax <= 0xFF);
119 
121 
122  RtlZeroMemory(&m_Queue, sizeof(m_Queue));
123  RtlZeroMemory(&m_States, sizeof(m_States));
124 
125  //
126  // Store the initial state in the state history array
127  //
129  m_PoxInterface = PoxInterface;
130 }
131 
132 VOID
135  )
136 {
138  KIRQL irql;
139  LONGLONG timeout = 0;
140 
141  //
142  // Acquire state machine *queue* lock, raising to DISPATCH_LEVEL
143  //
144  Lock(&irql);
145 
146  if (IsFull()) {
147  //
148  // The queue is full. This should never happen.
149  //
150  Unlock(irql);
151 
152  ASSERTMSG("The device power requirement state machine queue is full\n",
153  FALSE);
154  return;
155  }
156 
157  if (IsClosedLocked()) {
158  //
159  // The queue is closed. This should never happen.
160  //
163  "WDFDEVICE 0x%p !devobj 0x%p current device power requirement state"
164  " %!FxDevicePwrRequirementStates! dropping event "
165  "%!FxDevicePwrRequirementEvents! because of a closed queue",
169  Event);
170 
171  Unlock(irql);
172 
173  ASSERTMSG(
174  "The device power requirement state machine queue is closed\n",
175  FALSE
176  );
177  return;
178  }
179 
180  //
181  // Enqueue the event
182  //
184 
185  //
186  // Drop the state machine *queue* lock
187  //
188  Unlock(irql);
189 
190  //
191  // Now, if we are running at PASSIVE_LEVEL, attempt to run the state machine
192  // on this thread. If we can't do that, then queue a work item.
193  //
194  if (irql == PASSIVE_LEVEL) {
195  //
196  // Try to acquire the state machine lock
197  //
198  status = m_StateMachineLock.AcquireLock(
200  &timeout
201  );
202  if (FxWaitLockInternal::IsLockAcquired(status)) {
204 
205  //
206  // We now hold the state machine lock. So call the function that
207  // dispatches the next state.
208  //
210 
211  //
212  // The pnp state machine should be the only one deleting the object
213  //
214  ASSERT(info.m_DeleteObject == FALSE);
215 
216  //
217  // Release the state machine lock
218  //
219  m_StateMachineLock.ReleaseLock(
221  );
222 
223  info.Evaluate(m_PkgPnp);
224 
225  return;
226  }
227  }
228 
229  //
230  // For one reason or another, we couldn't run the state machine on this
231  // thread. So queue a work item to do it.
232  //
233  QueueToThread();
234  return;
235 }
236 
237 VOID
239  __inout FxPkgPnp* PkgPnp,
241  __in PVOID WorkerContext
242  )
243 {
245 
246  UNREFERENCED_PARAMETER(WorkerContext);
247 
248  pThis = PkgPnp->m_PowerPolicyMachine.m_Owner->
250 
251  //
252  // Take the state machine lock.
253  //
254  pThis->m_StateMachineLock.AcquireLock(
256  );
257 
258  //
259  // Call the function that will actually run the state machine.
260  //
261  pThis->ProcessEventInner(Info);
262 
263  //
264  // We are being called from the work item and m_WorkItemRunning is > 0, so
265  // we cannot be deleted yet.
266  //
267  ASSERT(Info->SomethingToDo() == FALSE);
268 
269  //
270  // Now release the state machine lock
271  //
272  pThis->m_StateMachineLock.ReleaseLock(
274  );
275 
276  return;
277 }
278 
279 VOID
282  )
283 {
284  KIRQL irql;
288 
289  //
290  // Process as many events as we can
291  //
292  for ( ; ; ) {
293  //
294  // Acquire state machine *queue* lock
295  //
296  Lock(&irql);
297 
298  if (IsEmpty()) {
299  //
300  // The queue is empty.
301  //
303  Unlock(irql);
304  return;
305  }
306 
307  //
308  // Get the event from the queue
309  //
310  event = m_Queue[GetHead()];
311  IncrementHead();
312 
313  //
314  // Drop the state machine *queue* lock
315  //
316  Unlock(irql);
317 
318  //
319  // Get the state table entry for the current state
320  //
321  // NOTE: Prefast complains about buffer overflow if (m_CurrentState ==
322  // DprMax), but that should never happen because DprMax is not a real
323  // state. We just use it to represent the maximum value in the enum that
324  // defines the states.
325  //
328 
329  //
330  // Based on the event received, figure out the next state
331  //
332  newState = DprMax;
333  for (ULONG i = 0; i < entry->TargetStatesCount; i++) {
334  if (entry->TargetStates[i].DprEvent == event) {
335  DO_EVENT_TRAP(&entry->TargetStates[i]);
336  newState = entry->TargetStates[i].DprState;
337  break;
338  }
339  }
340 
341  if (newState == DprMax) {
342  //
343  // Unexpected event for this state
344  //
348  TRACINGPNP,
349  "WDFDEVICE 0x%p !devobj 0x%p device power requirement state "
350  "%!FxDevicePwrRequirementStates! dropping event "
351  "%!FxDevicePwrRequirementEvents!",
355  event
356  );
357 
358  COVERAGE_TRAP();
359  }
360 
361  while (newState != DprMax) {
366  "WDFDEVICE 0x%p !devobj 0x%p entering device power requirement "
367  "state %!FxDevicePwrRequirementStates! from "
368  "%!FxDevicePwrRequirementStates!",
371  newState,
373  );
374 
375  //
376  // Update the state history array
377  //
379 
380  //
381  // Move to the new state
382  //
383  m_CurrentState = (BYTE) newState;
385 
386  //
387  // Invoke the state entry function (if present) for the new state
388  //
389  if (entry->StateFunc != NULL) {
390  newState = entry->StateFunc(this);
391  }
392  else {
393  newState = DprMax;
394  }
395  }
396  }
397 
398  return;
399 }
400 
404  )
405 {
406  This->m_PoxInterface->PkgPnp()->PowerPolicyProcessEvent(
408  );
409  return DprMax;
410 }
411 
415  )
416 {
417  This->m_PoxInterface->PkgPnp()->PowerPolicyProcessEvent(
419  );
420  return DprMax;
421 }
422 
426  )
427 {
428  This->m_PoxInterface->PoxReportDevicePoweredOn();
430 }
#define TRAP_ON_EVENT
Definition: fxpkgpnp.hpp:60
UCHAR GetHead(VOID)
__inline CfxDevice * GetDevice(VOID)
Definition: fxpackage.hpp:46
FxDevicePwrRequirementEvents m_Queue[FxDevicePwrRequirementEventQueueDepth]
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
static FxDevicePwrRequirementStates ReportingDevicePowerAvailable(__in FxDevicePwrRequirementMachine *This)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
static const FxDevicePwrRequirementTargetState m_DevicePowerRequiredDxStates[]
#define __analysis_assume(expr)
Definition: ms_sal.h:2893
LONG NTSTATUS
Definition: precomp.h:26
KIRQL irql
Definition: wave.h:1
static const FxDevicePwrRequirementTargetState m_DevicePowerNotRequiredDxStates[]
Definition: dhcpd.h:245
static FxDevicePwrRequirementStates PowerRequiredDx(__in FxDevicePwrRequirementMachine *This)
UCHAR IncrementHistoryIndex(VOID)
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define TRACINGPNPPOWERSTATES
Definition: dbgtrace.h:69
GLbitfield GLuint64 timeout
Definition: glext.h:7164
FxDevicePwrRequirementMachine * m_DevicePowerRequirementMachine
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
UCHAR KIRQL
Definition: env_spec_w32.h:591
BOOLEAN IsFull(VOID)
VOID IncrementHead(VOID)
#define FALSE
Definition: types.h:117
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:467
#define DO_EVENT_TRAP(x)
Definition: fxpkgpnp.hpp:61
static const FxDevicePwrRequirementTargetState m_DevicePowerRequiredD0States[]
#define COVERAGE_TRAP()
Definition: fxmacros.hpp:246
FxDevicePwrRequirementMachineStateHistory m_States
#define C_ASSERT(e)
Definition: intsafe.h:73
VOID ProcessEventInner(__inout FxPostProcessInfo *Info)
FxPkgPnp * m_PkgPnp
static FxDevicePwrRequirementStates PowerNotRequiredD0(__in FxDevicePwrRequirementMachine *This)
static const FxDevicePwrRequirementTargetState m_UnregisteredStates[]
int64_t LONGLONG
Definition: typedefs.h:68
UCHAR InsertAtTail(VOID)
#define ASSERT(a)
Definition: mode.c:44
const UCHAR FxDevicePwrRequirementEventQueueDepth
FxPkgPnp * PkgPnp(VOID)
struct _test_info info[]
Definition: SetCursorPos.c:19
unsigned char UCHAR
Definition: xmlstorage.h:181
uint32_t entry
Definition: isohybrid.c:63
#define DEBUGGED_EVENT
Definition: fxpkgpnp.hpp:59
#define __inout
Definition: dbghelp.h:50
struct _cl_event * event
Definition: glext.h:7739
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
BOOLEAN IsClosedLocked(VOID)
unsigned char BYTE
Definition: xxhash.c:193
VOID GetFinishedState(__inout FxPostProcessInfo *Info)
#define TRACINGPNP
Definition: dbgtrace.h:67
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOLEAN IsEmpty(VOID)
static const FxDevicePwrRequirementTargetState m_DevicePowerNotRequiredD0States[]
#define ARRAY_SIZE(a)
Definition: main.h:24
static VOID _ProcessEventInner(__inout FxPkgPnp *PkgPnp, __inout FxPostProcessInfo *Info, __in PVOID WorkerContext)
static const FxDevicePwrRequirementStateTable m_StateTable[]
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
static const FxDevicePwrRequirementTargetState m_WaitingForDevicePowerRequiredD0States[]
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
FxPkgPnp * m_PkgPnp
VOID ProcessEvent(__in FxDevicePwrRequirementEvents Event)
FxDevicePwrRequirementMachine(__in FxPoxInterface *PoxInterface)
UCHAR History[FxDevicePwrRequirementEventQueueDepth]
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
FxWaitLockInternal m_StateMachineLock
Definition: ps.c:97