aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--common.py47
-rw-r--r--config/config.py20
-rw-r--r--run/proc_entry.py5
-rwxr-xr-xrun_exps.py71
5 files changed, 69 insertions, 76 deletions
diff --git a/README.md b/README.md
index 0798b61..2fa4d2c 100644
--- a/README.md
+++ b/README.md
@@ -99,7 +99,7 @@ Schedule files have one of the following two formats:
99 ..., 99 ...,
100 ('path/to/proc','proc_value') 100 ('path/to/proc','proc_value')
101 ], 101 ],
102 'spin':[ 102 'task':[
103 ('real_time_task', 'task_arguments'), 103 ('real_time_task', 'task_arguments'),
104 ... 104 ...
105 ('real_time_task', 'task_arguments') 105 ('real_time_task', 'task_arguments')
diff --git a/common.py b/common.py
index 66df7bb..4920ec8 100644
--- a/common.py
+++ b/common.py
@@ -7,29 +7,34 @@ import sys
7from collections import defaultdict 7from collections import defaultdict
8from textwrap import dedent 8from textwrap import dedent
9 9
10def get_executable(prog, hint='unknown', optional=False): 10def get_executable(prog, cwd="."):
11 '''Search for @prog in system PATH. Print @hint if no binary is found.''' 11 '''Search for @prog in system PATH and @cwd.'''
12 12
13 def is_exe(fpath): 13 cwd_path = "%s/%s" % (cwd, prog)
14 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 14 if is_executable(cwd_path):
15 15 return cwd_path
16 fpath, fname = os.path.split(prog)
17 if fpath:
18 if is_exe(prog):
19 return prog
20 else: 16 else:
21 for path in os.environ["PATH"].split(os.pathsep): 17 for path in os.environ["PATH"].split(os.pathsep):
22 exe_file = os.path.join(path, prog) 18 exe_file = os.path.join(path, prog)
23 if is_exe(exe_file): 19 if is_executable(exe_file):
24 return exe_file 20 return exe_file
25 21
26 if not optional: 22 full_cwd = os.path.abspath(cwd)
27 sys.stderr.write("Cannot find executable '%s' in PATH. This is a part " 23 raise IOError("Cannot find executable '%s'! (cwd='%s')" % (prog, full_cwd))
28 "of '%s' which should be added to PATH to run.\n" % 24
29 (prog, hint)) 25def get_executable_hint(prog, hint, optional=False):
30 sys.exit(1) 26 '''Search for @prog in system PATH. Print @hint if no binary is found.
31 else: 27 Die if not @optional.'''
32 return None 28 try:
29 prog = get_executable(prog)
30 except IOError:
31 if not optional:
32 sys.stderr.write(("Cannot find executable '%s' in PATH. This is " +\
33 "a part of '%s' which should be added to PATH.\n")\
34 % (prog, hint))
35 sys.exit(1)
36
37 return prog
33 38
34def get_config_option(option): 39def get_config_option(option):
35 '''Search for @option in installed kernel config (if present). 40 '''Search for @option in installed kernel config (if present).
@@ -174,14 +179,12 @@ def ft_freq():
174 return freq 179 return freq
175 180
176 181
177def uname_matches(reg): 182def kernel():
178 data = subprocess.check_output(["uname", "-r"]) 183 return subprocess.check_output(["uname", "-r"])
179 return bool( re.match(reg, data) )
180 184
181def is_executable(fname): 185def is_executable(fname):
182 '''Return whether the file passed in is executable''' 186 '''Return whether the file passed in is executable'''
183 mode = os.stat(fname)[stat.ST_MODE] 187 return os.path.isfile(fname) and os.access(fname, os.X_OK)
184 return mode & stat.S_IXUSR and mode & stat.S_IRUSR
185 188
186def is_device(dev): 189def is_device(dev):
187 if not os.path.exists(dev): 190 if not os.path.exists(dev):
diff --git a/config/config.py b/config/config.py
index 3486a40..cbac6b2 100644
--- a/config/config.py
+++ b/config/config.py
@@ -1,18 +1,18 @@
1from __future__ import print_function 1from __future__ import print_function
2import itertools 2import itertools
3from common import get_executable,ft_freq 3from common import get_executable_hint,ft_freq
4 4
5'''Paths to binaries.''' 5'''Paths to binaries.'''
6BINS = {'rtspin' : get_executable('rtspin', 'liblitmus'), 6BINS = {'rtspin' : get_executable_hint('rtspin', 'liblitmus'),
7 'release' : get_executable('release_ts', 'liblitmus'), 7 'release' : get_executable_hint('release_ts', 'liblitmus'),
8 'ftcat' : get_executable('ftcat', 'feather-trace-tools'), 8 'ftcat' : get_executable_hint('ftcat', 'feather-trace-tools'),
9 'ftsplit' : get_executable('ft2csv', 'feather-trace-tools'), 9 'ftsplit' : get_executable_hint('ft2csv', 'feather-trace-tools'),
10 'ftsort' : get_executable('ftsort', 'feather-trace-tools'), 10 'ftsort' : get_executable_hint('ftsort', 'feather-trace-tools'),
11 'st_trace' : get_executable('st_trace', 'feather-trace-tools'), 11 'st_trace' : get_executable_hint('st_trace', 'feather-trace-tools'),
12 # Option, as not everyone uses kernelshark yet 12 # Option, as not everyone uses kernelshark yet
13 'trace-cmd' : get_executable('trace-cmd', 'rt-kernelshark', True), 13 'trace-cmd' : get_executable_hint('trace-cmd', 'rt-kernelshark', True),
14 # Optional, as sched_trace is not a publically supported repository 14 # Optional, as sched_trace is not a publically supported repository
15 'st_show' : get_executable('st_show', 'sched_trace', True)} 15 'st_show' : get_executable_hint('st_show', 'sched_trace', True)}
16 16
17'''Names of output files.''' 17'''Names of output files.'''
18FILES = {'ft_data' : 'ft.bin', 18FILES = {'ft_data' : 'ft.bin',
@@ -38,7 +38,7 @@ PARAMS = {'sched' : 'scheduler', # Scheduler used by run_exps
38DEFAULTS = {'params_file' : 'params.py', 38DEFAULTS = {'params_file' : 'params.py',
39 'sched_file' : 'sched.py', 39 'sched_file' : 'sched.py',
40 'duration' : 10, 40 'duration' : 10,
41 'spin' : 'rtspin', 41 'prog' : 'rtspin',
42 'cycles' : ft_freq() or 2000} 42 'cycles' : ft_freq() or 2000}
43 43
44'''Default sched_trace events (this is all of them).''' 44'''Default sched_trace events (this is all of them).'''
diff --git a/run/proc_entry.py b/run/proc_entry.py
index 4ac2c51..56f7c24 100644
--- a/run/proc_entry.py
+++ b/run/proc_entry.py
@@ -5,9 +5,10 @@ class ProcEntry(object):
5 self.proc = proc 5 self.proc = proc
6 self.data = data 6 self.data = data
7 7
8 def write_proc(self):
9 if not os.path.exists(self.proc): 8 if not os.path.exists(self.proc):
10 raise Exception("Invalid proc entry %s" % self.proc) 9 raise ValueError("Invalid proc entry %s" % self.proc)
10
11 def write_proc(self):
11 try: 12 try:
12 with open(self.proc, 'w') as entry: 13 with open(self.proc, 'w') as entry:
13 entry.write(self.data) 14 entry.write(self.data)
diff --git a/run_exps.py b/run_exps.py
index 6043931..77c9631 100755
--- a/run_exps.py
+++ b/run_exps.py
@@ -79,13 +79,13 @@ def convert_data(data):
79 r"(?P<HEADER>/proc/[\w\-]+?/)?" 79 r"(?P<HEADER>/proc/[\w\-]+?/)?"
80 r"(?P<ENTRY>[\w\-\/]+)" 80 r"(?P<ENTRY>[\w\-\/]+)"
81 r"\s*{\s*(?P<CONTENT>.*?)\s*?}$)|" 81 r"\s*{\s*(?P<CONTENT>.*?)\s*?}$)|"
82 r"(?P<SPIN>^" 82 r"(?P<TASK>^"
83 r"(?:(?P<TYPE>[^\d\-\s]\w*?) )?\s*" 83 r"(?:(?P<PROG>[^\d\-\s][\w\.]*?) )?\s*"
84 r"(?P<ARGS>[\w\-_\d\. \=]+)\s*$)", 84 r"(?P<ARGS>[\w\-_\d\. \=]+)\s*$)",
85 re.S|re.I|re.M) 85 re.S|re.I|re.M)
86 86
87 procs = [] 87 procs = []
88 spins = [] 88 tasks = []
89 89
90 for match in regex.finditer(data): 90 for match in regex.finditer(data):
91 if match.group("PROC"): 91 if match.group("PROC"):
@@ -94,16 +94,16 @@ def convert_data(data):
94 proc = (loc, match.group("CONTENT")) 94 proc = (loc, match.group("CONTENT"))
95 procs.append(proc) 95 procs.append(proc)
96 else: 96 else:
97 prog = match.group("TYPE") or "rtspin" 97 prog = match.group("PROG") or conf.DEFAULTS['prog']
98 spin = (prog, match.group("ARGS")) 98 spin = (prog, match.group("ARGS"))
99 spins.append(spin) 99 tasks.append(spin)
100 100
101 return {'proc' : procs, 'spin' : spins} 101 return {'proc' : procs, 'task' : tasks}
102 102
103 103
104def fix_paths(schedule, exp_dir, sched_file): 104def fix_paths(schedule, exp_dir, sched_file):
105 '''Replace relative paths of command line arguments with absolute ones.''' 105 '''Replace relative paths of command line arguments with absolute ones.'''
106 for (idx, (spin, args)) in enumerate(schedule['spin']): 106 for (idx, (task, args)) in enumerate(schedule['task']):
107 for arg in re.split(" +", args): 107 for arg in re.split(" +", args):
108 abspath = "%s/%s" % (exp_dir, arg) 108 abspath = "%s/%s" % (exp_dir, arg)
109 if os.path.exists(abspath): 109 if os.path.exists(abspath):
@@ -113,7 +113,7 @@ def fix_paths(schedule, exp_dir, sched_file):
113 print("WARNING: non-existent file '%s' may be referenced:\n\t%s" 113 print("WARNING: non-existent file '%s' may be referenced:\n\t%s"
114 % (arg, sched_file)) 114 % (arg, sched_file))
115 115
116 schedule['spin'][idx] = (spin, args) 116 schedule['task'][idx] = (task, args)
117 117
118 118
119def load_schedule(name, fname, duration): 119def load_schedule(name, fname, duration):
@@ -126,48 +126,43 @@ def load_schedule(name, fname, duration):
126 except: 126 except:
127 schedule = convert_data(data) 127 schedule = convert_data(data)
128 128
129 sched_dir = os.path.split(fname)[0]
130
129 # Make paths relative to the file's directory 131 # Make paths relative to the file's directory
130 fix_paths(schedule, os.path.split(fname)[0], fname) 132 fix_paths(schedule, sched_dir, fname)
131 133
132 proc_entries = [] 134 proc_entries = []
133 executables = [] 135 executables = []
134 136
135 # Create proc entries 137 # Create proc entries
136 for entry_conf in schedule['proc']: 138 for entry_conf in schedule['proc']:
137 path = entry_conf[0] 139 proc_entries += [ProcEntry(*entry_conf)]
138 data = entry_conf[1]
139 140
140 if not os.path.exists(path): 141 # Create executables
141 raise IOError("Invalid proc path %s: %s" % (path, name)) 142 for task_conf in schedule['task']:
143 if len(task_conf) != 2:
144 raise Exception("Invalid task conf %s: %s" % (task_conf, name))
142 145
143 proc_entries += [ProcEntry(path, data)] 146 (task, args) = (task_conf[0], task_conf[1])
144 147
145 # Create executables 148 real_task = com.get_executable(task, sched_dir)
146 for spin_conf in schedule['spin']:
147 if isinstance(spin_conf, str):
148 # Just a string defaults to default spin
149 (spin, args) = (conf.DEFAULTS['spin'], spin_conf)
150 else:
151 # Otherwise its a pair, the type and the args
152 if len(spin_conf) != 2:
153 raise IOError("Invalid spin conf %s: %s" % (spin_conf, name))
154 (spin, args) = (spin_conf[0], spin_conf[1])
155 149
156 real_spin = com.get_executable(spin, "") 150 # Last argument must always be duration
157 real_args = args.split() 151 real_args = args.split() + [duration]
158 if re.match(".*spin", real_spin):
159 real_args = ['-w'] + real_args + [duration]
160 152
161 if not com.is_executable(real_spin): 153 # All spins take a -w flag
162 raise OSError("Cannot run spin %s: %s" % (real_spin, name)) 154 if re.match(".*spin$", real_task) and '-w' not in real_args:
155 real_args = ['-w'] + real_args
163 156
164 executables += [Executable(real_spin, real_args)] 157 executables += [Executable(real_task, real_args)]
165 158
166 return proc_entries, executables 159 return proc_entries, executables
167 160
168 161
169def verify_environment(exp_params): 162def verify_environment(exp_params):
170 if exp_params.kernel and not com.uname_matches(exp_params.kernel): 163 '''Raise an exception if the current system doesn't match that required
164 by @exp_params.'''
165 if exp_params.kernel and not re.match(exp_params.kernel, com.kernel()):
171 raise InvalidKernel(exp_params.kernel) 166 raise InvalidKernel(exp_params.kernel)
172 167
173 if exp_params.config_options: 168 if exp_params.config_options:
@@ -197,15 +192,7 @@ def run_parameter(exp_dir, out_dir, params, param_name):
197 script_params = [script_params] 192 script_params = [script_params]
198 script_name = script_params.pop(0) 193 script_name = script_params.pop(0)
199 194
200 cwd_name = "%s/%s" % (exp_dir, script_name) 195 script = com.get_executable(script_name, cwd=exp_dir)
201 if os.path.isfile(cwd_name):
202 script = cwd_name
203 else:
204 script = com.get_executable(script_name, optional=True)
205
206 if not script:
207 raise Exception("Cannot find executable %s-script: %s" %
208 (param_name, script_name))
209 196
210 out = open('%s/%s-out.txt' % (out_dir, param_name), 'w') 197 out = open('%s/%s-out.txt' % (out_dir, param_name), 'w')
211 prog = Executable(script, script_params, 198 prog = Executable(script, script_params,
@@ -219,6 +206,7 @@ def run_parameter(exp_dir, out_dir, params, param_name):
219 206
220 207
221def get_exp_params(cmd_scheduler, cmd_duration, file_params): 208def get_exp_params(cmd_scheduler, cmd_duration, file_params):
209 '''Return ExpParam with configured values of all hardcoded params.'''
222 kernel = copts = "" 210 kernel = copts = ""
223 211
224 scheduler = cmd_scheduler or file_params[conf.PARAMS['sched']] 212 scheduler = cmd_scheduler or file_params[conf.PARAMS['sched']]
@@ -267,6 +255,7 @@ def load_experiment(sched_file, cmd_scheduler, cmd_duration,
267 else: 255 else:
268 file_params = {} 256 file_params = {}
269 257
258 # Create input needed by Experiment
270 exp_params = get_exp_params(cmd_scheduler, cmd_duration, file_params) 259 exp_params = get_exp_params(cmd_scheduler, cmd_duration, file_params)
271 procs, execs = load_schedule(exp_name, sched_file, exp_params.duration) 260 procs, execs = load_schedule(exp_name, sched_file, exp_params.duration)
272 261