예제 #1
0
FORCEINLINE
PRT_BOOLEAN
PrtStateHasDefaultTransitionOrAction(
_In_ PRT_MACHINEINST_PRIV			*context
)
{
	PrtAssert(context->receive == NULL, "This function should not be called at a receive");
	PRT_STATEDECL *stateDecl = PrtGetCurrentStateDecl(context);
	PRT_BOOLEAN hasDefaultTransition = (context->process->program->eventSets[stateDecl->transSetIndex].packedEvents[0] & 0x1) == 1;
	PRT_BOOLEAN hasDefaultAction = (context->currentActionSetCompact[0] & 0x1) == 1;
	return hasDefaultTransition || hasDefaultAction;
}
예제 #2
0
FORCEINLINE
void
PrtRunExitFunction(
_In_ PRT_MACHINEINST_PRIV			*context,
_In_ PRT_UINT32						transIndex
)
{
	PRT_STATEDECL *stateDecl = PrtGetCurrentStateDecl(context);
	context->lastOperation = ReturnStatement;
	PrtLog(PRT_STEP_EXIT, context);
	PRT_UINT32 exitFunIndex = context->process->program->machines[context->instanceOf].states[context->currentState].exitFunIndex;
	PrtPushNewEventHandlerFrame(context, exitFunIndex, NULL);
	PrtGetExitFunction(context)((PRT_MACHINEINST *)context);
	if (transIndex < stateDecl->nTransitions)
	{
		PRT_UINT32 transFunIndex = stateDecl->transitions[transIndex].transFunIndex;
		PRT_DBG_ASSERT(transFunIndex != PRT_SPECIAL_ACTION_PUSH_OR_IGN, "Must be valid function index");
		PrtPushNewEventHandlerFrame(context, transFunIndex, NULL);
		context->process->program->machines[context->instanceOf].funs[transFunIndex].implementation((PRT_MACHINEINST *)context);
	}
	PRT_DBG_ASSERT(context->lastOperation == ReturnStatement, "Exit function must terminate with a ReturnStatement");
}
예제 #3
0
void
PrtRunStateMachine(
_Inout_ PRT_MACHINEINST_PRIV	*context,
_In_ PRT_BOOLEAN				doDequeue
)
{
	PRT_BOOLEAN lockHeld;
	PRT_DODECL *currActionDecl;
	PRT_UINT32 eventValue;

	context->isRunning = PRT_TRUE;

	if (doDequeue)
	{
		lockHeld = PRT_TRUE;
		goto DoDequeue;
	}
	else
	{
		lockHeld = PRT_FALSE;
		PrtUnlockMutex(context->stateMachineLock);
		goto DoEntry;
	}

DoEntry:
	PrtUpdateCurrentActionsSet(context);
	PrtUpdateCurrentDeferredSet(context);

	context->lastOperation = ReturnStatement;
	if (context->funStack.length == 0)
	{
		PrtLog(PRT_STEP_ENTRY, context);
		PRT_UINT32 entryFunIndex = context->process->program->machines[context->instanceOf].states[context->currentState].entryFunIndex;
		PrtPushNewEventHandlerFrame(context, entryFunIndex, NULL);
	}
	PRT_UINT32 funIndex = PrtBottomOfFunStack(context)->funIndex;
	context->process->program->machines[context->instanceOf].funs[funIndex].implementation((PRT_MACHINEINST *)context);
	goto CheckLastOperation;

DoAction:
	currActionDecl = PrtGetAction(context);
	PRT_UINT32 doFunIndex = currActionDecl->doFunIndex;
	context->lastOperation = ReturnStatement;
	if (doFunIndex == PRT_SPECIAL_ACTION_PUSH_OR_IGN)
	{
		PrtLog(PRT_STEP_IGNORE, context);
	}
	else
	{
		if (context->funStack.length == 0)
		{
			PrtLog(PRT_STEP_DO, context);
			PrtPushNewEventHandlerFrame(context, doFunIndex, NULL);
		}
		PRT_UINT32 funIndex = PrtBottomOfFunStack(context)->funIndex;
		context->process->program->machines[context->instanceOf].funs[funIndex].implementation((PRT_MACHINEINST *)context);
	}
	goto CheckLastOperation;

CheckLastOperation:
	if (context->receive != NULL)
	{
		context->isRunning = PRT_FALSE;
		PrtUnlockMutex(context->stateMachineLock);
		return;
	}
	switch (context->lastOperation)
	{
	case PopStatement:
		PrtRunExitFunction(context, PrtGetCurrentStateDecl(context)->nTransitions);
		PrtPopState(context, PRT_TRUE);
		goto DoDequeue;
	case RaiseStatement:
		goto DoHandleEvent;
	case ReturnStatement:
		goto DoDequeue;
	default:
		PRT_DBG_ASSERT(0, "Unexpected case in switch");
		break;
	}

DoDequeue:
	if (!lockHeld)
	{
		lockHeld = PRT_TRUE;
		PrtLockMutex(context->stateMachineLock);
	}
	PrtAssert(context->receive == NULL, "Machine must not be blocked at a receive");
	if (PrtDequeueEvent(context, NULL))
	{
		lockHeld = PRT_FALSE;
		PrtUnlockMutex(context->stateMachineLock);
		goto DoHandleEvent;
	}
	else
	{
		context->isRunning = PRT_FALSE;
		PrtUnlockMutex(context->stateMachineLock);
		return;
	}

DoHandleEvent:
	PrtAssert(context->receive == NULL, "Must not be blocked at a receive");
	eventValue = PrtPrimGetEvent(PrtGetCurrentTrigger(context));
	if (PrtIsPushTransition(context, eventValue))
	{
		PrtTakeTransition(context, eventValue);
		goto DoEntry;
	}
	else if (PrtIsTransitionPresent(context, eventValue))
	{
		PrtRunExitFunction(context, PrtFindTransition(context, eventValue));
		PrtTakeTransition(context, eventValue);
		goto DoEntry;
	}
	else if (PrtIsActionInstalled(eventValue, context->currentActionSetCompact))
	{
		goto DoAction;
	}
	else
	{
		PrtRunExitFunction(context, PrtGetCurrentStateDecl(context)->nTransitions);
		PrtPopState(context, PRT_FALSE);
		if (context->isHalted)
			return;
		goto DoHandleEvent;
	}

	PRT_DBG_ASSERT(PRT_FALSE, "Must not get here");
	return;
}
예제 #4
0
FORCEINLINE
PRT_DODECL*
PrtGetAction(
_In_ PRT_MACHINEINST_PRIV		*context
)
{
	PRT_UINT32 currEvent = PrtPrimGetEvent(PrtGetCurrentTrigger(context));
	PRT_BOOLEAN isActionInstalled = PRT_FALSE;
	PRT_UINT32 i, nActions;
	PRT_STATESTACK currStack;
	PRT_STATEDECL *stateTable;
	PRT_UINT32 topOfStackState;
	PRT_STATEDECL *stateDecl;
	PRT_DODECL *actionDecl = NULL;

	//check if action is defined for the current state
	isActionInstalled = PrtIsActionInstalled(currEvent, PrtGetActionsPacked(context, context->currentState));
	if (isActionInstalled)
	{
		//
		// get action function
		//
		stateDecl = PrtGetCurrentStateDecl(context);
		nActions = stateDecl->nDos;
		for (i = 0; i < nActions; i++)
		{
			if (stateDecl->dos[i].triggerEventIndex == currEvent)
			{
				actionDecl = &stateDecl->dos[i];
				return actionDecl;
			}
		}
	}

	//
	// Scan the parent states
	//
	currStack = context->callStack;
	stateTable = context->process->program->machines[context->instanceOf].states;
	for (i = currStack.length - 1; i >= 0; i--)
	{
		topOfStackState = currStack.stateStack[i].stateIndex;
		isActionInstalled = PrtIsActionInstalled(currEvent, PrtGetActionsPacked(context, topOfStackState));
		if (isActionInstalled)
		{
			//
			// get action function
			//
			nActions = stateTable[topOfStackState].nDos;
			for (i = 0; i < nActions; i++)
			{
				if (stateTable[topOfStackState].dos[i].triggerEventIndex == currEvent)
				{
					actionDecl = &stateTable[topOfStackState].dos[i];
					return actionDecl;
				}
			}
		}
	}

	PRT_DBG_ASSERT(actionDecl != NULL, "Action must not be NULL");
	return actionDecl;
}
예제 #5
0
파일: PrtUser.c 프로젝트: thisiscam/P
static void PrtUserPrintStep(_In_ PRT_STEP step, PRT_MACHINEINST *sender, _In_ PRT_MACHINEINST *receiver, _In_ PRT_VALUE* event, _In_ PRT_VALUE* payload,
							_Inout_ char **buffer, _Inout_ PRT_UINT32 *bufferSize, _Inout_ PRT_UINT32 *numCharsWritten)
{
	PRT_MACHINEINST_PRIV * c = (PRT_MACHINEINST_PRIV *)receiver;
	PRT_STRING machineName = c->process->program->machines[c->instanceOf]->name;
	PRT_UINT32 machineId = c->id->valueUnion.mid->machineId;
	PRT_STRING stateName = PrtGetCurrentStateDecl(c)->name;
	PRT_STRING eventName;

	switch (step)
	{
	case PRT_STEP_HALT:
		PrtUserPrintString("<HaltLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") halted in state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_ENQUEUE:
		eventName = c->process->program->events[PrtPrimGetEvent(event)].name;
		PrtUserPrintString("<EnqueueLog> Enqueued event ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" on Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(")\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_DEQUEUE:
		eventName = c->process->program->events[PrtPrimGetEvent(event)].name;
		PrtUserPrintString("<DequeueLog> Dequeued event ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" by Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(")\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_ENTRY:
		PrtUserPrintString("<StateLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") entered state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_CREATE:
		PrtUserPrintString("<CreateLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") is created\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_GOTO:
	{
		PRT_MACHINEINST_PRIV *context = (PRT_MACHINEINST_PRIV *)sender;
		PRT_STRING destStateName = c->process->program->machines[context->instanceOf]->states[context->destStateIndex].name;
		PrtUserPrintString("<GotoLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") goes to state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(destStateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break; 
	}
	case PRT_STEP_RAISE:
		eventName = c->process->program->events[PrtPrimGetEvent(event)].name;
		PrtUserPrintString("<RaiseLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") raised event ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_POP:
		PrtUserPrintString("<PopLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") popped and reentered state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_PUSH:
		PrtUserPrintString("<PushLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") pushed\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_UNHANDLED:
		eventName = c->process->program->events[c->eventValue].name;
		PrtUserPrintString("<PopLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") popped with unhandled event ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" and reentered state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_DO:
		PrtUserPrintString("<ActionLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") executed action in state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_EXIT:
		PrtUserPrintString("<ExitLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") exiting state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	case PRT_STEP_IGNORE:
		eventName = c->process->program->events[PrtPrimGetEvent(event)].name;
		PrtUserPrintString("<ActionLog> Machine ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("(", buffer, bufferSize, numCharsWritten);
		PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(") ignored event ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(" in state ", buffer, bufferSize, numCharsWritten);
		PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten);
		PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten);
		break;
	default:
		PrtAssert(PRT_FALSE, "Illegal PRT_STEP value");
		break;
	}
}