diff --git a/.gitignore b/.gitignore
index ce5c01ab14cc7e2685eaace19a57fd29780c90e6..bc88d7251ca2fe421373c81e2cadb4b157fe225c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
 **/__binaries__
 /openmp
 **/__pycache__
-*.pyc
+*.py[co]
diff --git a/__init__.py b/__init__.py
index 0bca79607d08fbcad7a4ec756e380a1da1dd782d..01d84d95d4c3fe2b57d68dbd5c6706589ab2b121 100644
--- a/__init__.py
+++ b/__init__.py
@@ -21,8 +21,8 @@ try:
     assert "built-in" in str(gdb.breakpoints) # make sure we have the right gdb package
 except Exception as e:
     import importlib
-    if not ("No module named" in str(e) and "gdb" in str(e)) and \
-            not ("module 'gdb' has no attribute 'breakpoints'" in str(e)):
+    if (not ("No module named" in str(e) and "gdb" in str(e)) and 
+        not ("module 'gdb' has no attribute 'breakpoints'" in str(e))):
         log.error("Cannot import gdb: {}".format(e))
         
     log.critical("Importing DUMMY gdb module")
@@ -44,8 +44,13 @@ from .toolbox.python_utils import internal, info
 from .toolbox import register_model, toggle_activate_submodules
 
 log.info("Loading mcgdb models ...")
-from . import model
-
+try:
+    from . import model
+except Exception as e:
+    log_user.fatal("###                              ###")
+    log_user.fatal("### Loading mcgdb models failed. ###")
+    log_user.fatal("###                              ###")
+    log_user.exception(e)
 log_user.info("Loading of mcgdb environment completed.")
     
 ###################
@@ -56,8 +61,8 @@ def initialize_by_name():
         gdb_binname = line.split("\x00")[0]
         
     if "mcgdb" not in gdb_binname:
-        log.warn("*Not* loading mcgdb debugging extention.")
-        log.warn("Run `py import mcgdb; mcgdb.initialize()` to load it manually.")
+        log_user.warn("*Not* loading mcgdb debugging extention.")
+        log_user.warn("Run `py import mcgdb; mcgdb.initialize()` to load it manually.")
         return
     
     initialize()
diff --git a/capture.py b/capture.py
index 82d4b1ac58c48acfa77b23c71b9f8f50448fe98d..f1d72f4b7fc62a6b8ae4357b689b955e22f8d4fc 100644
--- a/capture.py
+++ b/capture.py
@@ -305,7 +305,8 @@ class FunctionBreakpoint(gdb.Breakpoint, representation.Filterable):
             ret = None
             mcgdb.toolbox.callback_crash("FunctionBreakpoint.prepare_before", e)
             
-        if ret is None: return False #spurious stop
+        if ret is None: #spurious stop
+            return interaction.proceed_stop_requests()
 
         (fct_stop, fct_finish, fct_data) = ret
 
diff --git a/interaction/aspect.py b/interaction/aspect.py
index 4dd97732e73cd1e1a6a6df4ed9539aab79b1be28..0a6bdb1da4840c1264c8c3abb29b6d01a504f908 100644
--- a/interaction/aspect.py
+++ b/interaction/aspect.py
@@ -18,7 +18,7 @@ class cmd_aspect_remove(gdb.Command):
         gdb.Command.__init__ (self, "mcgdb aspects remove", gdb.COMMAND_NONE)
         
     def invoke (self, argv, from_tty):
-        if "all" == argv:
+        if argv.startswith("all"):
             aspect.registered_trackers.clear()
             print("All aspects removed.")
             return
diff --git a/interaction/my_gdb.py b/interaction/my_gdb.py
index 05d0c33d346c4d1bb4f2524a3852b7a7c3c80886..cfadcaeab841b5594f461e8c3e8b43ef17497cb2 100644
--- a/interaction/my_gdb.py
+++ b/interaction/my_gdb.py
@@ -214,7 +214,16 @@ class cmd_mcgdb_load_by_name(gdb.Command):
     
     def invoke (self, args, from_tty):
         toolbox.load_models_by_name(args)
-            
+
+class cmd_mcgdb_load_by_library(gdb.Command):
+    def __init__(self):
+        gdb.Command.__init__ (self, "mcgdb load_model_by_libname", gdb.COMMAND_NONE)
+    
+    def invoke (self, args, from_tty):
+        class objfile:
+            filename = args
+        toolbox.detect_models(objfile)
+        
 class cmd_mcgdb_detect(gdb.Command):
     def __init__(self):
         gdb.Command.__init__ (self, "mcgdb detect_models", gdb.COMMAND_NONE)
@@ -280,6 +289,7 @@ def postInitialize():
     cmd_mcgdb_autodetect()
     cmd_mcgdb_detect()
     cmd_mcgdb_load_by_name()
+    cmd_mcgdb_load_by_library()
     
     gdb.events.cont.connect(cont)
     
diff --git a/model/__init__.py b/model/__init__.py
index 286095f01540d33999d845cfbde62b68dfadaa87..5891cdd4cb866044432f9f1f2effe83af2628f26 100644
--- a/model/__init__.py
+++ b/model/__init__.py
@@ -1,138 +1,2 @@
-from . import gpu, task, profiling, aftermath
+from . import gpu, task, profiling, numa
 
-    
-import gdb
-import mcgdb
-from mcgdb.toolbox.target import my_archi
-from mcgdb.toolbox import my_gdb
-
-# class kmpc_barrier_Breakpoint(mcgdb.capture.FunctionBreakpoint):
-#     func_type = mcgdb.capture.FunctionTypes.conf_func
-    
-#     def __init__(self):
-#         mcgdb.capture.FunctionBreakpoint.__init__(self, "__kmpc_for_static_init_4")
-
-#     def prepare_before (self):
-#         data = {}
-#         data["lower"] = my_archi.nth_arg(5, my_archi.INT_P)
-#         data["upper"] = my_archi.nth_arg(6, my_archi.INT_P)
-
-#         return (False, True, data)
-
-#     def prepare_after (self, data):
-#         lower, upper = data["lower"].dereference(), data["upper"].dereference()
-
-#         if lower == 84:
-#             print("ITER FAST to 86: {} -- {}".format(lower, upper))
-#             return True
-#         if lower == 312:
-#             print("ITER SLOW to 314: {} -- {}".format(lower, upper))
-#             return True
-     
-# class cmd_do_break (gdb.Command):
-#     def __init__ (self):
-#         gdb.Command.__init__ (self, "do_break", gdb.COMMAND_NONE)
-
-#     def invoke (self, args, from_tty):
-#         kmpc_barrier_Breakpoint()
-#         print("Breakpoint set on slow and fast iterations")
-        
-# cmd_do_break()
-
-# class cmd_do_measure (gdb.Command):
-#     def __init__ (self):
-#         gdb.Command.__init__ (self, "do_measure", gdb.COMMAND_NONE)
-
-#     def invoke (self, args, from_tty):
-#         gdb.execute("set scheduler-locking on")
-#         gdb.execute("tbreak __kmpc_for_static_fini")
-#         gdb.execute("profile manual start")
-#         gdb.execute("cont")
-#         gdb.execute("profile manual stop")
-#         gdb.execute("set scheduler-locking off")
-# cmd_do_break()
-# cmd_do_measure()
-
-import mcgdb.interaction
-
-class kmpc_for_static_Breakpoint(mcgdb.capture.FunctionBreakpoint):
-    func_type = mcgdb.capture.FunctionTypes.conf_func
-    
-    def __init__(self):
-        mcgdb.capture.FunctionBreakpoint.__init__(self, "__kmpc_for_static_init_4")
-    def prepare_before (self):
-        data = {}
-        data["lower"] = my_archi.nth_arg(5, my_archi.INT_P)
-        data["upper"] = my_archi.nth_arg(6, my_archi.INT_P)
-
-        return (False, True, data)
-
-    def prepare_after (self, data):
-        lower, upper = data["lower"].dereference(), data["upper"].dereference() #spurious stop 
-        print("Execute loop {} == {}".format(lower, upper))
-        
-        gdb.execute("set scheduler-locking on")
-        gdb.execute("profile manual start")
-
-total = None
-hits = 0
-has_hit = False
-class kmpc_for_fini_Breakpoint(mcgdb.capture.FunctionBreakpoint):
-    func_type = mcgdb.capture.FunctionTypes.conf_func
-    
-    def __init__(self):
-        mcgdb.capture.FunctionBreakpoint.__init__(self, "__kmpc_for_static_fini")
-
-    def prepare_before (self):
-        gdb.execute("profile manual stop")
-        gdb.execute("set scheduler-locking off")
-
-        global hits
-        hits += 1
-
-        do_stop = hits == total
-        if do_stop:
-            print("FINISHED")
-
-        if has_hit:
-            do_stop = True
-            has_hit = False
-            
-        if mcgdb.interaction.stop_requests:
-            print("---> {}".format(mcgdb.interaction.stop_requests))
-            global has_hit
-            has_hit = True
-
-        return do_stop, False, {}
-    
-class cmd_measure_all(gdb.Command):
-    def __init__ (self):
-        gdb.Command.__init__ (self, "measure_all", gdb.COMMAND_NONE)
-
-    def invoke (self, args, from_tty):
-        kmpc_for_static_Breakpoint()
-        kmpc_for_fini_Breakpoint()
-        global total
-        total = len(gdb.selected_inferior().threads())
-        
-cmd_measure_all()
-
-import os
-class cmd_pagemap(gdb.Command):
-    def __init__ (self):
-        gdb.Command.__init__ (self, "pagemap", gdb.COMMAND_NONE)
-    def invoke (self, args, from_tty):
-        addr = gdb.parse_and_eval(args)
-        os.system("/home/videau/pagemap -n {} {}".format(gdb.selected_inferior().pid, addr))
- 
-cmd_pagemap()
-
-
-class cmd_current_numa_node(gdb.Command):
-    def __init__ (self):
-        gdb.Command.__init__ (self, "current_numa_node", gdb.COMMAND_NONE)
-        
-    def invoke (self, args, from_tty):
-        with my_gdb.set_parameter("scheduler-locking", "on"):
-            gdb.execute("p numa_node_of_cpu(sched_getcpu())")
-cmd_current_numa_node()
diff --git a/model/numa/__init__.py b/model/numa/__init__.py
index 45ac7d8f05357a6912b44f5b2735e166f91b9703..07a9fd14609f72f55186c0ff3f531e4afbc9eafc 100644
--- a/model/numa/__init__.py
+++ b/model/numa/__init__.py
@@ -7,13 +7,14 @@ import logging; log = logging.getLogger(__name__)
 log_user = logging.getLogger("mcgdb.log.user.numa")
 
 import os
