mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-07-09 08:33:36 +01:00
cpustates: fix cluster shutdown tracking
This commit resolves a couple of issues that were causing impropper cluster shutdown tracking in the cpustates script. - requested_states in the PowerStateProcessor was being initalized to -1 instead of None if no state was requested; the later checks are against None. - requested_states was not being set if the request could be satisfied immediately, and was being cleared upon being statisfied at a later time. This caused a problem when a core leaves idle and then tries to re-enter cluster shutdown. Here is an example sequence of events that illustrates the issue (assume core0 and core1 are the only two cores on a cluster): 1. both cores are running 2. core0 requests cluster-sleep. As core1 is running, it is put into core-sleep instead, and its request is saved. 3. core1 requests cluster-sleep. As core0 has a pending request for cluster-sleep, both cores are put into cluster-sleep and the pending request is cleared. 4. core1 becomes active. core0 is elevated to core-sleep. 5. core1 tries to enter cluster-sleep. Since core0 is currently in core-sleep (and its prior request has laredy been cleared), core1 is put into core-sleep instead, and its request is saved. This is an ERROR as but cores have in fact requested cluster-sleep at this stage. If, in step 4., core0 becomes active instead, exactly the same situation will result, as core1 was put into cluster-sleep immediately and its request was never saved. Idle state requests are now always tracked on entry and are only cleared when the core leave idle. - Also removed a pointless identy assignment.
This commit is contained in:
@ -156,7 +156,7 @@ class PowerStateProcessor(object):
|
|||||||
first_cluster_state=sys.maxint, first_system_state=sys.maxint,
|
first_cluster_state=sys.maxint, first_system_state=sys.maxint,
|
||||||
wait_for_start_marker=False):
|
wait_for_start_marker=False):
|
||||||
self.power_state = SystemPowerState(len(core_clusters))
|
self.power_state = SystemPowerState(len(core_clusters))
|
||||||
self.requested_states = defaultdict(lambda: -1) # cpu_id -> requeseted state
|
self.requested_states = {} # cpu_id -> requeseted state
|
||||||
self.wait_for_start_marker = wait_for_start_marker
|
self.wait_for_start_marker = wait_for_start_marker
|
||||||
self._saw_start_marker = False
|
self._saw_start_marker = False
|
||||||
self._saw_stop_marker = False
|
self._saw_stop_marker = False
|
||||||
@ -230,6 +230,7 @@ class PowerStateProcessor(object):
|
|||||||
def _process_idle_entry(self, event):
|
def _process_idle_entry(self, event):
|
||||||
if self.cpu_states[event.cpu_id].is_idling:
|
if self.cpu_states[event.cpu_id].is_idling:
|
||||||
raise ValueError('Got idle state entry event for an idling core: {}'.format(event))
|
raise ValueError('Got idle state entry event for an idling core: {}'.format(event))
|
||||||
|
self.requested_states[event.cpu_id] = event.idle_state
|
||||||
self._try_transition_to_idle_state(event.cpu_id, event.idle_state)
|
self._try_transition_to_idle_state(event.cpu_id, event.idle_state)
|
||||||
|
|
||||||
def _process_idle_exit(self, event):
|
def _process_idle_exit(self, event):
|
||||||
@ -250,18 +251,11 @@ class PowerStateProcessor(object):
|
|||||||
|
|
||||||
def _try_transition_to_idle_state(self, cpu_id, idle_state):
|
def _try_transition_to_idle_state(self, cpu_id, idle_state):
|
||||||
related_ids = self.idle_related_cpus[(cpu_id, idle_state)]
|
related_ids = self.idle_related_cpus[(cpu_id, idle_state)]
|
||||||
idle_state = idle_state
|
|
||||||
|
|
||||||
# Tristate: True - can transition, False - can't transition,
|
# Tristate: True - can transition, False - can't transition,
|
||||||
# None - unknown idle state on at least one related cpu
|
# None - unknown idle state on at least one related cpu
|
||||||
transition_check = self._can_enter_state(related_ids, idle_state)
|
transition_check = self._can_enter_state(related_ids, idle_state)
|
||||||
|
|
||||||
if not transition_check:
|
|
||||||
# If we can't enter an idle state right now, record that we've
|
|
||||||
# requested it, so that we may enter it later (once all related
|
|
||||||
# cpus also want a state at least as deep).
|
|
||||||
self.requested_states[cpu_id] = idle_state
|
|
||||||
|
|
||||||
if transition_check is None:
|
if transition_check is None:
|
||||||
# Unknown state on a related cpu means we're not sure whether we're
|
# Unknown state on a related cpu means we're not sure whether we're
|
||||||
# entering requested state or a shallower one
|
# entering requested state or a shallower one
|
||||||
@ -276,8 +270,6 @@ class PowerStateProcessor(object):
|
|||||||
self.cpu_states[cpu_id].idle_state = idle_state
|
self.cpu_states[cpu_id].idle_state = idle_state
|
||||||
for rid in related_ids:
|
for rid in related_ids:
|
||||||
self.cpu_states[rid].idle_state = idle_state
|
self.cpu_states[rid].idle_state = idle_state
|
||||||
if self.requested_states[rid] == idle_state:
|
|
||||||
del self.requested_states[rid] # request satisfied, so remove
|
|
||||||
|
|
||||||
def _can_enter_state(self, related_ids, state):
|
def _can_enter_state(self, related_ids, state):
|
||||||
"""
|
"""
|
||||||
@ -288,12 +280,13 @@ class PowerStateProcessor(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
for rid in related_ids:
|
for rid in related_ids:
|
||||||
rid_requested_state = self.requested_states[rid]
|
rid_requested_state = self.requested_states.get(rid, None)
|
||||||
rid_current_state = self.cpu_states[rid].idle_state
|
rid_current_state = self.cpu_states[rid].idle_state
|
||||||
if rid_current_state is None:
|
if rid_current_state is None:
|
||||||
return None
|
return None
|
||||||
if rid_current_state < state and rid_requested_state < state:
|
if rid_current_state < state:
|
||||||
return False
|
if rid_requested_state is None or rid_requested_state < state:
|
||||||
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user