Skip to content

Commit 331e5d5

Browse files
authored
fmu2: restore pool state on all doStep exit paths (#15371)
Ensure fmi2DoStep always restores the memory pool and thread state, including error and assertion-driven exits, by routing failures through a shared cleanup path.
1 parent edd265e commit 331e5d5

1 file changed

Lines changed: 54 additions & 16 deletions

File tree

OMCompiler/SimulationRuntime/fmi/export/openmodelica/fmu2_model_interface.c

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,8 +2210,11 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
22102210
{
22112211
ModelInstance *comp = (ModelInstance *)c;
22122212
fmi2CallbackFunctions* functions = (fmi2CallbackFunctions*)comp->functions;
2213+
threadData_t *threadData = comp->threadData;
2214+
jmp_buf *old_jmp = threadData->mmc_jumper;
22132215
int i, zc_event = 0, time_event = 0;
22142216
int flag;
2217+
int done = 0;
22152218

22162219
fmi2Status status = fmi2OK;
22172220
fmi2Real* states = comp->states;
@@ -2229,6 +2232,12 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
22292232

22302233
MemPoolState doStep_pool_state = omc_util_get_pool_state();
22312234

2235+
setThreadData(comp);
2236+
2237+
/* try */
2238+
MMC_TRY_INTERNAL(simulationJumpBuffer)
2239+
threadData->mmc_jumper = threadData->simulationJumpBuffer;
2240+
22322241
eventInfo.newDiscreteStatesNeeded = fmi2False;
22332242
eventInfo.terminateSimulation = fmi2False;
22342243
eventInfo.nominalsOfContinuousStatesChanged = fmi2False;
@@ -2252,7 +2261,8 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
22522261
}
22532262
#endif
22542263

2255-
internalEventIteration(c, &eventInfo);
2264+
status = internalEventIteration(c, &eventInfo);
2265+
if (status != fmi2OK) goto doStep_cleanup;
22562266

22572267
/* Integration loop */
22582268
while (status == fmi2OK && comp->fmuData->localData[0]->timeValue < tEnd)
@@ -2269,22 +2279,25 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
22692279
double dt = comp->fmuData->localData[0]->timeValue - t;
22702280
double new_input_value = realInputDerivatives[mappedIndex] + comp->input_real_derivative[mappedIndex] * dt;
22712281
if (setReal(comp, i, new_input_value) != fmi2OK) // to be implemented by the includer of this file
2272-
return fmi2Error;
2282+
{
2283+
status = fmi2Error;
2284+
goto doStep_cleanup;
2285+
}
22732286
}
22742287
}
22752288
#endif
22762289

22772290
#if NUMBER_OF_STATES > 0
22782291
status = internalGetDerivatives(c, states_der, NUMBER_OF_STATES);
2279-
if (status != fmi2OK) return fmi2Error;
2292+
if (status != fmi2OK) goto doStep_cleanup;
22802293

22812294
status = internalGetContinuousStates(c, states, NUMBER_OF_STATES);
2282-
if (status != fmi2OK) return fmi2Error;
2295+
if (status != fmi2OK) goto doStep_cleanup;
22832296
#endif
22842297

22852298
#if NUMBER_OF_EVENT_INDICATORS > 0
22862299
status = internalGetEventIndicators(c, event_indicators_prev, NUMBER_OF_EVENT_INDICATORS);
2287-
if (status != fmi2OK) return fmi2Error;
2300+
if (status != fmi2OK) goto doStep_cleanup;
22882301
#endif
22892302

22902303
/* adjust for time events */
@@ -2313,16 +2326,19 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
23132326
if (flag < 0)
23142327
{
23152328
FILTERED_LOG(comp, fmi2Fatal, LOG_STATUSFATAL, "fmi2DoStep: CVODE integrator step failed.")
2316-
return fmi2Fatal;
2329+
status = fmi2Fatal;
2330+
goto doStep_cleanup;
23172331
}
23182332
#else
23192333
FILTERED_LOG(comp, fmi2Fatal, LOG_STATUSFATAL, "fmi2DoStep: FMU not compiled with SUNDIALS but solver CVODE selected.")
2320-
return fmi2Fatal;
2334+
status = fmi2Fatal;
2335+
goto doStep_cleanup;
23212336
#endif /* WITH_SUNDIALS */
23222337
break;
23232338
default:
23242339
FILTERED_LOG(comp, fmi2Fatal, LOG_STATUSFATAL, "fmi2DoStep: Unknown solver method %d.", comp->solverInfo->solverMethod)
2325-
return fmi2Fatal;
2340+
status = fmi2Fatal;
2341+
goto doStep_cleanup;
23262342
}
23272343