+import subprocess
 
 try:
     import shutil
 except ImportError:
     shutil = None
 
-numa_loaded = False
+numa_loaded = None
 
 PAGEMAP_PATH = "/home/videau/"
 PAGEMAP = "pagemap"
@@ -22,14 +23,22 @@ pagemap_bin = None
 
 class cmd_numa_pagemap(gdb.Command):
     def __init__ (self):
-        gdb.Command.__init__ (self, "pagemap", gdb.COMMAND_NONE)
+        gdb.Command.__init__ (self, "numa pagemap", gdb.COMMAND_NONE)
         global pagemap_bin
-        pagemap_bin = PAGEMAP
-        
-        if (shutil and shutil.which(PAGEMAP) # > py3.3 
-            or "/{}".format(PAGEMAP) in os.system("which {}").format(PAGEMAP))):
-            # nothing to do, we found it
-        else:
+
+        has_pagepage = False
+        try:
+            has_pagepage = shutil.which(PAGEMAP) is not None  # > py3.3
+        except AttributeError: # py2: shutil doesn't have which
+            pass
+
+        if not has_pagepage:
+            try:
+                has_pagepage = "/{}".format(PAGEMAP) in subprocess.check_output("which {}".format(PAGEMAP), shell=True, stderr=subprocess.STDOUT)
+            except subprocess.CalledProcessError: # which returned false
+                pass
+                
+        if not has_pagepage:
             pagemap_path = os.path.join(PAGEMAP_PATH, PAGEMAP)
             
             if not os.path.isfile(pagemap_path):
@@ -39,9 +48,21 @@ class cmd_numa_pagemap(gdb.Command):
                 pagemap_bin = pagemap_path
                 
     def invoke (self, args, from_tty):
-        addr = gdb.parse_and_eval(args)
-        os.system("{} -n {} {}".format(pagemap_bin, gdb.selected_inferior().pid, addr))
+        try:
+            addr = gdb.parse_and_eval(args)
+        except gdb.error as e:
+            log_user.error("Cannot evaluate '{}': {}".format(args, e))
+            return
+        
+        cmd = "{} -n {} {}".format(pagemap_bin, gdb.selected_inferior().pid, addr)
+        res = subprocess.check_output(cmd, shell=True)
+        try:
+            pm_addr, _, node = res[:-1].split(" ")
 
+            log_user.info("Address 0x{} is located on node {}".format(pm_addr, node))
+        except ValueError: # couldnt split correctly
+            log_user.warn("Unexpected response from pagemap: '{}'".format(res[:-1]))
+            
 class cmd_numa_current_node(gdb.Command):
     def __init__ (self):
         gdb.Command.__init__ (self, "numa current_node", gdb.COMMAND_NONE)
@@ -49,12 +70,13 @@ class cmd_numa_current_node(gdb.Command):
     def invoke (self, args, from_tty):
         for symb in ("numa_node_of_cpu", "sched_getcpu"):
             if not gdb.lookup_symbol(symb):
