in common/src/sm.c [430:483]
void sm_exec_end(SM_HANDLE sm)
{
/*Codes_SRS_SM_02_024: [ If sm is NULL then sm_exec_end shall return. ]*/
if (sm == NULL)
{
LogError("invalid arg SM_HANDLE sm=%p", sm);
}
else
{
int32_t state = interlocked_add(&sm->state, 0);
/*Codes_SRS_SM_42_013: [ sm_exec_end may be called when SM_FAULTED_BIT is 1. ]*/
if (
/*Codes_SRS_SM_02_059: [ If state is not SM_OPENED then sm_exec_end shall return. ]*/
((state & SM_STATE_MASK) != SM_OPENED) &&
/*Codes_SRS_SM_02_060: [ If state is not SM_OPENED_DRAINING_TO_BARRIER then sm_exec_end shall return. ]*/
((state & SM_STATE_MASK) != SM_OPENED_DRAINING_TO_BARRIER) &&
/*Codes_SRS_SM_02_061: [ If state is not SM_OPENED_DRAINING_TO_CLOSE then sm_exec_end shall return. ]*/
((state & SM_STATE_MASK) != SM_OPENED_DRAINING_TO_CLOSE)
)
{
LogError("sm name=%s. cannot execute exec end when state is %" PRI_SM_STATE "", sm->name, SM_STATE_VALUE(state));
}
else
{
/*Codes_SRS_SM_02_062: [ sm_exec_end shall decrement n with saturation at 0. ]*/
do /*a rather convoluted loop to make _end be idempotent (too many _end will be ignored)*/
{
int32_t n = interlocked_add(&sm->non_barrier_call_count, 0);
if (n <= 0)
{
/*Codes_SRS_SM_42_010: [ If n would decrement below 0, then sm_exec_end shall terminate the process. ]*/
LogCriticalAndTerminate("Unmatched call to sm_exec_end detected!!! Pending call count is invalid");
break;
}
else
{
if (interlocked_compare_exchange(&sm->non_barrier_call_count, n - 1, n) != n)
{
/*well - retry sort of...*/
}
else
{
/*Codes_SRS_SM_02_063: [ If n reaches 0 then sm_exec_end shall signal that. ]*/
if (n - 1 == 0)
{
wake_by_address_single(&sm->non_barrier_call_count);
}
break;
}
}
} while (1);
}
}
}