10#define SM_QUEUE_DEPTH 32
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
18#define SM_BREAK(Message) NT_ASSERTMSG(Message, FALSE)
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
91template <
typename Machine,
typename Event>
112template <
typename Machine,
typename Event>
256 SM_BREAK(
"State needs passive level but the machine has no work item");
282 return static_cast<Machine*
>(
this);
347template <
typename Machine,
typename Event>
355 m_Frames[0] = Initial;
360 m_WaitingForPassive =
FALSE;
361 m_WaitingForTimer =
FALSE;
363 m_UnexpectedCount = 0;
368template <
typename Machine,
typename Event>
380 if (!Self()->SmAccepts(
Ev) || (
info->Coalesce && IsQueued(
Ev)))
389 if (
info->Replace && RemoveQueued(
Ev))
392 Self()->SmOnDequeue(
Ev);
398 if (!m_Paused || !m_Running)
403 SM_BREAK(
"Resume event posted to a machine that is not paused");
412 Self()->SmReference();
415 Self()->SmDereference();
419 if (m_WaitingForTimer)
422 if (
static_cast<USHORT>(
Ev) != Machine::SmTimerEventId)
425 m_Queue[m_Count] =
Ev;
431 m_WaitingForTimer =
FALSE;
437 Self()->SmDereference();
442 m_Queue[m_Count] =
Ev;
454 Self()->SmReference();
456 Self()->SmDereference();
460template <
typename Machine,
typename Event>
470 if (!m_WaitingForPassive || !m_Running)
474 SM_BREAK(
"Passive continuation without a state waiting for it");
478 m_WaitingForPassive =
FALSE;
485 Self()->SmDereference();
488template <
typename Machine,
typename Event>
496 for (frame = 0; frame <= m_Depth; frame++)
498 for (walk = m_Frames[frame]; walk !=
NULL; walk = walk->
Parent)
500 if (walk == Ancestor)
508template <
typename Machine,
typename Event>
520template <
typename Machine,
typename Event>
529 removed = RemoveQueued(
Ev);
535 Self()->SmOnDequeue(
Ev);
538template <
typename Machine,
typename Event>
555template <
typename Machine,
typename Event>
576template <
typename Machine,
typename Event>
580 ULONG frame = m_Depth;
585 return m_Frames[frame];
588template <
typename Machine,
typename Event>
604template <
typename Machine,
typename Event>
621 if (
write == m_Count)
628template <
typename Machine,
typename Event>
633 const State* effective = EffectiveState();
651 eligible = takesRequests && (!Machine::SmCompletionsFirst || (
pass == 1));
653 eligible = !criticalOnly;
662 if (!Machine::SmCompletionsFirst)
669 *
Ev = m_Queue[found];
677template <
typename Machine,
typename Event>
686 for (walk = Entered; walk !=
NULL; walk = walk->
Parent)
693 if (!RemoveQueued(*
list))
698 Self()->SmOnDequeue(*
list);
704template <
typename Machine,
typename Event>
712 entry->State = SmCurrent()->Name;
715 entry->Depth = m_Depth;
719template <
typename Machine,
typename Event>
726 ULONG frame = m_Depth;
731 for (walk = m_Frames[frame]; walk !=
NULL; walk = walk->
Parent)
733 if (Discards(walk,
Ev))
753 return SmUnhandled();
762template <
typename Machine,
typename Event>
771 const State* previous;
772 USHORT traced = LastEvent;
787 Purge(Entered, &
irql);
792 NT_ASSERTMSG(
"Return from the outermost frame", m_Depth > 0);
795 Purge(SmCurrent(), &
irql);
810 m_Frames[m_Depth] =
target;
816 while (m_Depth > frame)
819 SM_BREAK(
"Caller left a frame that does not yield to it");
823 previous = m_Frames[frame];
828 Self()->SmStateChanged();
831 (traced != Machine::SmTimerEventId))
833 canceled = Self()->SmCancelTimer();
836 if (!canceled && !RemoveQueued(
static_cast<Event>(Machine::SmTimerEventId)))
838 m_WaitingForTimer =
TRUE;
852 m_WaitingForPassive =
TRUE;
855 Self()->SmQueuePassive();
869 SM_BREAK(
"State machine got an event no state handles");
879 traced =
static_cast<USHORT>(ev);
883 Self()->SmOnDequeue(ev);
static _Out_opt_ PULONGLONG Start
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
Run to completion engine. The first thread to post into an idle machine drains the queue; everyone el...
BOOLEAN SmIsWaitingForTimer() const
VOID SmDiscardQueued(_In_ Event Ev)
static const BOOLEAN SmCompletionsFirst
BOOLEAN SmIsIn(_In_ const State *Ancestor) const
BOOLEAN m_WaitingForTimer
static const USHORT SmTimerEventId
const State * SmCurrent() const
VOID SmInitialize(_In_ const State *Initial)
VOID SmContinueOnPassive()
BOOLEAN SmIsPaused() const
static SM_RESULT SmTransition(_In_ const State *Target)
BOOLEAN RemoveQueued(_In_ Event Ev)
BOOLEAN Dequeue(_Out_ Event *Ev)
const State * m_Frames[SM_MAX_DEPTH]
SM_TRACE m_Trace[SM_TRACE_DEPTH]
ULONG SmUnexpectedCount() const
VOID Purge(_In_ const State *Entered, _Inout_ KIRQL *Irql)
SM_RESULT Dispatch(_In_ Event Ev)
static SM_RESULT SmReturn(_In_ Event Ev)
SmState< Machine, Event > State
BOOLEAN SmAccepts(_In_ Event Ev)
const State * EffectiveState() const
static SM_RESULT SmPaused()
static SM_RESULT SmMakeResult(_In_ SM_RESULT_KIND Kind, _In_ USHORT Ev, _In_opt_ const VOID *Target)
VOID SmOnDequeue(_In_ Event Ev)
VOID Trace(_In_ SM_TRACE_KIND Kind, _In_ USHORT Ev)
static SM_RESULT SmCall(_In_ const State *Start)
static BOOLEAN Discards(_In_ const State *Target, _In_ Event Ev)
Event m_Queue[SM_QUEUE_DEPTH]
static SM_RESULT SmHandled()
static SM_RESULT SmUnhandled()
BOOLEAN IsQueued(_In_ Event Ev) const
BOOLEAN m_WaitingForPassive
const State * SmFrame(_In_ ULONG Index) const
static BOOLEAN HasFlag(_In_ const State *Target, _In_ ULONG Flag)
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...
BOOLEAN SmPost(_In_ Event Ev)
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
#define KeReleaseSpinLock(sl, irql)
#define KeAcquireSpinLock(sl, irql)
#define KeInitializeSpinLock(sl)
__in MdIrp __in PMdIoCsqIrpContext __in KIRQL CallerIrql
struct task_struct * current
#define UNREFERENCED_PARAMETER(P)
enum _SM_RESULT_KIND SM_RESULT_KIND
struct _SM_EVENT_INFO SM_EVENT_INFO
struct _SM_TRACE SM_TRACE
#define SM_STATE_TAKES_REQUESTS
enum _SM_TRACE_KIND SM_TRACE_KIND
enum _SM_EVENT_CLASS SM_EVENT_CLASS
#define SM_STATE_STOP_TIMER_ON_EXIT
#define SM_BREAK(Message)
#define SM_STATE_YIELDS_TO_CALLER
#define SM_FRAME_INNERMOST
#define SM_STATE_NEEDS_PASSIVE
struct _SM_EVENT_INFO * PSM_EVENT_INFO
struct _SM_RESULT SM_RESULT
struct _SM_TRACE * PSM_TRACE
#define SM_STATE_CRITICAL_ONLY
One state. Handler gets every event the state sees.
SM_RESULT(Machine::* Entry)()
SM_RESULT(Machine::* Handler)(_In_ Event Ev)
#define RtlZeroMemory(Destination, Length)
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH * Dispatch
_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