ReactOS 0.4.17-dev-1037-g720d112
smengine.h
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS USB 3 stack
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Hierarchical state machine engine shared by the USB 3 drivers
5 * COPYRIGHT: Copyright 2026 Justin Miller <justinmiller100@gmail.com>
6 */
7
8#pragma once
9
10#define SM_QUEUE_DEPTH 32
11#define SM_MAX_DEPTH 8
12#define SM_TRACE_DEPTH 32
13#define SM_TRACE_MASK (SM_TRACE_DEPTH - 1)
14#define SM_NO_EVENT 0xFFFF
15#define SM_FRAME_INNERMOST 0xFF
16
17#ifndef SM_BREAK
18#define SM_BREAK(Message) NT_ASSERTMSG(Message, FALSE)
19#endif
20
22typedef enum _SM_EVENT_CLASS
23{
29
30typedef struct _SM_EVENT_INFO
31{
37
38/* State flags, inherited by child states */
39#define SM_STATE_TAKES_REQUESTS 0x00000001
40#define SM_STATE_NEEDS_PASSIVE 0x00000002
41#define SM_STATE_CRITICAL_ONLY 0x00000004
42#define SM_STATE_YIELDS_TO_CALLER 0x00000008
43#define SM_STATE_STOP_TIMER_ON_EXIT 0x00000010
44
45typedef enum _SM_RESULT_KIND
46{
54
55typedef struct _SM_RESULT
56{
60 const VOID* Target;
62
63typedef enum _SM_TRACE_KIND
64{
78
79typedef struct _SM_TRACE
80{
86
91template <typename Machine, typename Event>
92struct SmState
93{
98 SM_RESULT (Machine::*Entry)();
100};
101
112template <typename Machine, typename Event>
114{
115public:
117
118 VOID
120 _In_ const State* Initial);
121
122 BOOLEAN
123 SmPost(
124 _In_ Event Ev);
125
126 VOID
128
129 const State*
130 SmCurrent() const
131 {
132 return m_Frames[m_Depth];
133 }
134
135 ULONG
136 SmDepth() const
137 {
138 return m_Depth;
139 }
140
141 const State*
143 _In_ ULONG Index) const
144 {
145 return m_Frames[Index];
146 }
147
148 BOOLEAN
149 SmIsIn(
150 _In_ const State* Ancestor) const;
151
152 BOOLEAN
154 {
155 return m_Paused;
156 }
157
158 BOOLEAN
160 {
161 return m_WaitingForTimer;
162 }
163
164 ULONG
166 {
167 return m_UnexpectedCount;
168 }
169
170protected:
171 static SM_RESULT
173 _In_ SM_RESULT_KIND Kind,
174 _In_ USHORT Ev,
175 _In_opt_ const VOID* Target)
176 {
177 SM_RESULT result = { static_cast<UCHAR>(Kind), SM_FRAME_INNERMOST, Ev, Target };
178 return result;
179 }
180
181 static SM_RESULT
183 {
185 }
186
187 static SM_RESULT
189 {
191 }
192
193 static SM_RESULT
195 _In_ const State* Target)
196 {
198 }
199
200 /* Return this right after the call that lets the resume event be posted */
201 static SM_RESULT
203 {
205 }
206
207 /* Enter Start in a new frame on top of the current state */
208 static SM_RESULT
210 _In_ const State* Start)
211 {
213 }
214
215 /* Leave the innermost frame and hand Ev to the state that called it */
216 static SM_RESULT
218 _In_ Event Ev)
219 {
220 return SmMakeResult(SmResultReturn, static_cast<USHORT>(Ev), NULL);
221 }
222
223 VOID
224 SmBeginPause();
225
226 /* For transient code that stands in for a state with a discard list */
227 VOID
229 _In_ Event Ev);
230
231 /* Default hooks, hidden by the machine when it needs them */
234
235 BOOLEAN
237 _In_ Event Ev)
238 {
240 return TRUE;
241 }
242
243 VOID
245 {
246 }
247
248 VOID
250 {
251 }
252
253 VOID
255 {
256 SM_BREAK("State needs passive level but the machine has no work item");
257 }
258
259 VOID
261 _In_ Event Ev)
262 {
264 }
265
266 VOID
268 {
269 }
270
271 /* FALSE when the timer already fired or is about to */
272 BOOLEAN
274 {
275 return TRUE;
276 }
277
278private:
279 Machine*
281 {
282 return static_cast<Machine*>(this);
283 }
284
285 static BOOLEAN
286 HasFlag(
287 _In_ const State* Target,
288 _In_ ULONG Flag);
289
290 static BOOLEAN
291 Discards(
292 _In_ const State* Target,
293 _In_ Event Ev);
294
295 const State*
296 EffectiveState() const;
297
298 BOOLEAN
299 IsQueued(
300 _In_ Event Ev) const;
301
302 BOOLEAN
304 _In_ Event Ev);
305
306 BOOLEAN
307 Dequeue(
308 _Out_ Event* Ev);
309
310 VOID
311 Purge(
312 _In_ const State* Entered,
314
315 VOID
316 Trace(
317 _In_ SM_TRACE_KIND Kind,
318 _In_ USHORT Ev);
319
321 Dispatch(
322 _In_ Event Ev);
323
324 BOOLEAN
325 Run(
327 _In_ USHORT LastEvent,
329 _In_opt_ const State* Entered);
330
334 UCHAR m_Depth; /* Index of the innermost frame in m_Frames */
335 UCHAR m_Count; /* Number of events in m_Queue */
343};
344
345/* IMPLEMENTATION *************************************************************/
346
347template <typename Machine, typename Event>
348VOID
350 _In_ const State* Initial)
351{
352 NT_ASSERT(Initial->Entry == NULL);
353
354 KeInitializeSpinLock(&m_Lock);
355 m_Frames[0] = Initial;
356 m_Depth = 0;
357 m_Count = 0;
358 m_Running = FALSE;
359 m_Paused = FALSE;
360 m_WaitingForPassive = FALSE;
361 m_WaitingForTimer = FALSE;
362 m_TraceIndex = 0;
363 m_UnexpectedCount = 0;
364 RtlZeroMemory(m_Trace, sizeof(m_Trace));
366}
367
368template <typename Machine, typename Event>
371 _In_ Event Ev)
372{
373 const SM_EVENT_INFO* info = &Machine::EventInfo[static_cast<ULONG>(Ev)];
374 const State* current;
376 KIRQL irql;
377
378 KeAcquireSpinLock(&m_Lock, &irql);
379
380 if (!Self()->SmAccepts(Ev) || (info->Coalesce && IsQueued(Ev)))
381 {
382 Trace(SmTraceRejected, static_cast<USHORT>(Ev));
383 KeReleaseSpinLock(&m_Lock, irql);
384 return FALSE;
385 }
386
387 Trace(SmTracePosted, static_cast<USHORT>(Ev));
388
389 if (info->Replace && RemoveQueued(Ev))
390 {
391 KeReleaseSpinLock(&m_Lock, irql);
392 Self()->SmOnDequeue(Ev);
393 KeAcquireSpinLock(&m_Lock, &irql);
394 }
395
396 if (info->Class == SmEventResume)
397 {
398 if (!m_Paused || !m_Running)
399 {
400 m_UnexpectedCount++;
401 Trace(SmTraceUnhandled, static_cast<USHORT>(Ev));
402 KeReleaseSpinLock(&m_Lock, irql);
403 SM_BREAK("Resume event posted to a machine that is not paused");
404 return TRUE;
405 }
406
407 /* The paused drainer already left, this thread takes over */
408 m_Paused = FALSE;
409 Trace(SmTraceResumed, static_cast<USHORT>(Ev));
410 KeReleaseSpinLock(&m_Lock, irql);
411
412 Self()->SmReference();
413 result = Dispatch(Ev);
414 if (!Run(irql, static_cast<USHORT>(Ev), result, NULL))
415 Self()->SmDereference();
416 return TRUE;
417 }
418
419 if (m_WaitingForTimer)
420 {
421 /* The drainer stopped after entering a state, the entry runs once the timer is done */
422 if (static_cast<USHORT>(Ev) != Machine::SmTimerEventId)
423 {
424 NT_ASSERTMSG("State machine queue overflow", m_Count < SM_QUEUE_DEPTH);
425 m_Queue[m_Count] = Ev;
426 m_Count++;
427 KeReleaseSpinLock(&m_Lock, irql);
428 return TRUE;
429 }
430
431 m_WaitingForTimer = FALSE;
432 current = SmCurrent();
433 KeReleaseSpinLock(&m_Lock, irql);
434
435 result = current->Entry ? (Self()->*current->Entry)() : SmHandled();
436 if (!Run(irql, static_cast<USHORT>(Ev), result, current))
437 Self()->SmDereference();
438 return TRUE;
439 }
440
441 NT_ASSERTMSG("State machine queue overflow", m_Count < SM_QUEUE_DEPTH);
442 m_Queue[m_Count] = Ev;
443 m_Count++;
444
445 if (m_Running)
446 {
447 KeReleaseSpinLock(&m_Lock, irql);
448 return TRUE;
449 }
450
451 m_Running = TRUE;
452 KeReleaseSpinLock(&m_Lock, irql);
453
454 Self()->SmReference();
455 if (!Run(irql, static_cast<USHORT>(Ev), SmHandled(), NULL))
456 Self()->SmDereference();
457 return TRUE;
458}
459
460template <typename Machine, typename Event>
461VOID
463{
464 const State* current;
466 KIRQL irql;
467
468 KeAcquireSpinLock(&m_Lock, &irql);
469
470 if (!m_WaitingForPassive || !m_Running)
471 {
472 m_UnexpectedCount++;
473 KeReleaseSpinLock(&m_Lock, irql);
474 SM_BREAK("Passive continuation without a state waiting for it");
475 return;
476 }
477
478 m_WaitingForPassive = FALSE;
479 current = SmCurrent();
480 KeReleaseSpinLock(&m_Lock, irql);
481
482 /* The reference taken by the drainer that queued the work item carries over */
483 result = current->Entry ? (Self()->*current->Entry)() : SmHandled();
485 Self()->SmDereference();
486}
487
488template <typename Machine, typename Event>
491 _In_ const State* Ancestor) const
492{
493 const State* walk;
494 ULONG frame;
495
496 for (frame = 0; frame <= m_Depth; frame++)
497 {
498 for (walk = m_Frames[frame]; walk != NULL; walk = walk->Parent)
499 {
500 if (walk == Ancestor)
501 return TRUE;
502 }
503 }
504
505 return FALSE;
506}
507
508template <typename Machine, typename Event>
509VOID
511{
512 KIRQL irql;
513
514 KeAcquireSpinLock(&m_Lock, &irql);
515 m_Paused = TRUE;
517 KeReleaseSpinLock(&m_Lock, irql);
518}
519
520template <typename Machine, typename Event>
521VOID
523 _In_ Event Ev)
524{
525 BOOLEAN removed;
526 KIRQL irql;
527
528 KeAcquireSpinLock(&m_Lock, &irql);
529 removed = RemoveQueued(Ev);
530 if (removed)
531 Trace(SmTraceDiscarded, static_cast<USHORT>(Ev));
532 KeReleaseSpinLock(&m_Lock, irql);
533
534 if (removed)
535 Self()->SmOnDequeue(Ev);
536}
537
538template <typename Machine, typename Event>
541 _In_ const State* Target,
543{
544 const State* walk;
545
546 for (walk = Target; walk != NULL; walk = walk->Parent)
547 {
548 if (walk->Flags & Flag)
549 return TRUE;
550 }
551
552 return FALSE;
553}
554
555template <typename Machine, typename Event>
558 _In_ const State* Target,
559 _In_ Event Ev)
560{
561 const Event* list;
562
563 if (Target->Discards == NULL)
564 return FALSE;
565
566 for (list = Target->Discards; *list != Event::Count; list++)
567 {
568 if (*list == Ev)
569 return TRUE;
570 }
571
572 return FALSE;
573}
574
575/* The state whose flags decide which queued events may run */
576template <typename Machine, typename Event>
579{
580 ULONG frame = m_Depth;
581
582 while ((frame > 0) && HasFlag(m_Frames[frame], SM_STATE_YIELDS_TO_CALLER))
583 frame--;
584
585 return m_Frames[frame];
586}
587
588template <typename Machine, typename Event>
591 _In_ Event Ev) const
592{
593 ULONG index;
594
595 for (index = 0; index < m_Count; index++)
596 {
597 if (m_Queue[index] == Ev)
598 return TRUE;
599 }
600
601 return FALSE;
602}
603
604template <typename Machine, typename Event>
607 _In_ Event Ev)
608{
609 ULONG read;
610 ULONG write = 0;
611
612 for (read = 0; read < m_Count; read++)
613 {
614 if (m_Queue[read] != Ev)
615 {
616 m_Queue[write] = m_Queue[read];
617 write++;
618 }
619 }
620
621 if (write == m_Count)
622 return FALSE;
623
624 m_Count = static_cast<UCHAR>(write);
625 return TRUE;
626}
627
628template <typename Machine, typename Event>
631 _Out_ Event* Ev)
632{
633 const State* effective = EffectiveState();
634 BOOLEAN takesRequests = HasFlag(effective, SM_STATE_TAKES_REQUESTS);
635 BOOLEAN criticalOnly = HasFlag(effective, SM_STATE_CRITICAL_ONLY);
636 ULONG pass;
637 ULONG index;
638 ULONG found = SM_QUEUE_DEPTH;
639
640 for (pass = 0; (pass < 2) && (found == SM_QUEUE_DEPTH); pass++)
641 {
642 for (index = 0; index < m_Count; index++)
643 {
644 SM_EVENT_CLASS eventClass =
645 Machine::EventInfo[static_cast<ULONG>(m_Queue[index])].Class;
646 BOOLEAN eligible;
647
648 if (eventClass == SmEventCritical)
649 eligible = TRUE;
650 else if (eventClass == SmEventRequest)
651 eligible = takesRequests && (!Machine::SmCompletionsFirst || (pass == 1));
652 else
653 eligible = !criticalOnly;
654
655 if (eligible)
656 {
657 found = index;
658 break;
659 }
660 }
661
662 if (!Machine::SmCompletionsFirst)
663 break;
664 }
665
666 if (found == SM_QUEUE_DEPTH)
667 return FALSE;
668
669 *Ev = m_Queue[found];
670 for (index = found + 1; index < m_Count; index++)
671 m_Queue[index - 1] = m_Queue[index];
672 m_Count--;
673 return TRUE;
674}
675
676/* Drop queued events the entered state discards, called with the lock held */
677template <typename Machine, typename Event>
678VOID
680 _In_ const State* Entered,
682{
683 const State* walk;
684 const Event* list;
685
686 for (walk = Entered; walk != NULL; walk = walk->Parent)
687 {
688 if (walk->Discards == NULL)
689 continue;
690
691 for (list = walk->Discards; *list != Event::Count; list++)
692 {
693 if (!RemoveQueued(*list))
694 continue;
695
696 Trace(SmTraceDiscarded, static_cast<USHORT>(*list));
697 KeReleaseSpinLock(&m_Lock, *Irql);
698 Self()->SmOnDequeue(*list);
699 KeAcquireSpinLock(&m_Lock, Irql);
700 }
701 }
702}
703
704template <typename Machine, typename Event>
705VOID
707 _In_ SM_TRACE_KIND Kind,
708 _In_ USHORT Ev)
709{
710 PSM_TRACE entry = &m_Trace[m_TraceIndex];
711
712 entry->State = SmCurrent()->Name;
713 entry->Event = Ev;
714 entry->Kind = static_cast<UCHAR>(Kind);
715 entry->Depth = m_Depth;
716 m_TraceIndex = (m_TraceIndex + 1) & SM_TRACE_MASK;
717}
718
719template <typename Machine, typename Event>
722 _In_ Event Ev)
723{
724 const State* walk;
726 ULONG frame = m_Depth;
727
728 /* Only the draining thread changes the frames, so no lock is needed here */
729 for (;;)
730 {
731 for (walk = m_Frames[frame]; walk != NULL; walk = walk->Parent)
732 {
733 if (Discards(walk, Ev))
734 return SmHandled();
735
736 if (walk->Handler == NULL)
737 continue;
738
739 result = (Self()->*walk->Handler)(Ev);
740 if (result.Kind != SmResultUnhandled)
741 {
742 result.Frame = static_cast<UCHAR>(frame);
743 return result;
744 }
745 }
746
747 if (frame == 0)
748 break;
749
750 frame--;
751 }
752
753 return SmUnhandled();
754}
755
762template <typename Machine, typename Event>
766 _In_ USHORT LastEvent,
768 _In_opt_ const State* Entered)
769{
770 const State* target;
771 const State* previous;
772 USHORT traced = LastEvent;
773 ULONG frame;
774 BOOLEAN canceled;
775 Event ev;
776 KIRQL irql;
777
778 for (;;)
779 {
780 /* Whoever posts the resume event owns the machine now, touch nothing */
781 if (Result.Kind == SmResultPaused)
782 return FALSE;
783
784 KeAcquireSpinLock(&m_Lock, &irql);
785
786 if ((Entered != NULL) && (Result.Kind != SmResultCall))
787 Purge(Entered, &irql);
788 Entered = NULL;
789
790 if (Result.Kind == SmResultReturn)
791 {
792 NT_ASSERTMSG("Return from the outermost frame", m_Depth > 0);
793 m_Depth--;
795 Purge(SmCurrent(), &irql);
796 traced = Result.Event;
797 KeReleaseSpinLock(&m_Lock, irql);
798 Result = Dispatch(static_cast<Event>(Result.Event));
799 continue;
800 }
801
802 if ((Result.Kind == SmResultTransition) || (Result.Kind == SmResultCall))
803 {
804 target = static_cast<const State*>(Result.Target);
805
806 if (Result.Kind == SmResultCall)
807 {
808 NT_ASSERTMSG("State machine frames exhausted", m_Depth + 1 < SM_MAX_DEPTH);
809 m_Depth++;
810 m_Frames[m_Depth] = target;
811 Trace(SmTraceCalled, traced);
812 }
813 else
814 {
815 frame = (Result.Frame == SM_FRAME_INNERMOST) ? m_Depth : Result.Frame;
816 while (m_Depth > frame)
817 {
818 if (!HasFlag(m_Frames[m_Depth], SM_STATE_YIELDS_TO_CALLER))
819 SM_BREAK("Caller left a frame that does not yield to it");
820 m_Depth--;
821 }
822
823 previous = m_Frames[frame];
824 m_Frames[frame] = target;
825 Trace(SmTraceEntered, traced);
826
827 KeReleaseSpinLock(&m_Lock, irql);
828 Self()->SmStateChanged();
829
830 if (HasFlag(previous, SM_STATE_STOP_TIMER_ON_EXIT) &&
831 (traced != Machine::SmTimerEventId))
832 {
833 canceled = Self()->SmCancelTimer();
834 KeAcquireSpinLock(&m_Lock, &irql);
835
836 if (!canceled && !RemoveQueued(static_cast<Event>(Machine::SmTimerEventId)))
837 {
838 m_WaitingForTimer = TRUE;
839 Trace(SmTraceWaitTimer, traced);
840 KeReleaseSpinLock(&m_Lock, irql);
841 return TRUE;
842 }
843 }
844 else
845 {
846 KeAcquireSpinLock(&m_Lock, &irql);
847 }
848 }
849
851 {
852 m_WaitingForPassive = TRUE;
853 Trace(SmTraceWaitPassive, traced);
854 KeReleaseSpinLock(&m_Lock, irql);
855 Self()->SmQueuePassive();
856 return TRUE;
857 }
858
859 KeReleaseSpinLock(&m_Lock, irql);
860 Entered = target;
861 Result = target->Entry ? (Self()->*target->Entry)() : SmHandled();
862 continue;
863 }
864
865 if (Result.Kind == SmResultUnhandled)
866 {
867 m_UnexpectedCount++;
868 Trace(SmTraceUnhandled, traced);
869 SM_BREAK("State machine got an event no state handles");
870 }
871
872 if (!Dequeue(&ev))
873 {
874 m_Running = FALSE;
875 KeReleaseSpinLock(&m_Lock, irql);
876 return FALSE;
877 }
878
879 traced = static_cast<USHORT>(ev);
880 Trace(SmTraceDispatched, traced);
881 KeReleaseSpinLock(&m_Lock, irql);
882
883 Self()->SmOnDequeue(ev);
884 Result = Dispatch(ev);
885 }
886}
static _Out_opt_ PULONGLONG Start
unsigned char BOOLEAN
Definition: actypes.h:127
#define read
Definition: acwin.h:97
#define write
Definition: acwin.h:98
#define index(s, c)
Definition: various.h:29
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
Run to completion engine. The first thread to post into an idle machine drains the queue; everyone el...
Definition: smengine.h:114
BOOLEAN SmIsWaitingForTimer() const
Definition: smengine.h:159
VOID SmDiscardQueued(_In_ Event Ev)
Definition: smengine.h:522
VOID SmQueuePassive()
Definition: smengine.h:254
ULONG m_UnexpectedCount
Definition: smengine.h:341
static const BOOLEAN SmCompletionsFirst
Definition: smengine.h:232
BOOLEAN SmIsIn(_In_ const State *Ancestor) const
Definition: smengine.h:490
BOOLEAN m_WaitingForTimer
Definition: smengine.h:339
static const USHORT SmTimerEventId
Definition: smengine.h:233
const State * SmCurrent() const
Definition: smengine.h:130
VOID SmInitialize(_In_ const State *Initial)
Definition: smengine.h:349
VOID SmBeginPause()
Definition: smengine.h:510
UCHAR m_TraceIndex
Definition: smengine.h:340
ULONG SmDepth() const
Definition: smengine.h:136
VOID SmContinueOnPassive()
Definition: smengine.h:462
BOOLEAN SmIsPaused() const
Definition: smengine.h:153
static SM_RESULT SmTransition(_In_ const State *Target)
Definition: smengine.h:194
BOOLEAN RemoveQueued(_In_ Event Ev)
Definition: smengine.h:606
BOOLEAN Dequeue(_Out_ Event *Ev)
Definition: smengine.h:630
const State * m_Frames[SM_MAX_DEPTH]
Definition: smengine.h:332
VOID SmStateChanged()
Definition: smengine.h:267
SM_TRACE m_Trace[SM_TRACE_DEPTH]
Definition: smengine.h:342
ULONG SmUnexpectedCount() const
Definition: smengine.h:165
VOID Purge(_In_ const State *Entered, _Inout_ KIRQL *Irql)
Definition: smengine.h:679
SM_RESULT Dispatch(_In_ Event Ev)
Definition: smengine.h:721
static SM_RESULT SmReturn(_In_ Event Ev)
Definition: smengine.h:217
SmState< Machine, Event > State
Definition: smengine.h:116
BOOLEAN SmAccepts(_In_ Event Ev)
Definition: smengine.h:236
KSPIN_LOCK m_Lock
Definition: smengine.h:331
const State * EffectiveState() const
Definition: smengine.h:578
static SM_RESULT SmPaused()
Definition: smengine.h:202
static SM_RESULT SmMakeResult(_In_ SM_RESULT_KIND Kind, _In_ USHORT Ev, _In_opt_ const VOID *Target)
Definition: smengine.h:172
BOOLEAN m_Running
Definition: smengine.h:336
VOID SmOnDequeue(_In_ Event Ev)
Definition: smengine.h:260
VOID Trace(_In_ SM_TRACE_KIND Kind, _In_ USHORT Ev)
Definition: smengine.h:706
static SM_RESULT SmCall(_In_ const State *Start)
Definition: smengine.h:209
BOOLEAN SmCancelTimer()
Definition: smengine.h:273
static BOOLEAN Discards(_In_ const State *Target, _In_ Event Ev)
Definition: smengine.h:557
Event m_Queue[SM_QUEUE_DEPTH]
Definition: smengine.h:333
static SM_RESULT SmHandled()
Definition: smengine.h:182
Machine * Self()
Definition: smengine.h:280
static SM_RESULT SmUnhandled()
Definition: smengine.h:188
BOOLEAN IsQueued(_In_ Event Ev) const
Definition: smengine.h:590
BOOLEAN m_WaitingForPassive
Definition: smengine.h:338
const State * SmFrame(_In_ ULONG Index) const
Definition: smengine.h:142
UCHAR m_Depth
Definition: smengine.h:334
VOID SmDereference()
Definition: smengine.h:249
static BOOLEAN HasFlag(_In_ const State *Target, _In_ ULONG Flag)
Definition: smengine.h:540
VOID SmReference()
Definition: smengine.h:244
BOOLEAN m_Paused
Definition: smengine.h:337
UCHAR m_Count
Definition: smengine.h:335
BOOLEAN Run(_In_ KIRQL CallerIrql, _In_ USHORT LastEvent, _In_ SM_RESULT Result, _In_opt_ const State *Entered)
Applies Result and keeps draining. Called without the lock. Entered is the state whose entry produced...
Definition: smengine.h:764
BOOLEAN SmPost(_In_ Event Ev)
Definition: smengine.h:370
Definition: list.h:39
_Out_ PKIRQL Irql
Definition: csq.h:179
struct tagRun Run
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define Trace(x)
Definition: inflate.c:42
KIRQL irql
Definition: wave.h:1
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
__in MdIrp __in PMdIoCsqIrpContext __in KIRQL CallerIrql
Definition: fxirpqueue.hpp:77
GLuint index
Definition: glext.h:6031
GLuint64EXT * result
Definition: glext.h:11304
#define Ev
Definition: i386-dis.c:352
uint32_t entry
Definition: isohybrid.c:63
struct task_struct * current
Definition: linux.c:32
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
unsigned short USHORT
Definition: pedump.c:61
#define list
Definition: rosglue.h:35
enum _SM_RESULT_KIND SM_RESULT_KIND
struct _SM_EVENT_INFO SM_EVENT_INFO
struct _SM_TRACE SM_TRACE
#define SM_TRACE_DEPTH
Definition: smengine.h:12
#define SM_STATE_TAKES_REQUESTS
Definition: smengine.h:39
enum _SM_TRACE_KIND SM_TRACE_KIND
enum _SM_EVENT_CLASS SM_EVENT_CLASS
#define SM_STATE_STOP_TIMER_ON_EXIT
Definition: smengine.h:43
_SM_RESULT_KIND
Definition: smengine.h:46
@ SmResultHandled
Definition: smengine.h:48
@ SmResultPaused
Definition: smengine.h:50
@ SmResultReturn
Definition: smengine.h:52
@ SmResultUnhandled
Definition: smengine.h:47
@ SmResultTransition
Definition: smengine.h:49
@ SmResultCall
Definition: smengine.h:51
#define SM_MAX_DEPTH
Definition: smengine.h:11
#define SM_BREAK(Message)
Definition: smengine.h:18
#define SM_STATE_YIELDS_TO_CALLER
Definition: smengine.h:42
_SM_TRACE_KIND
Definition: smengine.h:64
@ SmTraceEntered
Definition: smengine.h:68
@ SmTraceWaitTimer
Definition: smengine.h:76
@ SmTraceWaitPassive
Definition: smengine.h:72
@ SmTraceDispatched
Definition: smengine.h:67
@ SmTraceRejected
Definition: smengine.h:66
@ SmTraceCalled
Definition: smengine.h:73
@ SmTraceReturned
Definition: smengine.h:74
@ SmTracePaused
Definition: smengine.h:70
@ SmTraceResumed
Definition: smengine.h:71
@ SmTraceUnhandled
Definition: smengine.h:69
@ SmTraceDiscarded
Definition: smengine.h:75
@ SmTracePosted
Definition: smengine.h:65
#define SM_FRAME_INNERMOST
Definition: smengine.h:15
#define SM_NO_EVENT
Definition: smengine.h:14
#define SM_QUEUE_DEPTH
Definition: smengine.h:10
#define SM_STATE_NEEDS_PASSIVE
Definition: smengine.h:40
struct _SM_EVENT_INFO * PSM_EVENT_INFO
_SM_EVENT_CLASS
Definition: smengine.h:23
@ SmEventRequest
Definition: smengine.h:25
@ SmEventResume
Definition: smengine.h:26
@ SmEventCompletion
Definition: smengine.h:24
@ SmEventCritical
Definition: smengine.h:27
struct _SM_RESULT SM_RESULT
#define SM_TRACE_MASK
Definition: smengine.h:13
struct _SM_TRACE * PSM_TRACE
#define SM_STATE_CRITICAL_ONLY
Definition: smengine.h:41
Definition: xml2sdb.h:101
One state. Handler gets every event the state sees.
Definition: smengine.h:93
ULONG Flags
Definition: smengine.h:96
const SmState * Parent
Definition: smengine.h:94
PCSTR Name
Definition: smengine.h:95
const Event * Discards
Definition: smengine.h:99
SM_RESULT(Machine::* Entry)()
Definition: smengine.h:98
SM_RESULT(Machine::* Handler)(_In_ Event Ev)
Definition: smengine.h:97
PCSTR Name
Definition: smengine.h:32
BOOLEAN Replace
Definition: smengine.h:35
SM_EVENT_CLASS Class
Definition: smengine.h:33
BOOLEAN Coalesce
Definition: smengine.h:34
UCHAR Kind
Definition: smengine.h:57
USHORT Event
Definition: smengine.h:59
UCHAR Frame
Definition: smengine.h:58
const VOID * Target
Definition: smengine.h:60
PCSTR State
Definition: smengine.h:81
USHORT Event
Definition: smengine.h:82
UCHAR Kind
Definition: smengine.h:83
UCHAR Depth
Definition: smengine.h:84
Definition: tools.h:99
unsigned char UCHAR
Definition: typedefs.h:53
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
pass
Definition: typegen.h:25
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH * Dispatch
Definition: wsk.h:188
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define NT_ASSERT
Definition: rtlfuncs.h:3334
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3335