-                log_user.error("Symbol '{}' not found, cannot get current node.".format(symb)
-                               return
+                log_user.error("Symbol '{}' not found, cannot get current node.".format(symb))
+                return
         
         with my_gdb.set_parameter("scheduler-locking", "on"):
-            gdb.execute("p numa_node_of_cpu(sched_getcpu())")
-
+            node = gdb.execute("p numa_node_of_cpu(sched_getcpu())", to_string=True)
+        node = int(node.partition("= ")[-1])
+        log_user.info("Current node is N{}".format(node))
 
 class cmd_numa(gdb.Command):
     def __init__(self, limited=False):
@@ -69,7 +91,7 @@ class cmd_numa(gdb.Command):
 
         on_activated()
         numa_loaded = True
-            
+        log_user.info("Numa module successfully loaded.")
         if args:
             gdb.execute("numa {}".format(args))
 
diff --git a/model/profiling/info/__init__.py b/model/profiling/info/__init__.py
index c5516cb255f4592efe0bd18e61b13ac41227231e..90beb366e4d67d505ee159366a46d1f11b6496a6 100644
--- a/model/profiling/info/__init__.py
+++ b/model/profiling/info/__init__.py
@@ -6,7 +6,7 @@ log_user = logging.getLogger("mcgdb.log.user")
 from mcgdb.toolbox import my_gdb
 
 # will be added to global scope
-info_counters = "proc", "hit", "counter", "perf", "gprof", "memleaks"
+info_counters = "perf_standalone", "omp" #"proc", "hit", "counter", "perf", "gprof", "memleaks"
 info_counter_classes = None # will be populated in initialize()
 disabled_counters = set()
 
@@ -26,6 +26,14 @@ class Info_set(list):
         for info in self:
             info.stop()
 
+    def get(self, key):
+        values = []
+        for info in self:
+            try:
+                values.append(info.results[key])
+            except KeyError: pass
+        return values
+            
 def new_infoset():
     counters = []
     for info_counter_class in info_counter_classes:
diff --git a/model/profiling/info/perf.py b/model/profiling/info/perf.py
index 62aba86c2dd6f08acfa054c2059b7b3da1f5e955..bdbe056850e442e274ad3020b10c2ea26f42faf9 100644
--- a/model/profiling/info/perf.py
+++ b/model/profiling/info/perf.py
@@ -14,6 +14,11 @@ from .. import capture
 MCGDB_PATH = "/home/kevin/travail/Python/mcgdb"
 PREF_LD_PRELOAD = MCGDB_PATH+ "/model/profiling/__binaries__/libmcgdb_perf_stat.preload.so"
 
+try: # Python 3 standard library.
+    ProcessLookupError
+except NameError: # No such class in Python 2.
+    ProcessLookupError = NotImplemented
+
 class perf_process():
     UNITS = {"task-clock": "msec"}
     
@@ -57,6 +62,7 @@ class perf_process():
         log.error("Attach perf to process {}".format(pid))
         command = ['perf', 'stat', '-x;',
                    #'--pre', "kill -USR1 {}".format(os.getpid()),
+                   '-e', profile.interaction.counters.param_perf_counters.get(),
                    '-p', str(pid),
                    #'sleep', '999999999' # otherwise pref stat --pre returns immediatly
                    ]
@@ -297,8 +303,9 @@ class perf_info_ldpreload():
         return results
     
 def initialize():
-    capture.exec_at_main.append(perf_process.launch)
-    capture.exec_at_exit.append(perf_process.kill)
-    capture.exec_on_exited.append(perf_process.kill)
+    #capture.exec_at_main.append(perf_process.launch)
+    #capture.exec_at_exit.append(perf_process.kill)
+    #capture.exec_on_exited.append(perf_process.kill)
+    pass
 
-__COUNTERS__ = [perf_info_ldpreload]
+__COUNTERS__ = [] # perf_info_ldpreload
diff --git a/model/profiling/info/perf_standalone.py b/model/profiling/info/perf_standalone.py
index 7989990f4b41112ec621c474432dd2d2d703c944..dba3ef9baf846e8ad95fe660dfd67a22346836b0 100644
--- a/model/profiling/info/perf_standalone.py
+++ b/model/profiling/info/perf_standalone.py
@@ -1,6 +1,26 @@
+import subprocess
+import signal
+import time
+from collections import defaultdict, OrderedDict
+
+import logging; log = logging.getLogger(__name__)
+log_user = logging.getLogger("mcgdb.log.user")
+
+import gdb
+
+from ..interaction import counters
+
+DISABLE_STARTUP_SYNC = False
+MAX_WAIT = 5 # in 1/10 s
+HAS_PERF_SIGNAL = False # need to test version
+
+if DISABLE_STARTUP_SYNC:
+    log.warn("No startup sync between perf and mcgdb")
+
 class perf_info_standalone():
     "perf stat counters (standalone)"
     name = "perf standalone"
+    UNITS = {"task-clock": "msec"}
     
     def __init__(self):
         self.perf = None
@@ -11,39 +31,45 @@ class perf_info_standalone():
         assert self.perf is None
 
         self.rcvd = False
-        def handler(signum, frame):
+        
+        if DISABLE_STARTUP_SYNC:
             self.rcvd = True
+        else:
+            def handler(signum, frame):
+                self.rcvd = True
             
-        import signal, time, os
-        old = signal.signal(signal.SIGUSR1, handler)
-        
+            import signal, time, os
+            old = signal.signal(signal.SIGUSR1, handler)
+
         command = ['perf', 'stat', '-x,',
-                   '--pre', "kill -USR1 {}".format(os.getpid()),
-                   '-p', str(gdb.selected_inferior().pid),
-                   'sleep', '999999999' # otherwise pref stat --pre returns immediatly
+                   '-e', counters.param_perf_counters.get()
                    ]
-        self.perf = subprocess.Popen(command,
-                                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        
+        if HAS_PERF_SIGNAL:
+             # not working with old versions of perf
+            command += ['--pre', "kill -USR1 {}".format(os.getpid())]
+        command += [  #'-p', str(gdb.selected_inferior().pid),
+            '-p', str(gdb.selected_thread().ptid[1]),
+            'sleep', '999999999' # otherwise pref stat --pre returns immediatly
+                      ]
+        self.perf = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         self.res = "running"
         assert self.perf.pid > 1
 
-        MAX_WAIT = 100
-        cnt = MAX_WAIT
-        for cnt in range(MAX_WAIT):
-            if self.rcvd: break
-            time.sleep(0.1)
+        if not DISABLE_STARTUP_SYNC:
+            cnt = MAX_WAIT
+            for cnt in range(MAX_WAIT):
+                if self.rcvd: break
+                time.sleep(0.1)
 
-        signal.signal(signal.SIGUSR1, old)
+            signal.signal(signal.SIGUSR1, old)
         
-        if not self.rcvd:
-            #log.error("Waited to long for perf ...")
-            pass
+            if not self.rcvd and HAS_PERF_SIGNAL:
+                #log.error("Waited to long for perf ...")
+                pass
             
     def stop(self):
         assert not self.perf.returncode
-        
-        #self.perf.send_signal(signal.SIGINT)
-        
         sleep_pid = subprocess.Popen(["pgrep", "-P", str(self.perf.pid)],
                                      stdout=subprocess.PIPE).stdout.read().decode('ascii')
         subprocess.Popen(["kill", "-INT", sleep_pid[:-1]],
@@ -62,7 +88,8 @@ class perf_info_standalone():
             try:
                 self.results[k] += v
             except TypeError:
-                #log.error("Cannot add '{}' to '{}'.".format(v, self.results[k]))
+                log.error("Cannot add '{}' to '{}'.".format(v, self.results[k]))
+                import pdb;pdb.set_trace()
                 self.results[k] = "{}/{}".format(self.results[k], v)
             
     def reset(self):
@@ -84,7 +111,7 @@ class perf_info_standalone():
         info = OrderedDict()
         for k, val in self.results.items():
             try:
-                details = perf_info.UNITS[k]
+                details = perf_info_standalone.UNITS[k]
             except KeyError:
                 details = ""
             
@@ -101,15 +128,30 @@ class perf_info_standalone():
             if "sleep" in line:
                 log.critical("is this line really expected? {}".format(line))
             try:
-                val, _1, desc, _2, pct = line.split(",")
-                line = None if val == '<not counted>' \
-                    else float(val) #, "({}% -- {} -- {})".format(pct, _1, _2)
+                line_split = line.split(",")
+                if len(line_split) == 2:
+                    # old perf versions
+                    val, desc = line_split
+                else:
+                    # new versions
+                    val, _1, desc, _2, pct = line_split
+
+                if val == '<not counted>':
+                    line = None
+                elif "." in val:
+                    val = float(val)
+                elif val.isdigit():
+                    val = int(val)
+                else:
+                    pass
+      
             except Exception as e:
+                import pdb;pdb.set_trace()
                 desc = line
-                line = str(e) #, ""
+                val = str(e) #, ""
                 
-            results[desc] = line
+            results[desc] = val
             
         return results
 
-__COUNTERS__ = []
+__COUNTERS__ = [perf_info_standalone]
diff --git a/model/profiling/interaction/__init__.py b/model/profiling/interaction/__init__.py
index 78ee3e65a03190d5ea9ff8ea19f3826fcbe34018..e8c96535704215a4e866363ff2481d94f304b51c 100644
--- a/model/profiling/interaction/__init__.py
+++ b/model/profiling/interaction/__init__.py
@@ -3,7 +3,8 @@ log_user = logging.getLogger("mcgdb.log.user")
 
 import gdb
 
-from . import graph, manual, info, manage, profile, summary, graph_offline
+from . import graph, manual, info, manage, profile, summary, break_if
+from . import counters, graph_offline
 
 def initialize():    
     gdb.Command("profile", gdb.COMMAND_OBSCURE, prefix=True)
diff --git a/model/profiling/interaction/break_if.py b/model/profiling/interaction/break_if.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1e600959224cdbd8887c055b4b5b8a24653c989
--- /dev/null
+++ b/model/profiling/interaction/break_if.py
@@ -0,0 +1,49 @@
+import logging; log = logging.getLogger(__name__)
+log_user = logging.getLogger("mcgdb.log.user")
+
+import gdb
+from mcgdb.toolbox import my_gdb
+profile = None # resolved in initialize()
+
+class cmd_profile_break (gdb.Command):
+    def __init__ (self):
+        gdb.Command.__init__(self, "profile break", gdb.COMMAND_OBSCURE, prefix=True)
+
+    def invoke (self, args, from_tty):
+        if args == "clear":
+            profile.Profile.breakpoints[:] = []
+            
+            log_user.info("Profiling breakpoints cleared")
+            return
+        elif args.startswith("del"):
+            log_user.warn("Not implemented yet ...")
+            return
+        elif not args:
+            for i, (cpt, cmpt, val) in enumerate(profile.Profile.breakpoints):
+                print("#{} {} {} {}".format(i, cpt, cmpt, val))
+            return
+        
+class cmd_profile_break_if (gdb.Command):
+    def __init__ (self):
+        gdb.Command.__init__(self, "profile break if", gdb.COMMAND_OBSCURE)
+        
+    def invoke (self, args, from_tty):
+        try:
+            cpt, cmpt, val = args.split(" ")
+            val = float(val) if "." in val else int(val)
+            assert cmpt in ("==", "<", ">")
+        except ValueError:
+            log.warn("Argument format invalid. Expected '<cpt name> <comparator> <value>'")
+            return
+        
+        profile.Profile.breakpoints.append((cpt, cmpt, val))
+        
+        log_user.info("Profiling breakpoint set on {}.".format(args))
+        
+@my_gdb.internal
+def initialize():
+    global profile
+    from .. import profile
+    
+    cmd_profile_break()
+    cmd_profile_break_if()
diff --git a/model/profiling/interaction/counters.py b/model/profiling/interaction/counters.py
new file mode 100644
index 0000000000000000000000000000000000000000..78c8b6fd5e9c6d301de90414c175935ca540eb78
--- /dev/null
+++ b/model/profiling/interaction/counters.py
@@ -0,0 +1,30 @@
+import gdb
+
+DEFAULT = "instructions,cycles,task-clock"
+class param_perf_counters(gdb.Parameter):
+    __self = None
+
+    @classmethod
+    def get(clazz):
+        try:
+            return clazz.__self.value
+        except ValueError:
+            # not initialized
+            return DEFAULT
+    
+    def __init__ (self):
+        gdb.Parameter.__init__(self, "profile-perf-counters",
+                               gdb.COMMAND_OBSCURE,
+                               gdb.PARAM_STRING)
+        self.value = DEFAULT
+        assert param_perf_counters.__self is None
+        param_perf_counters.__self = self
+        
+    def get_set_string(self):
+        return "perf profiling counters set to '{}'".format(self.value)
+        
+    def get_show_string (self, svalue):
+        return "perf profiling counters are '{}'".format(svalue)
+
+def initialize():
+    param_perf_counters()
diff --git a/model/profiling/interaction/graph.py b/model/profiling/interaction/graph.py
index e0bf032c3d38e5e226f545330924311179028458..4d6de6b9a06eb20690fa39efc443aaa54efb69ee 100644
--- a/model/profiling/interaction/graph.py
+++ b/model/profiling/interaction/graph.py
@@ -289,3 +289,55 @@ def initialize():
     from .. import profile
     
     cmd_profile_graph()
+    cmd_profile_offline_graph()
+
+class  cmd_profile_offline_graph(gdb.Command):
+    def __init__ (self):
+        gdb.Command.__init__(self, "profile graph offline", gdb.COMMAND_OBSCURE, prefix=True)
+        
+    def invoke (self, args, from_tty):
+        import pygal
+
+        import fileinput
+
+        chart = pygal.Line()
+        names = []
+        do_div = False
+        
+        finput = fileinput.input()
+        for line in finput:
+            line = line[:-1]
+            
+            if not line:
+                finput.close()
+                break
+            
+            if line.endswith(" y2"):
+                secondary = True
+                line = line.replace(" y2", "")
+            elif line.endswith(" /"):
+                do_div = True
+                line = line.replace(" /", "")
+            else:
+                secondary = False
+
+            try:
+                name, values = line.split(" | ")
+            
+                cast = float if "." in values else int
+                values = list(map(cast, values.split(" ")))
+            except Exception as e:
+                log_user.warn("Parsing failed, the line above will be ignored ({})".format(e))
+                continue
+            if do_div is True:
+                do_div = values
+                continue
+            elif do_div:
+                values = [a/b for a, b in zip(values, do_div)]
+                
+            chart.add(name, values, secondary=secondary)
+            names.append(name)
+            
+        TARGET = '/tmp/chart.png'
+        chart.render_to_png(TARGET)
+        log_user.info("Chart of {} plotted into {}".format("/".join(names), TARGET))
diff --git a/model/profiling/interaction/summary.py b/model/profiling/interaction/summary.py
index 7d6c6abd57952a55b2483a72317c6a076fa53f96..b0464421a7477becaa0102306b9f7fcfc13f6a9d 100644
--- a/model/profiling/interaction/summary.py
+++ b/model/profiling/interaction/summary.py
@@ -129,9 +129,18 @@ class cmd_profile_info (gdb.Command):
                 log_user.info("***")
                 
         def print_a_set(info_set):
+            MAX_VALUE_LEN = 10
+            
             res = OrderedDict()
             for info in info_set:
-                res.update(info.to_log(ongoing))
+                results = info.to_log(ongoing)
+                if results is False:
+                    continue
+                res.update(results)
+                
+            if not res:
+                log_user.info("EMPTY")
+                return
 
             max_len = max(len(k) for k in res)
             for k, v in res.items():
@@ -146,15 +155,17 @@ class cmd_profile_info (gdb.Command):
                     str_val = commify(value)
                 else:
                     str_val = str(value)
+
+                padding_value = (MAX_VALUE_LEN - len(str_val.partition(".")[0])) * " "
                     
                 if isinstance(value, Unit):
-                    str_val += value.unit
+                    str_val += " " + value.unit
                     
                 if details:
                     str_val += " ({})".format(details)
                     
-                padding = (max_len - len(k)) * " "
-                log_user.info("".join([k, ": ", padding, str_val]))
+                padding_label = (max_len - len(k)) * " "
+                log_user.info("".join([k, ": ", padding_label, padding_value, str_val]))
                 
         if prof.do_first_last and firstlast:
             log_user.info("first start last stop")
@@ -214,16 +225,18 @@ class InfoEntrySummary():
         
     def avg(self, value, prof):
         if isinstance(value, str): return
+        
         try:
-            prev, it = self.values["avg"]
+            (prev, _what_), it = self.values["avg"]
             it += 1
-            # iterative mean http://www.heikohoffmann.de/htmlthesis/node134.html    
-            new =  + float(value) - prev + prev/it 
+            # iterative mean http://www.heikohoffmann.de/htmlthesis/node134.html
+            new = prev + float(value) - prev*1/it 
         except KeyError:  # first pass
             new = value
             it = 0
-        except:
+        except Exception as e:
             import pdb;pdb.set_trace()
+            return
         self.values["avg"] = new, it
             
 class cmd_profile_summ (gdb.Command):
diff --git a/model/profiling/profile.py b/model/profiling/profile.py
index 95b65d813386365d73552a03883747fff2bdedda..2bd95c15de98d7d37e0b9b66fbabf4977e298847 100644
--- a/model/profiling/profile.py
+++ b/model/profiling/profile.py
@@ -6,6 +6,7 @@ log_user = logging.getLogger("mcgdb.log.user")
 import gdb
 
 import mcgdb
+import mcgdb.interaction
 from mcgdb.toolbox import my_gdb
 from . import capture, info, interaction, checkpoint
 
@@ -44,7 +45,8 @@ class Profile_info():
 @my_gdb.Numbered
 class Profile():
     profiles = []
-
+    breakpoints = []
+    
     @classmethod
     def instanciate_info(clazz):
         return info.new_infoset()
@@ -136,9 +138,23 @@ class Profile():
         def firstlast():
             if self.per_thread.inside >= 1: 
                 return
-        
-            self.per_thread.firstlast.stop()
+
+            infoset = self.per_thread.firstlast
+            infoset.stop()
             
+
+            def need_to_stop():
+                
+                for cpt, cmpt, val in Profile.breakpoints:
+                    for res in infoset.get(cpt):
+                        if any([cmpt == "==" and res == val,
+                               cmpt == ">" and res > val,
+                               cmpt == "<" and res < val]): return cpt, cmpt, val
+            stop = need_to_stop()
+            if stop:
+                log_user.warn("Profiling breakpoint: Found {}".format(" ".join(map(str,stop))))
+                mcgdb.interaction.push_stop_request()
+                
         def per_fct():
             info_set = self.per_thread.per_fct_stack.pop()
             
diff --git a/model/task/environment/openmp/capture/__init__.py b/model/task/environment/openmp/capture/__init__.py
index 979bc789310555a1d722695e6e11699b20b5cf58..97098f4f5acb86b1d91da771deed81a49729c2d3 100644
--- a/model/task/environment/openmp/capture/__init__.py
+++ b/model/task/environment/openmp/capture/__init__.py
@@ -94,8 +94,12 @@ class OmpFramePragma(mcgdb.capture.FrameStripperDecorator):
 
         return "#pragma omp {}".format(fct[len(PREFIX):])
 
+
 class OmpFunctionBreakpoint(mcgdb.capture.FunctionBreakpoint):
+    breakpoint_sets = defaultdict(list)
+
     decorator = OmpFramePragma
+    omp_set = None
     
     def __init__(self, spec):
         try:
@@ -112,6 +116,14 @@ class OmpFunctionBreakpoint(mcgdb.capture.FunctionBreakpoint):
             spec = "iomp_preload.c:"+spec
             
         mcgdb.capture.FunctionBreakpoint.__init__(self, spec)
+
+        setname = self.__class__.omp_set
+        if setname is not None:
+            # if breakpoint is part of an enable-able set, disable it for now
+            
+            # try to slit based on spaces ?
+            OmpFunctionBreakpoint.breakpoint_sets[setname].append(self)
+            self.enabled = False
         
 class OmpGeneratedFrame(mcgdb.capture.FrameStripperDecorator):
     def __init__(self, parent):
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_barrier.py b/model/task/environment/openmp/capture/gomp/GOMP_barrier.py
index 7a56a70278124560a3a300a43ac00c6c44b1aee5..30b7ae594300bf61f00039f30f513b87f9555cad 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_barrier.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_barrier.py
@@ -19,6 +19,7 @@ def filename_lineno():
 
 class GOMP_barrier_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "barrier"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "GOMP_barrier")
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py b/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py
index 9ece83a6586eac17a860689f5389143a3c149506..780cd0ceea61933e22bb6b3f749269f3f045665d 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py
@@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint
 
 class GOMP_critical_start_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "critical"
     
     def __init__(self, named=False):
         OmpFunctionBreakpoint.__init__(self, "GOMP_critical_{}start".format("name_" if named else ""))
@@ -35,6 +36,7 @@ class GOMP_critical_start_Breakpoint(OmpFunctionBreakpoint):
         
 class GOMP_critical_end_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "critical"
     
     def __init__(self, named=False):
         OmpFunctionBreakpoint.__init__(self, "GOMP_critical_{}end".format("name_" if named else ""))
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py b/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py
index f4f675e0a85f8948c20212861e45890b484f1d23..58516876c6caf4d6751877602fff3e7f07bb547c 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py
@@ -14,6 +14,7 @@ from .. import OmpFunctionBreakpoint, omp_fct_to_job, get_omp_zone
 class GOMP_parallel_start_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
     inner_breakpoint = {}
+    omp_set = "parallel"
     
     def __init__(self, section=False, parallel=False):
         if section:
@@ -68,6 +69,7 @@ class GOMP_parallel_start_Breakpoint(OmpFunctionBreakpoint):
         
 class GOMP_parallel_end_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "parallel"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "GOMP_parallel_end")
@@ -89,7 +91,8 @@ class GOMP_parallel_end_Breakpoint(OmpFunctionBreakpoint):
         
 class GOMP_parallel_function_Breakpoint(mcgdb.capture.FunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "parallel"
+    
     def __init__(self, fn, job, creator):
         addr = "*"+str(fn).split(" ")[0]
         mcgdb.capture.FunctionBreakpoint.__init__(self, addr)
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py b/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py
index f5d8132a6fc67261e626a2de3be3c8646a64deb1..6365d4152a60bdc91920ee7d417575eea8836f1a 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py
@@ -11,7 +11,8 @@ from . import GOMP_parallel_start_end
 
 class GOMP_sections_start_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "sections"
+    
     def __init__(self):        
         OmpFunctionBreakpoint.__init__(self, "GOMP_sections_start")
 
@@ -35,7 +36,8 @@ class GOMP_sections_start_Breakpoint(OmpFunctionBreakpoint):
 
 class GOMP_sections_end_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "sections"
+    
     def __init__(self, no_wait=False):        
         OmpFunctionBreakpoint.__init__(self,
                    "GOMP_sections_end{}".format("_nowait" if no_wait else ""))
@@ -59,7 +61,8 @@ class GOMP_sections_end_Breakpoint(OmpFunctionBreakpoint):
         
 class GOMP_sections_next_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "sections"
+    
     def __init__(self):        
         OmpFunctionBreakpoint.__init__(self, "GOMP_sections_next")
 
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_single_start.py b/model/task/environment/openmp/capture/gomp/GOMP_single_start.py
index d4d64d8f89e2ee7e9af210affb755aa86742f339..d550080af9f43700eba4bd46e90696dec67a4c1b 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_single_start.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_single_start.py
@@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint
 
 class GOMP_single_start_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "single"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "GOMP_single_start")
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_task.py b/model/task/environment/openmp/capture/gomp/GOMP_task.py
index acdf8bdb06345271190e8313cd9e963c2fb95846..6fd67b08f56df5e4949f25b65498801d58bcce3d 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_task.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_task.py
@@ -15,7 +15,8 @@ from .. import parse_omp_dependencies
 
 class GOMP_task_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "task"
+    
     task_ptr_to_task = {}
     current_per_thread = {}
     
@@ -40,6 +41,7 @@ class GOMP_task_Breakpoint(OmpFunctionBreakpoint):
 
 class gomp_init_task_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "task deps"
     
     def set_dependencies(self, task, depend):
         NDEPEND_IDX, NOUT_IDX, DEP_OFFSET = range(3)
@@ -145,6 +147,7 @@ class gomp_init_task_Breakpoint(OmpFunctionBreakpoint):
     
 class GOMP_task_function_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "task"
     
     def __init__(self, addr, fct_name):
         OmpFunctionBreakpoint.__init__(self, addr)
diff --git a/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py b/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py
index 58f9db16d15ba58e40ed20372f64f4542185e4f4..1305c818819e765247f92b95dc4030c063c71ac3 100644
--- a/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py
+++ b/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py
@@ -14,6 +14,7 @@ from .. import current_worker
 
 class GOMP_taskwait_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "task deps"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "GOMP_taskwait")
