import gdb
import mcgdb
from mcgdb.toolbox.target import my_archi
from mcgdb.toolbox import my_gdb
from mcgdb.model.task import representation
#############################################
@my_gdb.Listed
@my_gdb.Numbered
@my_gdb.Dicted
[docs]class Filter(representation.CommComponent):
def __init__(self, name, instance, type_=None):
representation.CommComponent.__init__(self)
Filter.init_dict(str(instance), self)
if type_ is not None:
if type_.endswith("Base"):
type_ = type_[:type_.rindex("Base")]
type_ = type_.replace("_", ".")
self.type = type_
if name is None:
if "Filter." in self.type:
splitIdx = self.type.index("Filter.")
elif "Module." in self.type:
splitIdx = self.type.index("Module.")
else:
splitIdx = len(self.type)
name = self.type[0:splitIdx]
self.name = str(name)
self.instance = instance.cast(instance.dynamic_type)
self.owner_itf = None
self.is_top = False
self.running = False
self.executing = False
self.state = "Never executed"
#self.thread = None
self.work_count = 0
self.messages = []
#work_func = "%sFilter_work_function" % self.name
#changed that for distnace:
work_func = "%sFilter_work_function" % self.name.replace(".PedfBaseClass", "").replace(".", "_")
work_func = work_func
self.work_breakpoint = None
self.work_method = None
#if "Red" in self.name or "Hwcfg" in self.name:
#work_func = "toto"
pending = "pending" in gdb.execute("break '%s'" % work_func, to_string=True)
gdb.breakpoints()[-1].delete()
#pending = gdb.lookup_symbol(work_func)[0] is None;
if not pending:
import handle_workMeth
try:
self.work_breakpoint = handle_workMeth.WorkMethBreakpoint(work_func)
except my_gdb.AlreadyInstalledException as e:
self.work_breakpoint = e.actual
self.work_method = work_func
else:
print ("nop", work_func)
def __str__(self):
return "%s" % self.name
[docs] def set_name(self, name):
self.name = name
[docs] def consume_message(self, message):
self.messages.append(message)
[docs] def produce_message(self, itf):
return None
[docs] def get_messages(self):
return self.messages
[docs] def get_mark(self):
try:
current = gdb.parse_and_eval("_mind_this->__component_internal_data->pedf_ctlPtr")
if current == self.instance:
return "*"
except gdb.error:
pass
return " "
[docs] def run(self):
#my_gdb.push_stop_request("%s --> %s" % (self.name, self.state))
#gdb.execute("where")
#return
self.state = "Running"
#self.thread = gdb.parse_and_eval("&runTime.getThread()")
self.running = True
self.executing = True
self.work_count += 1
self.state_changed()
[docs] def finish_run(self):
self.state = "Not running"
self.running = False
self.executing = False
self.state_changed()
[docs] def state_changed(self, itf=None):
#print ("%s --> %s" % (self.name, self.state))
#gdb.execute("graph-it +suffix=", to_string=True)
return
#gdb.execute("!eog /tmp/my_graph.png")
#gdb.execute("!sleep 1")
my_gdb.push_stop_request("%s --> %s" % (self.name, self.state))
pass
@my_gdb.Listed
@my_gdb.Numbered
@my_gdb.Dicted
[docs]class Module(Filter):
def __init__(self, name, instance, type_=None):
Filter.__init__(self, name, instance, type_)
Module.init_dict(str(instance), self)
self.controller_itf = None
[docs] def set_name(self, name):
self.name = name
if self.controller_itf is not None:
self.controller_itf.comm_entity.set_name(name)
@my_gdb.Listed
@my_gdb.Numbered
@my_gdb.Dicted
[docs]class Worker(Filter):
def __init__(self, instance, parent):
Filter.__init__(self, parent, instance, type_="Controller")
Worker.init_dict(str(instance), self)
self.owner_itf = None
def __str__(self):
if self.name is not None:
return "%s" % self.name
return "Worker"
[docs] def set_name(self, name):
self.name = "%s_controller" % name
[docs]class Interface(representation.Endpoint):
ITF_TYPE = "Interface"
def __init__(self, module, name=None):
mcgdb.representation.Endpoint.__init__(self, module)
self.name = name
self.busy = None
self.blocking = False
def __str__(self):
if self.name is None:
return self.__class__.ITF_TYPE
else:
return "%s (%s)" % (self.name, self.__class__.ITF_TYPE)
[docs] def get_other_side(self):
if self.link is None:
return None
if len(self.link.endpoints) == 1:
raise ValueError("Link '%s' has only 1 endpoint." % self.link)
if len(self.link.endpoints) != 2:
raise ValueError("Link '%s' has more than 2 endpoints." % self.link)
for ep in self.link.endpoints:
if ep is not self:
return ep
[docs] def fetch_data(self):
self.comm_entity.state = "fetching data (%s)" % self.name
self.busy = self
self.link.count -= 1
self.link.out_count += 1
self.comm_entity.state_changed(itf=self)
[docs] def finish_fetch_data(self):
self.comm_entity.state = "Running"
self.busy = None
self.comm_entity.state_changed(itf=self)
[docs] def pop_data(self):
self.comm_entity.state = "Blocked poping (%s)" % self.name
self.comm_entity.executing = False
self.blocking = True
stop_on_deadlock()
self.comm_entity.state_changed(itf=self)
[docs] def finish_pop_data(self):
self.comm_entity.state = "Running"
self.comm_entity.executing = True
self.blocking = False
self.comm_entity.state_changed(itf=self)
[docs] def push_data(self):
self.comm_entity.state = "flushing data (%s)" % self.name
self.busy = self
self.comm_entity.state_changed(itf=self)
[docs] def finish_push_data(self):
self.comm_entity.state = "Running"
self.busy = None
self.comm_entity.state_changed(itf=self)
[docs] def flush_data(self):
self.comm_entity.state = "Blocked flushing (%s)" % self.name
self.comm_entity.executing = False
self.blocking = True
self.busy = self
self.link.count += 1
self.link.in_count += 1
self.comm_entity.state_changed(itf=self)
[docs] def finish_flush_data(self):
self.comm_entity.state = "Running"
self.comm_entity.executing = True
self.blocking = False
self.busy = None
self.comm_entity.state_changed(itf=self)
####
[docs]class OwnerLink(representation.Link):
def __init__(self):
representation.Link.__init__(self)
[docs]class OwnerInterface(Interface):
ITF_TYPE = "Owner"
def __init__(self, module, name=None):
Interface.__init__(self, module, name)
[docs]class OwneeInterface(Interface):
ITF_TYPE = "Ownee"
def __init__(self, module):
Interface.__init__(self, module)
####
[docs]class WorkerLink(OwnerLink):
def __init__(self):
OwnerLink.__init__(self)
[docs]class WorkerInterface(OwneeInterface):
ITF_TYPE = "Worker"
def __init__(self, module):
OwneeInterface.__init__(self, module)
[docs]class ControllerInterface(OwnerInterface):
ITF_TYPE = "Controller"
def __init__(self, module):
OwnerInterface.__init__(self, module, name=None)
####
[docs]class DataStreamLink(representation.Link):
def __init__(self):
representation.Link.__init__(self)
self.bridge = None
self.count = 0
self.in_count = 0
self.out_count = 0
def __str__(self):
return "DataStreamLink"+ ("(bridged)" if self.bridge is not None else "")
@my_gdb.Listed
@my_gdb.Dicted
[docs]class DataStreamInterface(Interface):
ITF_TYPE = "DataStream"
def __init__(self, instance, module, name, is_source):
Interface.__init__(self, module, name)
if instance is not None:
if instance.type.code == gdb.TYPE_CODE_REF:
instance = instance.address
if not str(instance.dynamic_type).endswith("*"):
instance = instance.address
DataStreamInterface.init_dict(str(instance), self)
self.bridge = None
self.real = None
self.instance = instance
self.is_source = is_source
self.messages = []
[docs] def produce_message(self):
return self.do_produce_message()
[docs] def do_produce_message(self):
return model.representation.Message("%s/%s" % (self.comm_entity, self.name),
None, "DataStream<>")
[docs] def consume_message(self, msg):
self.do_consume_message(msg)
[docs] def do_consume_message(self, msg):
self.messages.append(msg)
[docs] def get_messages(self):
return self.messages
def __str__(self):
return " ".join(( self.name, str(self.instance), "NA" if self.instance is None else str(self.instance.type)))
####
[docs]class DataStreamBridgeLink(DataStreamLink):
def __init__(self, link1, link2):
DataStreamLink.__init__(self)
link1.bridge = self
link2.bridge = self
self.bridges = [link1, link2]
def __str__(self):
return "DataStreamBridgeLink"
[docs]class DataStreamBridgeInterface(DataStreamInterface):
ITF_TYPE = "DataStream Bridge"
def __init__(self, real):
DataStreamInterface.__init__(self, None, real.comm_entity, real.name, real.is_source)
self.real = real
real.real = self
self.is_source = real.is_source
####
[docs]class DynamicControlLink(representation.Link):
def __init__(self):
representation.Link.__init__(self)
self.message_queue = []
self.waiting_io = False
[docs] def get_messages(self):
return self.message_queue
@my_gdb.Listed
@my_gdb.Dicted
[docs]class DynamicControlInterface(Interface):
ITF_TYPE = "DynamicControl"
def __init__(self, instance, module, name):
Interface.__init__(self, module, name)
if instance.type.code == gdb.TYPE_CODE_REF:
instance = instance.address
str_instance = str(instance)
DynamicControlInterface.init_dict(str_instance, self)
self.instance = instance
self.is_source = "Out" in str(instance.dynamic_type)
[docs] def produce_message(self):
return self.do_produce_message()
[docs] def do_produce_message(self):
cmd = gdb.parse_and_eval("cmd")
return model.representation.Message("%s/%s" % (self.comm_entity, self.name),
str(cmd), "DynamicControl<%s>" % cmd.dynamic_type)
#############################################
[docs]def connect_control_interface(parent, worker):
link = WorkerLink()
def connect(module, is_worker):
Interface = WorkerInterface if is_worker else ControllerInterface
itf = Interface(module)
link.add_endpoint(itf)
return itf
parent.controller_itf = connect(worker, is_worker=True)
worker.owner_itf = connect(parent, is_worker=False)
worker.name = "%s_controller" % parent.name
[docs]def connect_owner_interface(parent, son):
link = OwnerLink()
def connect(module, is_owner):
Interface = OwnerInterface if is_owner else OwneeInterface
itf = Interface(module)
link.add_endpoint(itf)
return itf
owner_itf = connect(parent, is_owner=True)
connect(son, is_owner=False)
son.owner_itf = owner_itf
[docs]def connect_datastream_interface(this, this_module, this_name, that, that_module, that_name):
link = DataStreamLink()
def connect(instance, module, name, is_source=False):
itf = DataStreamInterface(instance, module, name, is_source)
link.add_endpoint(itf)
return itf
this_itf = connect(this, this_module, this_name, is_source=True)
that_itf = connect(that, that_module, that_name)
def getBridgeLinkInterface(local_itf):
for other_local_itf in local_itf.comm_entity.endpoints:
if not isinstance(other_local_itf, DataStreamInterface):
continue
if other_local_itf is local_itf:
continue
if local_itf.name is None or other_local_itf.name is None:
continue
if local_itf.name != other_local_itf.name:
continue
#same name, create a bridge
#(two interface CANT have the same name within ONE entity)
if other_local_itf.real is None:
#no bridge endpoint on other_local_itf
#cas 1, 3
link = DataStreamBridgeLink(local_itf.link, other_local_itf.link)
other_remote_itf = DataStreamBridgeInterface(other_local_itf.get_other_side())
link.add_endpoint(other_remote_itf)
local_itf.bridge = other_local_itf
other_local_itf.bridge = local_itf
else:
#this is a bridge endpoint
#cas 5, 6
bridge_itf = other_local_itf
if not isinstance(bridge_itf, DataStreamBridgeInterface):
bridge_itf = bridge_itf.real
link = bridge_itf.link
bridge_itf.real.real = None
bridge_itf.endpoint_closed()
return link, local_itf.get_other_side()
else:
#cas 0
return None, local_itf.get_other_side()
link_this, to_connect_that = getBridgeLinkInterface(this_itf)
link_that, to_connect_this = getBridgeLinkInterface(that_itf)
#cas 1
if link_this is None and link_that is None:
pass
#cas 1
elif link_this is not None and link_that is None:
assert to_connect_that.real is None
link_this.add_endpoint(DataStreamBridgeInterface(to_connect_that))
to_connect_that.link.bridge = link_this
#cas 2
elif link_that is not None and link_this is None:
assert to_connect_this.real is None
link_that.add_endpoint(DataStreamBridgeInterface(to_connect_this))
to_connect_this.link.bridge = link_that
else:
assert link_this is not None and link_that is not None
assert len(link_this.endpoints) == 1
assert len(link_that.endpoints) == 1
itf = link_that.endpoints[0]
itf.link_destructed()
for bridged in link_that.bridges:
bridged.bridge = link_this
link_this.add_endpoint(itf)
[docs]def connect_dynamic_control_interface(this, this_module, this_name, that, that_module, that_name):
link = DynamicControlLink()
def connect(instance, module, name):
if isinstance(module, Module) and module.controller_itf is not None:
module = module.controller_itf.comm_entity
itf = DynamicControlInterface(instance, module, name)
link.add_endpoint(itf)
connect(this, this_module, this_name)
connect(that, that_module, that_name)
[docs]def complete_interface_mapping():
import handle_ds_operator
handle_ds_operator.init()
for module in Filter.list_:
module.instance = module.instance.cast(module.instance.dynamic_type)
if not isinstance(module, Worker):
module.set_name(str(module.instance["myName"].string()))
for attrib in module.instance.dereference().type.fields():
attrib_name = attrib.name
if not attrib_name.endswith("_Itf"):
continue
stream = module.instance[attrib_name]
stream_name = str(stream["myName"].string())
for connected in my_gdb.StdListPrinter(stream["connectedTo"]).children():
remote_stream = connected["stream"]
remote_name = str(remote_stream["myName"].string())
remote_filter = remote_stream["myController"]
remote_filter = remote_filter.cast(remote_filter.dynamic_type)
if "DchanApexModel" in str(remote_filter.dynamic_type):
# here, the remote_filter is wrong, because it's a DchanApexModel
# instead of the real Module we want to connect. So we need to
# retreive the right Module.
remote_filter = None
# we know it's a controller, so take all the fields of all the controllers
if not "dma" in remote_name:
for a_module in Worker.list_:
for an_attrib in a_module.instance.dereference().type.fields():
an_attrib_name = an_attrib.name
# and look for the Inteface field with matching name
if not (an_attrib_name.startswith(remote_name) and an_attrib_name.endswith("_Itf")):
continue
# now, we know that we've got the right Module selected
remote_filter = a_module.instance
break
if remote_filter is not None:
break
else:
print ("COULDNT LOOKUP ", remote_name)
actual_rmt_filter = Filter.key_to_value(str(remote_filter))
if actual_rmt_filter is None:
continue
connect_datastream_interface(stream, module, stream_name,
remote_stream, actual_rmt_filter, remote_name)
global loops
loops = [l for l in compute_loops()]
compute_loops_itf()
#############################################
[docs]def get_children(node):
for itf in node.endpoints:
if isinstance(itf, OwnerInterface) or \
isinstance(itf, OwneeInterface):
continue
if not itf.is_source:
continue
yield itf.get_other_side().comm_entity
loops = []
loops_itf = []
[docs]def compute_loops(node=None, node_parents=[]):
if node is None:
node = Filter.list_[1]
child_parents = [node]
child_parents.extend(node_parents)
for child in get_children(node):
if not child in node_parents:
for lp in compute_loops(child, child_parents):
yield lp
else:
yield [node]+child_parents[child_parents.index(child)::-1]
[docs]def compute_loops_itf():
loop_pairs = [zip(lp, lp[1:]) for lp in get_loops()]
#loop_pairs = list of list of loop nodes (a-b, b-c, c-a)*
for loop in loop_pairs:
ifaces = []
for src, dst in loop:
for itf in src.endpoints:
if isinstance(itf, OwnerInterface) or \
isinstance(itf, OwneeInterface):
continue
if not itf.is_source:
continue
if itf.get_other_side().comm_entity == dst:
ifaces.append(itf)
break
loops_itf.append(ifaces)
[docs]def get_loops():
return loops
[docs]def stop_on_deadlock():
deads = check_deadlock()
if deads:
my_gdb.push_stop_request(" /!\\ Deadlock detected in Loop %s /!\\" % ", ".join(["#%d" % d for d in deads]))
[docs]def check_deadlock(only_idx=None):
dead = []
for idx, loop in enumerate(loops_itf):
if only_idx is not None and only_idx != idx:
continue
for itf in loop:
itf = itf.get_other_side()
if not itf.blocking:
break
else:
dead.append(idx)
return dead
#############################################
runtime_types = {}
[docs]def runtime_type(type_name):
if type_name in runtime_types:
return runtime_types[type_name]
type_ = gdb.lookup_type(type_name)
runtime_types[type_name] = type_
return type_