void PRT_CALL_CONV PrtSetLocalVarEx(_Inout_ PRT_VALUE **locals, _In_ PRT_UINT32 varIndex, _In_ PRT_VALUE *value, _In_ PRT_BOOLEAN cloneValue) { PRT_DBG_ASSERT(PrtIsValidValue(value), "value is not valid"); PRT_DBG_ASSERT(PrtIsValidValue(locals[varIndex]), "Variable must contain a valid value"); PrtFreeValue(locals[varIndex]); locals[varIndex] = cloneValue ? PrtCloneValue(value) : value; }
void PRT_CALL_CONV PrtSetGlobalVarEx(_Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_UINT32 varIndex, _In_ PRT_VALUE *value, _In_ PRT_BOOLEAN cloneValue) { PRT_DBG_ASSERT(PrtIsValidValue(value), "value is not valid"); PRT_DBG_ASSERT(PrtIsValidValue(context->varValues[varIndex]), "Variable must contain a valid value"); PrtFreeValue(context->varValues[varIndex]); context->varValues[varIndex] = cloneValue ? PrtCloneValue(value) : value; }
void PrtRaise( _Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_VALUE *event, _In_ PRT_VALUE *payload ) { PrtAssert(!PrtIsSpecialEvent(event), "Raised event must not be null"); PrtAssert(PrtInhabitsType(payload, PrtGetPayloadType(context, event)), "Payload must be member of event payload type"); context->lastOperation = RaiseStatement; PrtFreeValue(context->currentTrigger); PrtFreeValue(context->currentPayload); context->currentTrigger = PrtCloneValue(event); context->currentPayload = PrtCloneValue(payload); PrtLog(PRT_STEP_RAISE, context); }
void P_CTOR_Timer_IMPL(PRT_MACHINEINST *context, PRT_VALUE *value) { TimerContext *timerContext = (TimerContext *)PrtMalloc(sizeof(TimerContext)); timerContext->client = PrtCloneValue(value); timerContext->started = PRT_FALSE; context->extContext = timerContext; }
void P_CTOR_Timer_IMPL(PRT_MACHINEINST *context, PRT_VALUE *value) { printf("Entering P_CTOR_Timer_IMPL\n"); TimerContext *timerContext = (TimerContext *)malloc(sizeof(TimerContext)); timerContext->client = PrtCloneValue(value); timerContext->timer = CreateWaitableTimer(NULL, TRUE, NULL); PrtAssert(timerContext->timer != NULL, "CreateWaitableTimer failed"); context->extContext = timerContext; }
void PrtPushNewEventHandlerFrame( _Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_UINT32 funIndex, _In_ PRT_VALUE **locals ) { PRT_UINT16 length = context->funStack.length; PrtAssert(length < PRT_MAX_FUNSTACK_DEPTH, "Fun stack overflow"); context->funStack.length = length + 1; context->funStack.funs[length].funIndex = funIndex; PRT_BOOLEAN freeLocals = (locals == NULL); PRT_FUNDECL *funDecl = &(context->process->program->machines[context->instanceOf].funs[funIndex]); if (locals == NULL && funDecl->maxNumLocals != 0) { locals = PrtCalloc(funDecl->maxNumLocals, sizeof(PRT_VALUE *)); for (PRT_UINT32 i = 0; i < funDecl->maxNumLocals; i++) { locals[i] = NULL; } } PRT_UINT32 count = funDecl->numEnvVars; if (funDecl->name == NULL) { PrtAssert(0 < count, "numEnvVars must be positive for anonymous function"); PRT_UINT32 payloadIndex = count - 1; if (locals[payloadIndex] != NULL) { PrtFreeValue(locals[payloadIndex]); } locals[payloadIndex] = PrtCloneValue(context->currentPayload); } if (funDecl->localsNmdTupType != NULL) { PRT_UINT32 size = funDecl->localsNmdTupType->typeUnion.nmTuple->arity; for (PRT_UINT32 i = 0; i < size; i++) { PRT_TYPE *indexType = funDecl->localsNmdTupType->typeUnion.nmTuple->fieldTypes[i]; if (locals[count] != NULL) { PrtFreeValue(locals[count]); } locals[count] = PrtMkDefaultValue(indexType); count++; } } context->funStack.funs[length].locals = locals; context->funStack.funs[length].freeLocals = freeLocals; context->funStack.funs[length].returnTo = 0xFFFF; context->funStack.funs[length].rcase = NULL; }
PRT_MACHINEINST_PRIV * PrtMkMachinePrivate( _Inout_ PRT_PROCESS_PRIV *process, _In_ PRT_UINT32 instanceOf, _In_ PRT_VALUE *payload ) { PRT_UINT32 packSize; PRT_UINT32 nVars; PRT_UINT8 eQSize; PRT_MACHINEINST_PRIV *context; PRT_UINT32 i; PrtLockMutex(process->processLock); nVars = process->program->machines[instanceOf].nVars; eQSize = PRT_QUEUE_LEN_DEFAULT; // // Allocate memory for state machine context // context = (PRT_MACHINEINST_PRIV*)PrtMalloc(sizeof(PRT_MACHINEINST_PRIV)); // // Add it to the array of machines in the process // PRT_UINT32 numMachines = process->numMachines; PRT_UINT32 machineCount = process->machineCount; PRT_MACHINEINST **machines = process->machines; if (machineCount == 0) { machines = (PRT_MACHINEINST **)PrtCalloc(1, sizeof(PRT_MACHINEINST *)); process->machines = machines; process->machineCount = 1; } else if (machineCount == numMachines) { PRT_MACHINEINST **newMachines = (PRT_MACHINEINST **)PrtCalloc(2 * machineCount, sizeof(PRT_MACHINEINST *)); for (PRT_UINT32 i = 0; i < machineCount; i++) { newMachines[i] = machines[i]; } PrtFree(machines); machines = newMachines; process->machines = newMachines; process->machineCount = 2 * machineCount; } machines[numMachines] = (PRT_MACHINEINST *)context; process->numMachines++; // // Initialize Machine Identity // context->process = (PRT_PROCESS *)process; context->instanceOf = instanceOf; PRT_MACHINEID id; id.machineId = process->numMachines; // index begins with 1 since 0 is reserved id.processId = process->guid; context->id = PrtMkMachineValue(id); context->extContext = NULL; context->isModel = PRT_FALSE; // // Initialize the map used in PrtDist, map from sender to the last seqnumber received // PRT_TYPE *domType = PrtMkPrimitiveType(PRT_KIND_MACHINE); PRT_TYPE *codType = PrtMkPrimitiveType(PRT_KIND_INT); PRT_TYPE *recvMapType = PrtMkMapType(domType, codType); context->recvMap = PrtMkDefaultValue(recvMapType); PrtFreeType(domType); PrtFreeType(codType); PrtFreeType(recvMapType); // Initialize Machine Internal Variables // context->currentState = process->program->machines[context->instanceOf].initStateIndex; context->isRunning = PRT_FALSE; context->isHalted = PRT_FALSE; context->lastOperation = ReturnStatement; context->currentTrigger = PrtMkEventValue(PRT_SPECIAL_EVENT_NULL); context->currentPayload = PrtCloneValue(payload); // // Allocate memory for local variables and initialize them // context->varValues = NULL; if (nVars > 0) { context->varValues = PrtCalloc(nVars, sizeof(PRT_VALUE*)); for (i = 0; i < nVars; i++) { context->varValues[i] = PrtMkDefaultValue(process->program->machines[instanceOf].vars[i].type); } } context->receive = NULL; // // Initialize various stacks // context->callStack.length = 0; context->funStack.length = 0; // // Initialize event queue // context->eventQueue.eventsSize = eQSize; context->eventQueue.events = (PRT_EVENT*)PrtCalloc(eQSize, sizeof(PRT_EVENT)); context->eventQueue.headIndex = 0; context->eventQueue.tailIndex = 0; context->eventQueue.size = 0; packSize = PrtGetPackSize(context); // // Initialize Inherited Deferred Set // context->inheritedDeferredSetCompact = (PRT_UINT32*)PrtCalloc(packSize, sizeof(PRT_UINT32)); // // Initialize the current deferred set // context->currentDeferredSetCompact = (PRT_UINT32*)PrtCalloc(packSize, sizeof(PRT_UINT32)); // // Initialize actions // context->inheritedActionSetCompact = (PRT_UINT32*)PrtCalloc(packSize, sizeof(PRT_UINT32)); context->currentActionSetCompact = (PRT_UINT32*)PrtCalloc(packSize, sizeof(PRT_UINT32)); // //Initialize state machine lock // context->stateMachineLock = PrtCreateMutex(); // //Log // PrtLog(PRT_STEP_CREATE, context); // // Allocate external context Structure // process->program->machines[context->instanceOf].extCtorFun((PRT_MACHINEINST *)context, payload); PrtUnlockMutex(process->processLock); // // Run the state machine // PrtLockMutex(context->stateMachineLock); PrtRunStateMachine(context, PRT_FALSE); return context; }
void PrtSendPrivate( _Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_VALUE *event, _In_ PRT_VALUE *payload ) { PRT_EVENTQUEUE *queue; PRT_UINT32 tail; PRT_UINT32 eventMaxInstances; PRT_UINT32 maxQueueSize; PRT_UINT32 eventIndex; PrtAssert(!PrtIsSpecialEvent(event), "Enqueued event must not be null"); PrtAssert(PrtInhabitsType(payload, PrtGetPayloadType(context, event)), "Payload must be member of event payload type"); if (context->isHalted) { // drop the event silently return; } eventIndex = PrtPrimGetEvent(event); eventMaxInstances = context->process->program->events[eventIndex].eventMaxInstances; maxQueueSize = context->process->program->machines[context->instanceOf].maxQueueSize; PrtLockMutex(context->stateMachineLock); queue = &context->eventQueue; // check if maximum allowed instances of event are already present in queue if (eventMaxInstances != 0xffffffff && PrtIsEventMaxInstanceExceeded(queue, eventIndex, eventMaxInstances)) { PrtUnlockMutex(context->stateMachineLock); PrtHandleError(PRT_STATUS_EVENT_OVERFLOW, context); return; } // if queue is full, resize the queue if possible if (queue->eventsSize == queue->size) { if (maxQueueSize != 0xffffffff && queue->size == maxQueueSize) { PrtUnlockMutex(context->stateMachineLock); PrtHandleError(PRT_STATUS_QUEUE_OVERFLOW, context); return; } PrtResizeEventQueue(context); } tail = queue->tailIndex; // // Add event to the queue // queue->events[tail].trigger = PrtCloneValue(event); queue->events[tail].payload = PrtCloneValue(payload); queue->size++; queue->tailIndex = (tail + 1) % queue->eventsSize; // //Log // PrtLog(PRT_STEP_ENQUEUE, context); // // Now try to run the machine if its not running already // if (context->isRunning) { PrtUnlockMutex(context->stateMachineLock); } else if (context->receive == NULL) { PrtRunStateMachine(context, PRT_TRUE); } else if (PrtIsEventReceivable(context, PrtPrimGetEvent(event))) { PrtRunStateMachine(context, PRT_FALSE); } else { PrtUnlockMutex(context->stateMachineLock); } return; }
void P_CTOR_Client_IMPL(PRT_MACHINEINST *context, PRT_VALUE *value) { ClientContext *clientContext = (ClientContext *)PrtMalloc(sizeof(ClientContext)); clientContext->client = PrtCloneValue(value); context->extContext = clientContext; }