diff --git a/model/task/environment/openmp/capture/gomp/libgomp b/model/task/environment/openmp/capture/gomp/libgomp
deleted file mode 120000
index 26e79e954d84f98354c21b3524c309bddd477897..0000000000000000000000000000000000000000
--- a/model/task/environment/openmp/capture/gomp/libgomp
+++ /dev/null
@@ -1 +0,0 @@
-/usr/src/debug/gcc-5.1.1-20150422/libgomp
\ No newline at end of file
diff --git a/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py b/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py
index 6baee6939eb170024581b884a4d8d9d45deab3c8..283d3798bbd0128980030df86065532ea745c71b 100644
--- a/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py
+++ b/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py
@@ -8,7 +8,9 @@ from ... import representation
 from .. import current_worker, OmpFunctionBreakpoint, get_omp_zone
 
 handlers = {} # opm operation -> handler
-class omp_get_thread_num_Breakpoint(OmpFunctionBreakpoint):    
+class omp_get_thread_num_Breakpoint(OmpFunctionBreakpoint):
+    omp_set = "master"
+    
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "omp_get_thread_num")
 
@@ -19,6 +21,7 @@ class omp_get_thread_num_Breakpoint(OmpFunctionBreakpoint):
         return handler.prepare_before() if handler else None    
 
 class omp_master_Handler():
