X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/147baad3c85745bba0138d0b4ba105e94d4ee91f..0d9a15e44114bd49c578a0ceda7503abdd9b39a9:/src/simix/simcalls.py diff --git a/src/simix/simcalls.py b/src/simix/simcalls.py index 46c7101f85..7d1b2b76bb 100755 --- a/src/simix/simcalls.py +++ b/src/simix/simcalls.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (c) 2014-2015. The SimGrid Team. All rights reserved. +# Copyright (c) 2014-2016. The SimGrid Team. All rights reserved. # This program is free software; you can redistribute it and/or modify it # under the terms of the license (GNU LGPL) which comes with this package. @@ -9,30 +9,17 @@ import re import glob -types = [( - 'TCHAR', 'char', 'c'), ('TSTRING', 'const char*', 'cc'), ('TINT', 'int', 'i'), ('TLONG', 'long', 'l'), ('TUCHAR', 'unsigned char', 'uc'), ('TUSHORT', 'unsigned short', 'us'), ('TUINT', 'unsigned int', 'ui'), ('TULONG', 'unsigned long', 'ul'), ('TFLOAT', 'float', 'f'), - ('TDOUBLE', 'double', 'd'), ('TDPTR', 'void*', 'dp'), ('TFPTR', 'FPtr', 'fp'), ('TCPTR', 'const void*', 'cp'), ('TSIZE', 'size_t', 'sz'), ('TSGSIZE', 'sg_size_t', 'sgsz'), ('TSGOFF', 'sg_offset_t', 'sgoff'), ('TVOID', 'void', ''), ('TDSPEC', 'void*', 'dp'), ('TFSPEC', 'FPtr', 'fp')] - - class Arg(object): - simcall_types = {k: v for _, k, v in types} - def __init__(self, name, type, casted=None): + def __init__(self, name, type): self.name = name self.type = type - self.casted = casted - assert type in self.simcall_types, '%s not in (%s)' % ( - type, ', '.join(self.simcall_types.keys())) def field(self): return self.simcall_types[self.type] def rettype(self): - return '%s' % self.casted if self.casted else self.type - - def cast(self): - return '(%s)' % self.casted if self.casted else '' - + return self.type class Simcall(object): simcalls_BODY = None @@ -49,15 +36,15 @@ class Simcall(object): # libsmx.c simcall_BODY_ if self.simcalls_BODY is None: f = open('libsmx.cpp') - self.simcalls_BODY = set( - re.findall('simcall_BODY_(.*?)\(', f.read())) + self.simcalls_BODY = set(re.findall('simcall_BODY_(.*?)\(', f.read())) f.close() if self.name not in self.simcalls_BODY: - print '# ERROR: No function calling simcall_BODY_%s' % self.name - print '# Add something like this to libsmx.c:' - print '%s simcall_%s(%s) {' % (self.res.rettype(), self.name, ', '.join('%s %s' % (arg.rettype(), arg.name) for arg in self.args)) - print ' return simcall_BODY_%s(%s);' % (self.name) - print '}' + print ('# ERROR: No function calling simcall_BODY_%s' % self.name) + print ('# Add something like this to libsmx.c:') + print ('%s simcall_%s(%s) {' % (self.res.rettype(), self.name, ', '. + join('%s %s' % (arg.rettype(), arg.name) for arg in self.args))) + print (' return simcall_BODY_%s(%s);' % (self.name, "...")) + print ('}') return False # smx_*.c void simcall_HANDLER_host_on(smx_simcall_t simcall, @@ -66,22 +53,21 @@ class Simcall(object): self.simcalls_PRE = set() for fn in glob.glob('smx_*') + glob.glob('../mc/*'): f = open(fn) - self.simcalls_PRE |= set( - re.findall('simcall_HANDLER_(.*?)\(', f.read())) + self.simcalls_PRE |= set(re.findall('simcall_HANDLER_(.*?)\(', f.read())) f.close() if self.need_handler: - if (self.name not in self.simcalls_PRE): - print '# ERROR: No function called simcall_HANDLER_%s' % self.name - print '# Add something like this to the relevant C file (like smx_io.c if it\'s an IO call):' - print '%s simcall_HANDLER_%s(smx_simcall_t simcall%s) {' % (self.res.rettype(), self.name, ''.join(', %s %s' % (arg.rettype(), arg.name) - for arg in self.args)) - print ' // Your code handling the simcall' - print '}' + if self.name not in self.simcalls_PRE: + print ('# ERROR: No function called simcall_HANDLER_%s' % self.name) + print ('# Add something like this to the relevant C file (like smx_io.c if it\'s an IO call):') + print ('%s simcall_HANDLER_%s(smx_simcall_t simcall%s) {' % (self.res.rettype(), self.name, ''. + join(', %s %s' % (arg.rettype(), arg.name)for arg in self.args))) + print (' // Your code handling the simcall') + print ('}') return False else: - if (self.name in self.simcalls_PRE): - print '# ERROR: You have a function called simcall_HANDLER_%s, but that simcall is not using any handler' % self.name - print '# Either change your simcall definition, or kill that function' + if self.name in self.simcalls_PRE: + print ('# ERROR: You have a function called simcall_HANDLER_%s, but that simcall is not using any handler' % self.name) + print ('# Either change your simcall definition, or kill that function') return False return True @@ -100,43 +86,44 @@ class Simcall(object): res.append('static inline %s simcall_%s__get__%s(smx_simcall_t simcall) {' % ( arg.rettype(), self.name, arg.name)) res.append( - ' return %s simcall->args[%i].%s;' % (arg.cast(), i, arg.field())) + ' return simgrid::simix::unmarshal<%s>(simcall->args[%i]);' % (arg.rettype(), i)) res.append('}') res.append('static inline void simcall_%s__set__%s(smx_simcall_t simcall, %s arg) {' % ( - self.name, arg.name, arg.type)) - res.append(' simcall->args[%i].%s = arg;' % (i, arg.field())) + self.name, arg.name, arg.rettype())) + res.append(' simgrid::simix::marshal<%s>(simcall->args[%i], arg);' % (arg.rettype(), i)) res.append('}') # Return value getter/setters if self.res.type != 'void': res.append( 'static inline %s simcall_%s__get__result(smx_simcall_t simcall){' % (self.res.rettype(), self.name)) - res.append(' return %s simcall->result.%s;' % - (self.res.cast(), self.res.field())) + res.append(' return simgrid::simix::unmarshal<%s>(simcall->result);' % self.res.rettype()) res.append('}') res.append( - 'static inline void simcall_%s__set__result(smx_simcall_t simcall, %s result){' % (self.name, self.res.type,)) - res.append(' simcall->result.%s = result;' % (self.res.field())) + 'static inline void simcall_%s__set__result(smx_simcall_t simcall, %s result){' % (self.name, self.res.rettype())) + res.append(' simgrid::simix::marshal<%s>(simcall->result, result);' % (self.res.rettype())) res.append('}') return '\n'.join(res) def case(self): res = [] + args = [ "simgrid::simix::unmarshal<%s>(simcall->args[%d])" % (arg.rettype(), i) + for i, arg in enumerate(self.args) ] res.append('case SIMCALL_%s:' % (self.name.upper())) if self.need_handler: - res.append( - ' %ssimcall_HANDLER_%s(simcall %s);' % ('simcall->result.%s = ' % self.res.field() if self.call_kind == 'Func' else ' ', - self.name, - ''.join(', %s simcall->args[%d].%s' % (arg.cast(), i, arg.field()) - for i, arg in enumerate(self.args)))) + call = "simcall_HANDLER_%s(simcall%s%s)" % (self.name, + ", " if len(args) > 0 else "", + ', '.join(args)) else: - res.append( - ' %sSIMIX_%s(%s);' % ('simcall->result.%s = ' % self.res.field() if self.call_kind == 'Func' else ' ', - self.name, - ','.join('%s simcall->args[%d].%s' % (arg.cast(), i, arg.field()) - for i, arg in enumerate(self.args)))) - res.append(' %sbreak; \n' % - ('SIMIX_simcall_answer(simcall);\n ' if self.call_kind != 'Blck' else ' ')) + call = "SIMIX_%s(%s)" % (self.name, ', '.join(args)) + if self.call_kind == 'Func': + res.append(" simgrid::simix::marshal<%s>(simcall->result, %s);" % (self.res.rettype(), call)) + else: + res.append(" " + call + ";"); + if self.call_kind != 'Blck': + res.append(' SIMIX_simcall_answer(simcall);') + res.append(' break;') + res.append('') return '\n'.join(res) def body(self): @@ -145,41 +132,20 @@ class Simcall(object): 'inline static %s simcall_BODY_%s(%s) {' % (self.res.rettype(), self.name, ', '.join('%s %s' % (arg.rettype(), arg.name) for arg in self.args))) - res.append(' smx_process_t self = SIMIX_process_self();') - res.append('') res.append( ' /* Go to that function to follow the code flow through the simcall barrier */') if self.need_handler: res.append(' if (0) simcall_HANDLER_%s(%s);' % (self.name, - ', '.join(["&self->simcall"] + [arg.name for arg in self.args]))) + ', '.join(["&SIMIX_process_self()->simcall"] + [arg.name for arg in self.args]))) else: res.append(' if (0) SIMIX_%s(%s);' % (self.name, ', '.join(arg.name for arg in self.args))) - res.append( - ' /* end of the guide intended to the poor programmer wanting to go from MSG to Surf */') - res.append('') - res.append(' self->simcall.call = SIMCALL_%s;' % - (self.name.upper())) - res.append( - ' memset(&self->simcall.result, 0, sizeof(self->simcall.result));') - res.append( - ' memset(self->simcall.args, 0, sizeof(self->simcall.args));') - res.append('\n'.join(' self->simcall.args[%d].%s = (%s) %s;' % (i, arg.field(), arg.type, arg.name) - for i, arg in enumerate(self.args))) - res.append(' if (self != simix_global->maestro_process) {') - res.append( - ' XBT_DEBUG("Yield process \'%s\' on simcall %s (%d)", self->name,') - res.append( - ' SIMIX_simcall_name(self->simcall.call), (int)self->simcall.call);') - res.append(' SIMIX_process_yield(self);') - res.append(' } else {') - res.append(' SIMIX_simcall_handle(&self->simcall, 0);') - res.append(' } ') - if self.res.type != 'void': - res.append(' return (%s) self->simcall.result.%s;' % - (self.res.rettype(), self.res.field())) - else: - res.append(' ') + res.append(' return simcall<%s%s>(SIMCALL_%s%s);' % ( + self.res.rettype(), + "".join([ ", " + arg.rettype() for i, arg in enumerate(self.args) ]), + self.name.upper(), + "".join([ ", " + arg.name for i, arg in enumerate(self.args) ]) + )); res.append(' }') return '\n'.join(res) @@ -204,18 +170,33 @@ def parse(fn): if line.startswith('#') or not line: continue match = re.match( - r'(\S*?) *(\S*?) *(\S*?) *\((.*?)(?:, *(.*?))?\) *(.*)', line) + r'^(\S+)\s+([^\)\(\s]+)\s*\(*(.*)\)\s*(\[\[.*\]\])?\s*;\s*?$', line) assert match, line - ans, handler, name, rest, resc, args = match.groups() - assert (ans == 'Proc' or ans == 'Func' or ans == 'Blck'), "Invalid call type: '%s'. Faulty line:\n%s\n" % ( - ans, line) - assert (handler == 'H' or handler == '-'), "Invalid need_handler indication: '%s'. Faulty line:\n%s\n" % ( - handler, line) + ret, name, args, attrs = match.groups() sargs = [] - for n, t, c in re.findall(r'\((.*?), *(.*?)(?:, *(.*?))?\)', args): - sargs.append(Arg(n, t, c)) - sim = Simcall(name, handler == 'H', - Arg('result', rest, resc), sargs, ans) + if not re.match("^\s*$", args): + for arg in re.split(",", args): + args = args.strip() + match = re.match("^(.*?)\s*?(\S+)$", arg) + t, n = match.groups() + t = t.strip() + n = n.strip() + sargs.append(Arg(n, t)) + if ret == "void": + ans = "Proc" + else: + ans = "Func" + handler = True + if attrs: + attrs = attrs[2:-2] + for attr in re.split(",", attrs): + if attr == "block": + ans = "Blck" + elif attr == "nohandler": + handler = False + else: + assert False, "Unknown attribute %s in: %s" % (attr, line) + sim = Simcall(name, handler, Arg('result', ret), sargs, ans) if resdi is None: simcalls.append(sim) else: @@ -278,6 +259,7 @@ if __name__ == '__main__': # smx_popping_accessors.c # fd = header('popping_accessors.h') + fd.write('#include "src/simix/popping_private.h"'); handle(fd, Simcall.accessors, simcalls, simcalls_dict) fd.write( "\n\n/* The prototype of all simcall handlers, automatically generated for you */\n\n") @@ -361,11 +343,28 @@ if __name__ == '__main__': # smx_popping_bodies.cpp # fd = header('popping_bodies.cpp') + fd.write('#include \n') fd.write('#include "smx_private.h"\n') fd.write('#include "src/mc/mc_forward.hpp"\n') fd.write('#include "xbt/ex.h"\n') fd.write('#include \n') fd.write("/** @cond */ // Please Doxygen, don't look at this\n") + fd.write(''' +template +inline static R simcall(e_smx_simcall_t call, T const&... t) +{ + smx_process_t self = SIMIX_process_self(); + simgrid::simix::marshal(&self->simcall, call, t...); + if (self != simix_global->maestro_process) { + XBT_DEBUG("Yield process '%s' on simcall %s (%d)", self->name.c_str(), + SIMIX_simcall_name(self->simcall.call), (int)self->simcall.call); + SIMIX_process_yield(self); + } else { + SIMIX_simcall_handle(&self->simcall, 0); + } + return simgrid::simix::unmarshal(self->simcall.result); +} +''') handle(fd, Simcall.body, simcalls, simcalls_dict) fd.write("/** @endcond */\n"); fd.close()