SM_RESULT sm_exec_begin()

in common/src/sm.c [379:428]


SM_RESULT sm_exec_begin(SM_HANDLE sm)
{
    SM_RESULT result;
    /*Codes_SRS_SM_02_021: [ If sm is NULL then sm_exec_begin shall fail and return SM_ERROR. ]*/
    if (sm == NULL)
    {
        LogError("invalid argument SM_HANDLE sm=%p", sm);
        result = SM_ERROR;
    }
    else
    {
        int32_t state1 = interlocked_add(&sm->state, 0);
        if (
            /*Codes_SRS_SM_02_054: [ If state is not SM_OPENED then sm_exec_begin shall return SM_EXEC_REFUSED. ]*/
            ((state1 & SM_STATE_MASK) != SM_OPENED) ||
            /*Codes_SRS_SM_02_055: [ If SM_CLOSE_BIT is 1 then sm_exec_begin shall return SM_EXEC_REFUSED. ]*/
            ((state1 & SM_CLOSE_BIT) == SM_CLOSE_BIT) ||
            /*Codes_SRS_SM_42_002: [ If SM_FAULTED_BIT is 1 then sm_exec_begin shall return SM_EXEC_REFUSED. ]*/
            ((state1 & SM_FAULTED_BIT) == SM_FAULTED_BIT)
            )
        {
            LogError("sm name=%s. cannot call sm_exec_begin when state is %" PRI_SM_STATE "", sm->name, SM_STATE_VALUE(state1));
            result = SM_EXEC_REFUSED;
        }
        else
        {
            /*Codes_SRS_SM_02_056: [ sm_exec_begin shall increment n. ]*/
            (void)interlocked_increment(&sm->non_barrier_call_count);
            int32_t state2 = interlocked_add(&sm->state, 0);

            /*Codes_SRS_SM_02_057: [ If the state changed after incrementing n then sm_exec_begin shall return SM_EXEC_REFUSED. ]*/
            if (state1 != state2)
            {
                LogError("sm name=%s. state changed meanwhile from %" PRI_SM_STATE " to %" PRI_SM_STATE "", sm->name, SM_STATE_VALUE(state1), SM_STATE_VALUE(state2));
                int32_t n = interlocked_decrement(&sm->non_barrier_call_count);
                if (n == 0)
                {
                    wake_by_address_single(&sm->non_barrier_call_count);
                }
                result = SM_EXEC_REFUSED;
            }
            else
            {
                /*Codes_SRS_SM_02_058: [ sm_exec_begin shall return SM_EXEC_GRANTED. ]*/
                result = SM_EXEC_GRANTED;
            }
        }
    }
    return result;
}