+    
     def prepare_before(self):
         if current_worker().number != 1:
             return None
diff --git a/model/task/environment/openmp/capture/iomp/__init__.py b/model/task/environment/openmp/capture/iomp/__init__.py
index 9948abb869fbb3804d46bfd6dfd1cc500c8b7e1a..a0dda602ac4b39e7a494a2dc4623105984c03754 100644
--- a/model/task/environment/openmp/capture/iomp/__init__.py
+++ b/model/task/environment/openmp/capture/iomp/__init__.py
@@ -13,18 +13,24 @@ def activate():
     main_worker = representation.Worker(gdb.selected_thread())
     gdb.selected_thread().name = str(main_worker)
 
-    log.critical("Activate OMPT task tracking")
-    gdb.execute("set ompt_status += ompt_status_track")
+    #log.critical("Activate OMPT task tracking")
+    #gdb.execute("set ompt_status += ompt_status_track")
+    
 # keep last to use objets above
-from . import \
-    kmpc_fork_call, \
-    kmpc_launch_worker, \
-    kmpc_barrier, \
-    kmpc_single, \
-    kmpc_critical, \
-    kmpc_omp_task, \
-    kmpc_for_static, \
-    kmpc_omp_taskwait, \
-    kmpc_master 
+from . import            \
+     kmpc_barrier,       \
+     kmpc_single,        \
+     kmpc_critical,      \
+     kmpc_omp_task,      \
+     kmpc_for_static,    \
+     kmpc_omp_taskwait,  \
+     kmpc_fork_call,     \
+     kmpc_launch_worker, \
+     kmpc_master
 
