In the List Config state machine (802.1Q-2018 clause 8.6.9.3), upon a ConfigChange (when GateEnabled is TRUE) ConfigPending is set to TRUE in the CONFIG_PENDING state, remains TRUE in the UPDATE_CONFIG state machine and is then set to FALSE in the CONFIG_IDLE state.
Also in the List Config stat machine, in the UPDATE_CONFIG state, NewConfigCT is set to TRUE. NewConfigCT being TRUE triggers the Cycle Timer state machine (802.1Q-2018 clause 8.6.9.1) to transition to the CYCLE_IDLE state, which then transitions to the SET_CYCLE_START_TIME (UCT). In the SET_CYCLE_START_TIME state, the SetCycleStartTime() procedure determines which rules should be taken.
Unfortunately, after the List Config state machine changes to the UPDATE_CONFIG state, it is not clear if ConfigPending will be set to FALSE before or after the Cycle Timer state machine gets to the SET_CYCLE_START_TIME state, hence the race condition.
This race condition only makes a difference to the outcome of the SetCycleStartTime() calculation when:
* A dynamic schedule change is done (applying a new gate control list while another one is already running)
* In the List Config state machine (802.1Q-2018 clause 8.6.9.3), the transition from CONFIG_PENDING to UPDATE_CONFIG occurs when (ConfigChangeTime < CurrentTime) (the problem doesn't occur if the transition occurs when ConfigChangeTime is equal to CurrentTime)
This is the behavior of the SetCycleStart() calculation after the List Config state machine under the two cases
* if the Cycle Timer state machine is run before ConfigPending is set to FALSE:
* ConfigPending is TRUE
* "ConfigChangeTime <= (CurrentTime + OperCy-cleTime + OperCycleTimeExtension)" must be true as ConfigChangeTime <= CurrentTime (this was required in the transition from the CONFIG_PENDING to the UPDATE_CONFIG in the List Config state machine)
* Therefore the SetCycleStart() will use rule "d)" and set CycleStartTime = ConfigChangeTime
* if the Cycle Timer state machine is run after ConfigPending is set to FALSE:
* ConfigPending is FALSE
* At this point, CurrentTime >= ConfigChangeTime >= OperBaseTime (ConfigChangeTIme is set >= AdminBaseTime in the SetConfigChangeTime() function; OperBaseTime was set AdminBaseTime in the UPDATEC_CONFIG state of the List Config state machine; and CurrentTime >= ConfigChangeTime as this was required in the transition from the CONFIG_PENDING to the UPDATE_CONFIG in the List Config state machine)
* The question is whether CurrentTime > OperBaseTime or CurrentTime == OperBaseTime:
* If (ConfigPending = FALSE, and OperBaseTime >= CurrentTime)
* CycleStartTime = OperBaseTime = AdminBaseTime
* If (ConfigPending = FALSE, and OperBaseTime < CurrentTime)
* CycleStartTime = (OperBaseTime + N*OperCycleTime), where N is the smallest integer for which CycleStartTime >= CurrentTime
* If CurrentTime > OperBaseTime (which will occur if the transition from CONFIG_PENDING to UPDATE_CONFIG in the List Config state machine occurs when ConfigChangeTime < CurrentTime) then the cycle will only start N*OperCycleTime after OperBaseTime essentially not starting a cycle (and not running any gates) for N*OperCycleTime