Source code for mcgdb.model.task.environment.openmp.interaction.step

import logging; log = logging.getLogger(__name__)
log_user = logging.getLogger("mcgdb.log.user.step")

import gdb

from mcgdb.toolbox import my_gdb, aspect
from mcgdb.interaction import push_stop_request

representation = None

OPM_ZONES = ("single", "parallel", "critical", "task", "sections", "barrier", "master")

current_worker = None

@my_gdb.internal
[docs]def initialize(): global representation, current_worker from .. import representation current_worker = representation.Worker.get_current_worker
@my_gdb.internal
[docs]def activate(): aspect.register("step", aspects) cmd_omp_step() cmd_omp_next()
######################
[docs]class cmd_omp_next (gdb.Command): """ Stops the execution before the next OPM zone [.] --> stop only on the current thread, anythread otherwise [{}] --> stop at the next [where] zone. """.format(",".join(OPM_ZONES)) def __init__ (self): gdb.Command.__init__(self, "omp next", gdb.COMMAND_OBSCURE)
[docs] def invoke (self, arg, from_tty): args = gdb.string_to_argv(arg) # by default apply to any thread, # if args[0] is . apply to current thread apply_to = None if args and args[0] == ".": apply_to = current_worker() args.pop(0) where = args[0] if args and args[0] in OPM_ZONES else None if where is None and arg: print("Could not recognize 'where' argument '{}'".format(arg)) print("It should be one of {}".format(",".join(OPM_ZONES))) return step._nexting[apply_to] = where my_gdb.start_or_continue()
###
[docs]class cmd_omp_step (gdb.Command): """Steps inside the next OPM zone. Usage: (default) -> stop the first thread entering the zone all -> stop all the threads entering the zone out -> stop the end of the (inner most) zone """ def __init__ (self): gdb.Command.__init__(self, "omp step", gdb.COMMAND_OBSCURE)
[docs] def invoke (self, args, from_tty): step._stepping = True if "out" in args: step._step_out = True step._stepping = False my_gdb.start_or_continue()
#####################################
[docs]class step: _nexting = {} # worker -> (where|None) _stepping = False _step_out = False @staticmethod
[docs] def nexting(current_where): cw = current_worker() if None in step._nexting.keys(): cw = None else: cw = current_worker() if cw not in step._nexting.keys(): return False target_where = step._nexting[cw] if target_where is not None and \ current_where != target_where: return False del step._nexting[cw] return True
@staticmethod
[docs] def stepping(): ret = step._stepping step._stepping = False return ret
@staticmethod
[docs] def stepping_out(): ret = step._step_out step._step_out = False return ret
[docs]def check_nexting(where, what=None): assert where in OPM_ZONES if what is None: what = "{} zone".format(where.title()) if step.nexting(where): push_stop_request("[OpenMP next] reached {}".format(what)) return True return False
[docs]def check_stepping(evt): if step.stepping(): push_stop_request("[OpenMP step] inside {}".format(evt)) return True return False
[docs]def check_stepping_out(evt): if step.stepping_out(): push_stop_request("[OpenMP step out] outside {}".format(evt)) return True return False
####################### # Aspect for stepping # #######################
[docs]def aspects(Tracks): @Tracks(representation.Worker) class WorkerTracker: def __init__(this): pass @Tracks(representation.ParallelJob) class ParallelJobTracker: def __init__(this): this.args.num_workers, this.args.parent_worker = this.meth_args check_nexting("parallel") def start_working(this): check_stepping("Worker #{} in parallel zone".format(this.args.worker.number)) def stop_working(this): pass def completed(this): check_stepping_out("Parallel zone") def start_section_zone(this): check_nexting("sections") def stop_section_zone(this): check_stepping_out("Section zone") @Tracks(representation.SingleJob) class SingleTracker: def __init__(this): this.args.worker, this.args.parallel_job = this.meth_args def enter(this): check_nexting("single") if this.args.inside: check_stepping("Worker #{} in single zone".format(this.args.worker.number)) def finished(this): pass def completed(this): check_stepping_out("Single zone") @Tracks(representation.TaskJob) class TaskJobTracker: def __init__(this): this.args.worker, = this.meth_args log_user.info("New task: {}".format(this.self)) if check_nexting("task", "Task #{} creation".format(this.self.number)): my_gdb.up_before_prompt() def start(this): check_stepping("Worker #{} on the task".format(this.args.worker.number)) def finish(this): check_stepping_out("Task") @Tracks(representation.CriticalJob) class CriticalJobTracker: def __init__(this): this.args.worker,this. args.parallel_job = this.meth_args def try_enter(this): if check_nexting("critical"): my_gdb.up_before_prompt() def entered(this): check_stepping("Worker #{} in critical zone".format(this.args.worker.number)) def left(this): pass def completed(this): check_stepping_out("Critical zone") @Tracks(representation.Barrier) class BarrierTracker: def __init__(this): #if this.self.internal: return this.args.parallel_job, this.args.worker,= this.meth_args def reach_barrier(this): #if this.self.internal: return if check_nexting("barrier", "Barrier"): my_gdb.up_before_prompt() if gdb.parameter("scheduler-locking") == "on": log_user.warning("gdb scheduler-locking is active,") log_user.warning("OpenMP won't be able to pass the barrier") log_user.warning("Run `omp schedule all` if necessary.") def leave_barrier(this): if this.self.internal: return check_stepping_out("Barrier") @Tracks(representation.SectionJob) class SectionJobTracker: def __init__(this): this.args.parallel_job, this.args.worker, this.args.count = this.meth_args def work_on_section(this): if (this.args.section_id != 0): check_stepping("inside Section #{}".format(this.args.section_id)) def ended(this): pass def completed(this): pass