+log.warning("Many OpenMP feature disabled (hardcoded)")
+
+from . import  kmpc_for_static
+
+    
 from ..preload import omp_preload
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_barrier.py b/model/task/environment/openmp/capture/iomp/kmpc_barrier.py
index e16c93ece1e2261caf6c7463c4308203d6a7d262..f0547756bf8d4428d20becb1bbbd76a1bdf73850 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_barrier.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_barrier.py
@@ -21,6 +21,7 @@ def filename_lineno():
 
 class kmpc_barrier_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "barrier"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_barrier")
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_critical.py b/model/task/environment/openmp/capture/iomp/kmpc_critical.py
index e8065af2494b9b62a533633c51591b84758661a9..59985eba1ed55171272c9b74451e515cefda75b0 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_critical.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_critical.py
@@ -11,7 +11,8 @@ from .. import OmpFunctionBreakpoint
 
 class kmpc_critical_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-    
+    omp_set = "critical"
+
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_critical")
         
@@ -33,6 +34,7 @@ class kmpc_critical_Breakpoint(OmpFunctionBreakpoint):
         
 class kmpc_end_critical_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "critical"
     
     def __init__(self, named=False):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_end_critical")
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_for_static.py b/model/task/environment/openmp/capture/iomp/kmpc_for_static.py
index 19866c4117c3c9eb58e010e51556f22d35ce0df1..b799239d07b110e9d863467afd69850ebf00b8ea 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_for_static.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_for_static.py
@@ -1,5 +1,7 @@
 import gdb
 
+import logging; log = logging.getLogger(__name__)
+
 import mcgdb
 from mcgdb.toolbox.target import my_archi
 from mcgdb.toolbox import my_gdb
@@ -14,20 +16,23 @@ def ptr_to_int(ptr):
 
 class kmpc_for_static_init_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "loop static"
+    
     def __init__(self, _type="4u"):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_for_static_init_{}".format(_type))
 
     def prepare_before (self):
         data = {}
-        data["loc"] = my_gdb.add_to_num(my_archi.nth_arg(5, my_archi.VOID_P))
-        data["plower"] = my_archi.nth_arg(5, my_archi.INT)
-        data["pupper"] = my_archi.nth_arg(6, my_archi.INT)
-
+        #my_gdb.addr2num(my_archi.nth_arg(5, my_archi.VOID_P)) # should access loc->psource
+        data["loc"] = my_gdb.addr2num(gdb.newest_frame().older().read_register("pc"))
+        data["plower"] = my_archi.nth_arg(5, my_archi.INT_P)
+        data["pupper"] = my_archi.nth_arg(6, my_archi.INT_P)
+        data["incr"] = my_archi.nth_arg(8, my_archi.INT)
+        
         data["loop"] = representation.ForLoopJob.get_loop_at_loc(data["loc"],
                                                                  ptr_to_int(data["plower"]),
-                                                                 ptr_to_int(data["pupper"]))
-        
+                                                                 ptr_to_int(data["pupper"]),
+                                                                 data["incr"])
         return False, True, data
 
     def prepare_after(self, data):
@@ -38,28 +43,45 @@ class kmpc_for_static_init_Breakpoint(OmpFunctionBreakpoint):
         
 class kmpc_for_static_fini_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "loop static"
+    
     def __init__(self,):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_for_static_fini")
 
     def prepare_before (self):
         data = {}
-        worker = current_worker()
-        data["loop"] = loop = representation.ForLoopJob.get_current_loop_of(worker)
+        data["worker"] = worker = current_worker()
+        
+        data["loop"], data["iteration"] = loop, iteration \
+            = representation.ForLoopJob.get_current_loop_of(worker)
+        
+        if not loop:
+            log.warn("spurious end")
+            return
+        
         loop.stop_work_of(worker)
-
+        
         stop_after = loop.break_after_next
         loop.break_after_next = False
-        
+
+        data["old-scheduler-locking"] = gdb.parameter("scheduler-locking")
+        if stop_after:
+            gdb.execute("set scheduler-locking on")
+            
         return False, stop_after, data
         
     def prepare_after(self, data):
-        iteration = loop.working
-        log_user.info("Stopped after loop {} iteration {}-{}.".format(loop, iteration[0], iteration[1]))
+        gdb.execute("set scheduler-locking {}".format(data["old-scheduler-locking"]))
+        log.warn("Stopped in worker {} after loop {} iteration {}-{}.".format(
+                data["worker"],
+                data["loop"],
+                data["iteration"][0],
+                data["iteration"][1]))
         
         return True
 
         
 def activate():
-    kmpc_for_static_init_Breakpoint()
+    kmpc_for_static_init_Breakpoint(_type="4u")
+    kmpc_for_static_init_Breakpoint(_type="4")
     kmpc_for_static_fini_Breakpoint()
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py b/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py
index f8cfb2d09a7660955e2de0d4347a91af77776925..191b8f5b2632f29456cd1bac4fd8aa22b72b90d5 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py
@@ -12,6 +12,8 @@ from .. import OmpFunctionBreakpoint
 
 class kmpc_fork_call_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "parallel"
+    
     inner_breakpoint = {}
     
     def __init__(self):
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_master.py b/model/task/environment/openmp/capture/iomp/kmpc_master.py
index 92f79935f2631d49f71ae823bdb5f1e39added24..ec2509b20d70572562f92f20a7d147eb9dc585cb 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_master.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_master.py
@@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint
 
 class kmpc_master_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "master"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_master")
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py b/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py
index eb41ce283d4978d51747831c08310452701f23b1..2d34f66866b83d4f7735fa96d2e15163bbe17ccd 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py
@@ -16,6 +16,7 @@ HANDLE_TO_TASK = {}
 
 class kmp_check_deps_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "task deps"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmp_check_deps")
@@ -73,6 +74,7 @@ class kmp_check_deps_Breakpoint(OmpFunctionBreakpoint):
     
 class kmpc_omp_task_alloc_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "task"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_omp_task_alloc")
@@ -111,7 +113,8 @@ class kmpc_omp_task_alloc_Breakpoint(OmpFunctionBreakpoint):
         
 class kmpc_task_function_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
-
+    omp_set = "task"
+    
     def __init__(self, fn):
         addr = str(fn).split("0x")[1]
         addr = "*0x"+str(addr).split(" ")[0]
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py b/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py
index 345bd62e824865dd38218bcf2acf3dcfcb941518..de776919e95a40456286b430d1ca7e139632d5ce 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py
@@ -14,6 +14,7 @@ from .. import current_worker
 
 class kmpc_taskwait_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "task deps"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_omp_taskwait")
diff --git a/model/task/environment/openmp/capture/iomp/kmpc_single.py b/model/task/environment/openmp/capture/iomp/kmpc_single.py
index e5a277e17bd60f323054a9c37b6b25ee0115a40f..8bd0d1d7bbf1711e99d44776487ab7844de89bf9 100644
--- a/model/task/environment/openmp/capture/iomp/kmpc_single.py
+++ b/model/task/environment/openmp/capture/iomp/kmpc_single.py
@@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint
 
 class kmpc_single_Breakpoint(OmpFunctionBreakpoint):
     func_type = mcgdb.capture.FunctionTypes.conf_func
+    omp_set = "single"
     
     def __init__(self):
         OmpFunctionBreakpoint.__init__(self, "__kmpc_single")
diff --git a/model/task/environment/openmp/interaction/__init__.py b/model/task/environment/openmp/interaction/__init__.py
index 418e14dbf44ce3cf5740833dd5177c1503f38c09..0f5cc998b1ae1286bac282278867840aff1d49e8 100644
--- a/model/task/environment/openmp/interaction/__init__.py
+++ b/model/task/environment/openmp/interaction/__init__.py
@@ -4,14 +4,20 @@ import mcgdb
 
 representation = None
 
