in common/src/sm.c [485:539]
SM_RESULT sm_barrier_begin(SM_HANDLE sm)
{
SM_RESULT result;
/*Codes_SRS_SM_02_027: [ If sm is NULL then sm_barrier_begin shall fail and return SM_ERROR. ]*/
if (sm == NULL)
{
LogError("invalid arg SM_HANDLE sm=%p", sm);
result = SM_ERROR;
}
else
{
int32_t state = interlocked_add(&sm->state, 0);
if (
/*Codes_SRS_SM_02_064: [ If state is not SM_OPENED then sm_barrier_begin shall return SM_EXEC_REFUSED. ]*/
((state & SM_STATE_MASK) != SM_OPENED) ||
/*Codes_SRS_SM_02_065: [ If SM_CLOSE_BIT is set to 1 then sm_barrier_begin shall return SM_EXEC_REFUSED. ]*/
((state & SM_CLOSE_BIT) == SM_CLOSE_BIT) ||
/*Codes_SRS_SM_42_003: [ If SM_FAULTED_BIT is set to 1 then sm_barrier_begin shall return SM_EXEC_REFUSED. ]*/
((state & SM_FAULTED_BIT) == SM_FAULTED_BIT)
)
{
LogError("sm name=%s. cannot execute barrier begin when state is %" PRI_SM_STATE "", sm->name, SM_STATE_VALUE(state));
result = SM_EXEC_REFUSED;
}
else
{
/*Codes_SRS_SM_02_066: [ sm_barrier_begin shall switch the state to SM_OPENED_DRAINING_TO_BARRIER. ]*/
if (interlocked_compare_exchange(&sm->state, state - SM_OPENED + SM_OPENED_DRAINING_TO_BARRIER + SM_STATE_INCREMENT, state) != state)
{
/*Codes_SRS_SM_02_067: [ If the state changed meanwhile then sm_barrier_begin shall return SM_EXEC_REFUSED. ]*/
LogError("sm name=%s. state changed meanwhile (it was %" PRI_SM_STATE "), this thread cannot start a barrier, likely competing threads", sm->name, SM_STATE_VALUE(state));
result = SM_EXEC_REFUSED;
}
else
{
/*Codes_SRS_SM_02_068: [ sm_barrier_begin shall wait for n to reach 0. ]*/
if (InterlockedHL_WaitForValue(&sm->non_barrier_call_count, 0, UINT32_MAX) != INTERLOCKED_HL_OK)
{
/*switch back the state*/
/*Codes_SRS_SM_02_070: [ If there are any failures then sm_barrier_begin shall return SM_ERROR. ]*/
(void)interlocked_add(&sm->state, -SM_OPENED_DRAINING_TO_BARRIER + SM_OPENED + SM_STATE_INCREMENT);
LogError("sm name=%s. failure in InterlockedHL_WaitForValue(&sm->non_barrier_call_count=%p, 0, UINT32_MAX), state was %" PRI_SM_STATE "", sm->name, &sm->non_barrier_call_count, SM_STATE_VALUE(state));
result = SM_ERROR;
}
else
{
/*Codes_SRS_SM_02_069: [ sm_barrier_begin shall switch the state to SM_OPENED_BARRIER and return SM_EXEC_GRANTED. ]*/
(void)interlocked_add(&sm->state, -SM_OPENED_DRAINING_TO_BARRIER + SM_OPENED_BARRIER + SM_STATE_INCREMENT);
result = SM_EXEC_GRANTED;
}
}
}
}
return result;
}