23282344
// update time
@@ -2339,25 +2355,28 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
23392355
double dt = comp->fmuData->localData[0]->timeValue - t;
23402356
double new_input_value = realInputDerivatives[mappedIndex] + comp->input_real_derivative[mappedIndex] * dt;
23412357
if (setReal(comp, i, new_input_value) != fmi2OK) // to be implemented by the includer of this file
2342-
return fmi2Error;
2358+
{
2359+
status = fmi2Error;
2360+
goto doStep_cleanup;
2361+
}
23432362
}
23442363
}
23452364
#endif
23462365

23472366
/* set the continuous states */
23482367
#if NUMBER_OF_STATES > 0
23492368
status = internalSetContinuousStates(c, states, NUMBER_OF_STATES);
2350-
if (status != fmi2OK) return fmi2Error;
2369+
if (status != fmi2OK) goto doStep_cleanup;
23512370
#endif
23522371

23532372
/* signal completed integrator step */
23542373
status = internal_CompletedIntegratorStep(c, fmi2True, &enterEventMode, &terminateSimulation);
2355-
if (status != fmi2OK) return fmi2Error;
2374+
if (status != fmi2OK) goto doStep_cleanup;
23562375

23572376
/* check for events */
23582377
#if NUMBER_OF_EVENT_INDICATORS > 0
23592378
status = internalGetEventIndicators(c, event_indicators, NUMBER_OF_EVENT_INDICATORS);
2360-
if (status != fmi2OK) return fmi2Error;
2379+
if (status != fmi2OK) goto doStep_cleanup;
23612380

23622381
for (i = 0; i < NUMBER_OF_EVENT_INDICATORS; i++)
23632382
{
@@ -2382,34 +2401,53 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
23822401
eventInfo.valuesOfContinuousStatesChanged = fmi2True;
23832402
eventInfo.nextEventTimeDefined = fmi2False;
23842403
eventInfo.nextEventTime = 0.0;
2385-
internalEventIteration(c, &eventInfo);
2404+
status = internalEventIteration(c, &eventInfo);
2405+
if (status != fmi2OK) goto doStep_cleanup;
23862406

23872407
if (eventInfo.valuesOfContinuousStatesChanged)
23882408
{
23892409
#if NUMBER_OF_STATES > 0
23902410
status = internalGetContinuousStates(c, states, NUMBER_OF_STATES);
2391-
if (status != fmi2OK) return fmi2Error;
2411+
if (status != fmi2OK) goto doStep_cleanup;
23922412
#endif
23932413
}
23942414

23952415
if (eventInfo.nominalsOfContinuousStatesChanged)
23962416
{
23972417
#if NUMBER_OF_STATES > 0
23982418
status = internalGetNominalsOfContinuousStates(c, states, NUMBER_OF_STATES);
2399-
if (status != fmi2OK) return fmi2Error;
2419+
if (status != fmi2OK) goto doStep_cleanup;
24002420
#endif
24012421
}
24022422

24032423
#if NUMBER_OF_EVENT_INDICATORS > 0
24042424
status = internalGetEventIndicators(c, event_indicators_prev, NUMBER_OF_EVENT_INDICATORS);
2405-
if (status != fmi2OK) return fmi2Error;
2425+
if (status != fmi2OK) goto doStep_cleanup;
24062426
#endif
24072427

24082428
comp->solverInfo->didEventStep = 1;
24092429
}
24102430
}
24112431

2432+
done = 1;
2433+
2434+
/* catch */
2435+
MMC_CATCH_INTERNAL(simulationJumpBuffer)
2436+
2437+
doStep_cleanup:
2438+
threadData->mmc_jumper = old_jmp;
24122439
omc_util_restore_pool_state(doStep_pool_state);
2440+
resetThreadData(comp);
2441+
2442+
if (!done)
2443+
{
2444+
if (status == fmi2OK)
2445+
{
2446+
FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2DoStep: terminated by an assertion.")
2447+
status = fmi2Error;
2448+
}
2449+
}
2450+
24132451
return status;
24142452
}
24152453

0 commit comments

Comments
 (0)