-from . import  step, show, \
-    graph, sequence, info, start, all_out, \
-    task, critical, barrier, sections, \
-    attach, stacktree, loop
+from . import enable
 
-from . import ayudame_wrapper, ayudame_preload
-from . import graph
+# from . import  step, show, \
+#     graph, sequence, info, start, all_out, \
+#     task, critical, barrier, sections, \
+#     attach, stacktree
 
+from . import info
+
+from . import loop
+
+# from . import ayudame_wrapper, ayudame_preload
+# from . import graph
+        
 def activate():
     global representation
     from .. import representation
@@ -41,7 +47,7 @@ class cmd_omp_debug (gdb.Command):
     def invoke (self, args, from_tty):
         activate = "on" in args
 
-        print("omp debugging activated: {}".format(activate))
+        print("OMP debugging activated: {}".format(activate))
         from .. import toolbox
         toolbox.NO_PRINT = not activate
 
diff --git a/model/task/environment/openmp/interaction/enable.py b/model/task/environment/openmp/interaction/enable.py
new file mode 100644
index 0000000000000000000000000000000000000000..97a809901c24ec0105c85c864e0a18f53b6010ee
--- /dev/null
+++ b/model/task/environment/openmp/interaction/enable.py
@@ -0,0 +1,68 @@
+import logging; log = logging.getLogger(__name__)
+log_user = logging.getLogger("mcgdb.log.user")
+
+import gdb
+
+representation = None
+capture = None
+
+def activate():
+    global representation, capture
+    from .. import representation
+    from .. import capture
+    
+    cmd_omp_enable()
+    cmd_omp_disable()
+    
+class cmd_omp_enable (gdb.Command):
+    enabled = []
+
+    def __init__ (self):
+        gdb.Command.__init__(self, "omp enable", gdb.COMMAND_OBSCURE)
+        
+    def invoke (self, args, from_tty):
+        disabled = [s for s in capture.OmpFunctionBreakpoint.breakpoint_sets.keys() if s not in cmd_omp_enable.enabled]
+        
+        found = True
+        if args and not args in disabled:
+            log_user.info("Cannot find '{}' breakpoint sets.".format(args))
+            found = False
+        if not found or not args:
+            log_user.info("Sets that can be enabled: {}".format(", ".join(disabled)))                          
+            return
+
+        for bpt in capture.OmpFunctionBreakpoint.breakpoint_sets[args]:
+            bpt.enabled = True
+            log_user.info("Enabling {}@{}...".format(bpt.__class__.__name__, bpt.location))
+            
+        assert args not in cmd_omp_enable.enabled
+        cmd_omp_enable.enabled.append(args)
+
+    def complete (self, text, word):
+        disabled = [s for s in capture.OmpFunctionBreakpoint.breakpoint_sets.keys() if s not in cmd_omp_enable.enabled]
+
+        return [setname for setname in disabled if setname.startswith(word)]
+
+class cmd_omp_disable (gdb.Command):
+
+    def __init__ (self):
+        gdb.Command.__init__(self, "omp disable", gdb.COMMAND_OBSCURE)
+        
+    def invoke (self, args, from_tty):
+        found = True
+        if args and not args in cmd_omp_enable.enabled:
+            log_user.info("Cannot find '{}' breakpoint sets.".format(args))
+            found = False
+        if not found or not args:
+            log_user.info("Sets that can be disabled: {}".format(", ".join(cmd_omp_enable.enabled)))
+            return
+
+        for bpt in capture.OmpFunctionBreakpoint.breakpoint_sets[args]:
+            bpt.enabled = False
+            log_user.info("Disabling {}@{}...".format(bpt.__class__.__name__, bpt.location))
+            
+        assert args in cmd_omp_enable.enabled
+        cmd_omp_enable.enabled.remove(args)
+        
+    def complete (self, text, word):
+       return [setname for setname in cmd_omp_enable.enabled if setname.startswith(word)]
diff --git a/model/task/environment/openmp/interaction/graph.py b/model/task/environment/openmp/interaction/graph.py
index b5cf4900f8379cf7413a4a77b5e0091dd17584d2..134c6563cdb5a14c25d2e5fe44d017df95c81db4 100644
--- a/model/task/environment/openmp/interaction/graph.py
+++ b/model/task/environment/openmp/interaction/graph.py
@@ -47,6 +47,7 @@ def activate():
     
     try:
         import networkx as nx # https://pypi.python.org/pypi/networkx/
+        import matplotlib as mpl ; mpl.use('Agg') # Force matplotlib/nx to not use any Xwindows backend.
         #import pygraphviz as pgv # https://pygraphviz.github.io/
     except ImportError as e:
         log.warning("Could not initialize {} package: '{}'".format(__name__, e))
diff --git a/model/task/environment/openmp/interaction/loop.py b/model/task/environment/openmp/interaction/loop.py
index ca4ccb968a6eb7be42e16c2f95467fe7d22514f9..eb8f1f9bf18e788d4caad86f4496273690a7bc51 100644
--- a/model/task/environment/openmp/interaction/loop.py
+++ b/model/task/environment/openmp/interaction/loop.py
@@ -1,6 +1,11 @@
 import gdb
 
+import logging; log = logging.getLogger(__name__)
+log_user = logging.getLogger("mcgdb.log.user")
+
 from mcgdb.toolbox import my_gdb
+from mcgdb.toolbox import aspect
+import mcgdb.interaction
 
 representation = None
 current_worker = None
@@ -12,12 +17,13 @@ def activate():
 
     cmd_omp_loop()
     cmd_omp_loop_profile()
+    cmd_omp_loop_profile_iterations()
     cmd_omp_loop_last_range()
     cmd_omp_loop_break()
     cmd_omp_loop_break_after_next()
     
     aspect.register("loop-profile", loop_aspects)
-    
+
 class cmd_omp_loop (gdb.Command):
     def __init__ (self):
         gdb.Command.__init__(self, "omp loop", gdb.COMMAND_OBSCURE, prefix=True)
@@ -44,7 +50,7 @@ class cmd_omp_loop_break (gdb.Command):
 class cmd_omp_loop_break_after_next (gdb.Command):
     def __init__ (self):
         gdb.Command.__init__(self, "omp loop break after_next", gdb.COMMAND_OBSCURE, prefix=1)
-
+        
     def invoke (self, args, from_tty):
         last_loop = representation.ForLoopJob.get_last_loop()
 
@@ -52,58 +58,58 @@ class cmd_omp_loop_break_after_next (gdb.Command):
             log_user.warn("Could not find any last loop")
             return
 
-        action = "Enable" if not self.break_after_next else "Disable"
-            
-        log_user.info("{} break-after-next breakpoint on loop {}.".format(action, last_loop))
-        self.break_after_next = not self.break_after_next
+        action = "Enable" if not last_loop.break_after_next else "Disable"
+
+        log_user.info("{} break-after-next breakpoint on loop {}.".format(action, repr(last_loop)))
+        last_loop.break_after_next = not last_loop.break_after_next
+
+iteration_profiling_enabled = False
 
-profiling_enabled = False
 class cmd_omp_loop_profile (gdb.Command):
     def __init__ (self):
-        gdb.Command.__init__(self, "omp loop profile", gdb.COMMAND_OBSCURE, prefix=1)
+        gdb.Command.__init__(self, "omp loop profile", gdb.COMMAND_OBSCURE, prefix=True)
 
-    def invoke (self, args, from_tty):
-        global profiling_enabled
+    def invoke (self, arg, from_tty):
+        log_user.warn("Please specify what kind of profiling you want to do.")
         
-        profiling_enabled = not profiling_enabled
-        action = "enabled" if profiling_enabled else "disabled"
-
-        log_user.info("Loop profiling {}.".format(action))
-        
-        if not profiling_enabled and gdb.parameter("scheduler-locking") == "on":
-            gdb.execute("set scheduler-locking off")
-            log_user.info("Scheduler locking disabled.")
-
-class cmd_omp_loop_break_profile (gdb.Command):
+class cmd_omp_loop_profile_iterations (gdb.Command):
     def __init__ (self):
-        gdb.Command.__init__(self, "omp loop profile break", gdb.COMMAND_OBSCURE, prefix=1)
+        gdb.Command.__init__(self, "omp loop profile iterations", gdb.COMMAND_OBSCURE, prefix=1)
 
     def invoke (self, args, from_tty):
