2 # -*- coding: utf-8 -*-
4 # Copyright (c) 2014-2022. The SimGrid Team. All rights reserved.
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the license (GNU LGPL) which comes with this package.
15 def __init__(self, name, thetype):
18 self.simcall_types = []
21 return self.simcall_types[self.type]
30 def __init__(self, name, handler, res, args, call_kind):
34 self.need_handler = handler
35 self.call_kind = call_kind
38 # smx_*.c void simcall_HANDLER_host_on(smx_simcall_t simcall,
40 if self.simcalls_pre is None:
41 self.simcalls_pre = set()
42 for fn in glob.glob('smx_*') + glob.glob('../kernel/actor/ActorImpl*') + \
43 glob.glob('../mc/*cpp') + glob.glob('../kernel/activity/*cpp'):
45 self.simcalls_pre |= set(re.findall(r'simcall_HANDLER_(.*?)\(', f.read()))
48 if self.name not in self.simcalls_pre:
49 print('# ERROR: No function called simcall_HANDLER_%s' % self.name)
50 print('# Add something like this to the relevant C file (like smx_io.c if it\'s an IO call):')
51 print('%s simcall_HANDLER_%s(smx_simcall_t simcall%s)' % (self.res.rettype(), self.name, ''.
52 join(', %s %s' % (arg.rettype(), arg.name)for arg in self.args)))
54 print(' // Your code handling the simcall')
58 if self.name in self.simcalls_pre:
60 '# ERROR: You have a function called simcall_HANDLER_%s, but that simcall is not using any handler' %
62 print('# Either change your simcall definition, or kill that function')
67 return ' "Simcall::%s",' % self.name.upper()
72 regex = re.compile(r"^boost::intrusive_ptr<(.*?)>(.*)$") # to compute the raw type
73 # Arguments getter/setters
74 for i, arg in enumerate(self.args):
75 rawtype = regex.sub(r'\1*\2', arg.rettype())
76 res.append('static inline %s simcall_%s__get__%s(smx_simcall_t simcall)' % (
77 arg.rettype(), self.name, arg.name))
79 res.append(' return simgrid::simix::unmarshal<%s>(simcall->args_[%i]);' % (arg.rettype(), i))
81 res.append('static inline %s simcall_%s__getraw__%s(smx_simcall_t simcall)' % (
82 rawtype, self.name, arg.name))
84 res.append(' return simgrid::simix::unmarshal_raw<%s>(simcall->args_[%i]);' % (rawtype, i))
86 res.append('static inline void simcall_%s__set__%s(smx_simcall_t simcall, %s arg)' % (
87 self.name, arg.name, arg.rettype()))
89 res.append(' simgrid::simix::marshal<%s>(simcall->args_[%i], arg);' % (arg.rettype(), i))
92 # Return value getter/setters
93 if self.res.type != 'void':
94 rawtype = regex.sub(r'\1*\2', self.res.rettype())
96 'static inline %s simcall_%s__get__result(smx_simcall_t simcall)' % (self.res.rettype(), self.name))
98 res.append(' return simgrid::simix::unmarshal<%s>(simcall->result_);' % self.res.rettype())
100 res.append('static inline %s simcall_%s__getraw__result(smx_simcall_t simcall)' % (rawtype, self.name))
102 res.append(' return simgrid::simix::unmarshal_raw<%s>(simcall->result_);' % rawtype)
105 'static inline void simcall_%s__set__result(smx_simcall_t simcall, %s result)' % (self.name, self.res.rettype()))
107 res.append(' simgrid::simix::marshal<%s>(simcall->result_, result);' % (self.res.rettype()))
109 return '\n'.join(res)
114 args = ["simcall_.code_"]
115 res.append(indent + 'case Simcall::%s:' % (self.name.upper()))
116 if self.need_handler:
117 call = "simcall_HANDLER_%s(&simcall_%s%s)" % (self.name,
118 ", " if args else "",
121 call = "SIMIX_%s(%s)" % (self.name, ', '.join(args))
122 res.append(indent + " " + call + ";")
123 if self.call_kind != 'Blck':
124 res.append(indent + ' simcall_answer();')
125 res.append(indent + ' break;')
127 return '\n'.join(res)
129 def handler_prototype(self):
130 if self.need_handler:
131 return "XBT_PRIVATE void simcall_HANDLER_%s(smx_simcall_t simcall%s);" % (self.name,
132 ''.join(', %s %s' % (arg.rettype(), arg.name)
133 for i, arg in enumerate(self.args)))
140 simcalls_guarded = {}
141 for line in open(fn).read().split('\n'):
142 if line.startswith('##'):
144 simcalls_guarded[re.search(r'## *(.*)', line).group(1)] = resdi
145 if line.startswith('#') or not line:
148 r'^(\S+)\s+([^\)\(\s]+)\s*\(*(.*)\)\s*(\[\[.*\]\])?\s*;\s*$', line)
150 raise AssertionError(line)
151 ret, name, args, attrs = match.groups()
153 if not re.match(r"^\s*$", args):
154 for arg in re.split(",", args):
156 match = re.match(r"^(.*?)\s*?(\S+)$", arg)
157 t, n = match.groups()
160 sargs.append(Arg(n, t))
162 raise Exception ("Func simcalls (ie, returning a value) not supported anymore")
167 for attr in re.split(",", attrs):
170 elif attr == "nohandler":
173 raise AssertionError("Unknown attribute %s in: %s" % (attr, line))
174 sim = Simcall(name, handler, Arg('result', ret), sargs, ans)
179 return simcalls, simcalls_guarded
184 fd.write('/**********************************************************************/\n')
185 fd.write('/* File generated by src/simix/simcalls.py from src/simix/simcalls.in */\n')
187 fd.write('/* DO NOT EVER CHANGE THIS FILE */\n')
189 fd.write('/* change simcalls specification in src/simix/simcalls.in */\n')
190 fd.write('/* Copyright (c) 2014-2022. The SimGrid Team. All rights reserved. */\n')
191 fd.write('/**********************************************************************/\n\n')
193 fd.write(' * Note that the name comes from http://en.wikipedia.org/wiki/Popping\n')
194 fd.write(' * Indeed, the control flow is doing a strange dance in there.\n')
196 fd.write(' * That\'s not about http://en.wikipedia.org/wiki/Poop, despite the odor :)\n')
201 def handle(fd, func, simcalls, guarded_simcalls):
204 fd.write('\n'.join(filter(nonempty, (func(simcall) for simcall in simcalls))))
206 for guard, ll in guarded_simcalls.items():
207 fd.write('\n#if %s\n' % (guard))
208 fd.write('\n'.join(func(simcall) for simcall in ll))
214 simcalls, simcalls_dict = parse('simcalls.in')
217 ok &= all(map(Simcall.check, simcalls))
218 for _k, v in simcalls_dict.items():
219 ok &= all(map(Simcall.check, v))
221 print("Some checks fail!")
225 if __name__ == '__main__':