blob: 80119d9cf3bd37958f26230640258cf186d77982 [file] [log] [blame]
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +01001#!/usr/bin/env python3
2
3""" structured_task.py:
4
Nicola Mazzucato935f9cb2025-05-16 17:21:07 +01005 A generic abstraction class for executing a task with prerequisites and
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +01006 post execution action """
7
8from __future__ import print_function
9
10__copyright__ = """
11/*
Karl Zhang08681e62020-10-30 13:56:03 +080012 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010013 *
14 * SPDX-License-Identifier: BSD-3-Clause
15 *
16 */
17 """
Karl Zhang08681e62020-10-30 13:56:03 +080018
19__author__ = "tf-m@lists.trustedfirmware.org"
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010020__project__ = "Trusted Firmware-M Open CI"
Xinyu Zhang06286a92021-07-22 14:00:51 +080021__version__ = "1.4.0"
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010022
23import abc
24import time
25import multiprocessing
26
27
28class structuredTask(multiprocessing.Process):
29 """ A class that defined well structured chained execution of commands """
30
31 __metaclass__ = abc.ABCMeta
32
33 def __init__(self, name):
34
35 self._stopevent = multiprocessing.Event()
36 self._exec_sleep_period = 1.0
37 self._join_timeout = 1.0
38 self._exec_timeout = 0.0
39 self._task_name = name
40
41 # multiprocessing safe shared memory variables
42 self._mprc_manager = multiprocessing.Manager()
43
44 # Dictionary used to store objects between stages
45 self._mprc_stash = self._mprc_manager.dict()
46
47 # Integer variable that stores status of flow
48 self._mprc_status = multiprocessing.Value('i', False)
49 super(structuredTask, self).__init__(name=name)
50
51 # Perform initialization
52 # If user code raises exception, class memory will not be allocated
53 # Variables can be safely shared in the pre stages, use stash for
54 # next stages
55 self.pre_exec(self.pre_eval())
56
57 # Class API/Interface
58
59 @abc.abstractmethod
60 def pre_eval(self):
61 """ Tests that need to be run in set-up state """
62
63 @abc.abstractmethod
64 def pre_exec(self, eval_ret):
Nicola Mazzucato935f9cb2025-05-16 17:21:07 +010065 """ Tasks that set-up execution environment """
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010066
67 @abc.abstractmethod
68 def task_exec(self):
69 """ Main tasks """
70
71 @abc.abstractmethod
72 def post_eval(self, eval_ret):
73 """ Tests that need to be run after main task """
74
75 @abc.abstractmethod
76 def post_exec(self):
77 """ Tasks that are run after main task """
78
79 def stash(self, key, data):
80 """ Store object in a shared memory interface """
81
82 self._mprc_stash[key] = data
83
84 def unstash(self, key):
85 """ Retrieve object from a shared memory interface """
86
87 try:
88 return self._mprc_stash[key]
89 except KeyError:
90 return None
91
92 def get_name(self):
93 """" Return name label of class """
94 return self._task_name
95
96 def get_status(self):
97 """ Return the status of the execution flow """
98 with self._mprc_status.get_lock():
99 return self._mprc_status.value
100
101 def set_status(self, status):
102 """ Return the status of the execution flow """
103 with self._mprc_status.get_lock():
104 self._mprc_status.value = status
105
106 def run(self):
107 try:
108
109 # Run Core code
110 while not self._stopevent.is_set():
111 self.task_exec()
112 time.sleep(self._exec_sleep_period)
113 break
114 # print("Stop Event Detected")
115 # TODO Upgrade reporting to a similar format
116 print("%s ==> Stop Event Detected" % self.get_name())
117
118 # Post stage
119 # If something faifs in post the user should set the correct status
120 self.set_status(0)
121 print("%s ==> Stop Event Set OK Status" % self.get_name())
122 except Exception as exc:
123 print(("ERROR: Stopping %s "
124 "with Exception: \"%s\"") % (self.get_name(), exc))
125 self.set_status(1)
126 # Always call post, and determine success failed by get_status
127 self.post_exec(self.post_eval())
128
129 def _t_stop(self):
130 """ Internal class stop to be called through thread """
Minos Galanakisea421232019-06-20 17:11:28 +0100131
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100132 if(self.is_alive()):
133 print("%s =========> STOP" % self.get_name())
134 self._stopevent.set()
135 print("Thead is alive %s" % self.is_alive())
136 print("Stop Event Triggered")
137
138 def stop(self):
139 """ External stop to be called by user code """
140
141 self._t_stop()
142 super(structuredTask, self).join(self._join_timeout)