-        cpt, cmpt, val = args.split(" ")
+        global iteration_profiling_enabled
         
-        log_user.info("Breakpoint set on profile {}.".format(args))
+        iteration_profiling_enabled = not iteration_profiling_enabled
+        action = "enabled" if iteration_profiling_enabled else "disabled"
+
+        log_user.info("Loop iteration profiling {}.".format(action))
+        
+        if not iteration_profiling_enabled and gdb.parameter("scheduler-locking") == "on":
+            gdb.execute("set scheduler-locking off")
+            log_user.info("Scheduler locking disabled.")        
 
 def loop_aspects(Tracks):
     from .. import representation
     
-    @Tracks(representation.TaskJob)
+    @Tracks(representation.ForLoopJob)
     class ForLoopJob:
         def __init__(this):
-            print("start loop {}".format(this.self))
-            if profiling_enabled:
-                print("set scheduler locking")
+            pass
                 
         def start_work_on(this):
-            print("loop {} {}".format(this.args.lower, this.args.upper))
-            if profiling_enabled:
-                print("start profiling")
+            if iteration_profiling_enabled:
+                gdb.execute("set scheduler-locking on")
+                #print("START profiling {} {}".format(this.args.lower, this.args.upper))
+                gdb.execute("profile manual start")
                 
         def stop_work_of(this):
-            print("loop iteration done")
-            if profiling_enabled:
-                print("stop profiling")
+            if iteration_profiling_enabled:
+                gdb.execute("profile manual stop")
+                gdb.execute("set scheduler-locking off")
                 
         def done(this):
-            print("loop done")
-            if profiling_enabled:
-                print("set scheduler locking")
+            global iteration_profiling_enabled
+            
+            if iteration_profiling_enabled:
+                mcgdb.interaction.push_stop_request("Iteration profiling finished.")
+                iteration_profiling_enabled = False
diff --git a/model/task/environment/openmp/interaction/profile.py b/model/task/environment/openmp/interaction/profile.py
index 13e5b450889f1e26a38dc9269df789fe7e1d11d4..c6674e2cf1dd72a74f37dbda114692285d9dc300 100644
--- a/model/task/environment/openmp/interaction/profile.py
+++ b/model/task/environment/openmp/interaction/profile.py
@@ -1,3 +1,6 @@
+import logging; log = logging.getLogger(__name__)
+log_user = logging.getLogger("mcgdb.log.user.openmp.profile")
+
 import gdb
 
 from mcgdb.toolbox import my_gdb
@@ -15,4 +18,5 @@ class cmd_omp_profile (gdb.Command):
     def __init__ (self):
         gdb.Command.__init__(self, "omp profile", gdb.COMMAND_OBSCURE, prefix=True)
 
-        
+    def invoke (self, arg, from_tty):
+        log_user.warn("Please specify what kind of profiling you want to do.")
diff --git a/model/task/environment/openmp/representation.py b/model/task/environment/openmp/representation.py
index d362b7a7d67abcd5ba92b72462b4445229a6fafc..27fd45f31baf97a49a1020ec3d4521f498d43826 100644
--- a/model/task/environment/openmp/representation.py
+++ b/model/task/environment/openmp/representation.py
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
 import logging; log = logging.getLogger(__name__)
 from collections import OrderedDict
 
@@ -1035,12 +1033,12 @@ class TaskJob(Job):
 @my_gdb.Dicted
 class ForLoopJob(Job, aspect.Tracker):
     @staticmethod
-    def get_loop_at_loc(loc, lower, upper):
+    def get_loop_at_loc(loc, lower, upper, incr):
         try:
             return ForLoopJob.dict_[loc]
         except KeyError: pass
 
-        return ForLoopJob(loc, lower, upper)
+        return ForLoopJob(loc, lower, upper, incr)
     
     @staticmethod
     def get_last_loop():
@@ -1057,31 +1055,54 @@ class ForLoopJob(Job, aspect.Tracker):
             except KeyError:
                 pass
         return None, None
+
+    @staticmethod
+    def get_current_loop_of(worker):
+        loop, iteration = ForLoopJob.get_last_loop_of(worker)
+
+        # if we have a last loop, and it's not finished
+        if loop and iteration[-1]:
+            return loop, iteration
+        else:
+            return None, None
     
-    def __init__(self, loc, lower, upper):
+    def __init__(self, loc, lower, upper, incr):
         Job.__init__(self)
         ForLoopJob.init_dict(loc, self)
-
+        
         self.loc = loc
         self.lower = lower
-        self.upper == upper
-
+        self.upper = upper
+        self.incr = incr
+        
         self.working = {}
 
         self.break_after_next = False
+
+        self.work_remaining = int((upper - lower + 1)/incr) # +1 because of boundaries
+        self.workers_done = 0
         
     def start_work_on(self, worker, lower, upper):
         assert worker not in self.working
-
+        
         self.working[worker] = [lower, upper, True]
     
     def stop_work_of(self, worker):
         assert worker in self.working
         assert self.working[worker][-1] is True
         
-        self.working[worker] = False
+        self.working[worker][-1] = False
+        lower, upper = self.working[worker][:2]
 
+        self.work_remaining -= (upper - lower + 1) # +1 because of boundaries
+        
+        self.workers_done += 1
+        
+        if self.work_remaining == 0 and len(Worker.list_) == self.workers_done:
+            self.done()
+        
     def done(self):
+        print("LOOP {} done".format(self))
         pass
     
 class Init:
diff --git a/toolbox/my_gdb.py b/toolbox/my_gdb.py
index ac52bbbc6cec1c0a851dfff1e8ebf25dc4053865..81c903802874e7a387ae1ad43350955f61016524 100644
--- a/toolbox/my_gdb.py
+++ b/toolbox/my_gdb.py
@@ -907,6 +907,6 @@ def find_type(orig, name):
 def initialize():
     #gdb.events.new_objfile.connect(AllInfBreakpoint.handler_new_objfile)
     
-    log.warn("Signal handler NOT registered (commented out)")
+    log.warn("Signal handler NOT registered (hardcoded)")
     #signal.signal(signal.SIGINT, signal_handler)
     
diff --git a/toolbox/paje.py b/toolbox/paje.py
index 91a3a29ef621e91916e7b5b7e8f38c22b0007fd4..54401bd87c75f09f04493a52168481098b3000d9 100644
--- a/toolbox/paje.py
+++ b/toolbox/paje.py
@@ -211,6 +211,7 @@ class cmd_printPaje(gdb.Command):
     def invoke_limited(self, to_screen, to_file, tids):
       Event.feed_raw(to_file, tids)
 
+PAJE_ENABLED = False
 @my_gdb.internal
 def initialize():
   global tempfile, ctypes, ctypes, fcntl, initialized
@@ -218,6 +219,10 @@ def initialize():
   import ctypes
   import fcntl
 
+  if not PAJE_ENABLED:
+    log.warn("Paje tracing disabled (hardcoded).")
+    return
+  
   global poti_lib
   try:
     libc = ctypes.CDLL("libc.so.6")
@@ -229,8 +234,8 @@ def initialize():
     log_user.debug("Paje trace output enabled")
     initialized = True
   except Exception as e:
-    log.warn("Paje: Could *not* initialize Paje/libpoti tracing")
-    log.warn("Paje: Falling back on raw tracing.")
-    log.info(e)
+    log.warn("Could *not* initialize Paje/libpoti tracing")
+    log.warn("Falling back on raw tracing.")
+    log.warn(e)
     cmd_printPaje(limited=True)
     initialized = None
diff --git a/toolbox/python_utils.py b/toolbox/python_utils.py
index b4ca364d267f7a7171e13355d4327302d832fb52..bc44e038dc9cd2f500e3ce92180470aa92018a12 100644
--- a/toolbox/python_utils.py
+++ b/toolbox/python_utils.py
@@ -23,7 +23,8 @@ except ImportError:
 try:
     from profilehooks import profile as profile_decorator # https://github.com/mgedmin/profilehooks
 except ImportError as e:
-    log_import.error("Cannot import profilehooks package, mcgdb profiling will not be available. ({})".format(e))
+    log.warning("Cannot import 'profilehooks' package, mcgdb profiling won't be available:")
+    log.warning(e)
     profile_decorator = None
 
 DO_PROFILE = False