xref: /llvm-project/openmp/libompd/gdb-plugin/ompd/ompd_handles.py (revision f98ee40f4b5d7474fc67e82824bf6abbaedb7b1c)
1import ompdModule
2import imp
3
4
5class ompd_parallel(object):
6    def __init__(self, parallel_handle):
7        """Initializes an ompd_parallel object with the pointer
8        to a handle of a parallel region."""
9        self.parallel_handle = parallel_handle
10        self.threads = {}
11        self.itasks = {}
12        self.enclosing_parallel_handle = None
13        self.enclosing_parallel = False
14        self.task_handle = None
15
16    def get_thread_in_parallel(self, thread_num):
17        """Obtains thread handles for the threads associated with the
18        parallel region specified by parallel_handle."""
19        if not thread_num in self.threads:
20            thread_handle = ompdModule.call_ompd_get_thread_in_parallel(
21                self.parallel_handle, thread_num
22            )
23            self.threads[thread_num] = ompd_thread(thread_handle)
24        return self.threads[thread_num]
25
26    def get_enclosing_parallel_handle(self):
27        """Obtains a parallel handle for the parallel region enclosing
28        the parallel region specified by parallel_handle."""
29        if not self.enclosing_parallel_handle:
30            self.enclosing_parallel_handle = (
31                ompdModule.call_ompd_get_enclosing_parallel_handle(self.parallel_handle)
32            )
33        return self.enclosing_parallel_handle
34
35    def get_enclosing_parallel(self):
36        if not self.enclosing_parallel:
37            self.enclosing_parallel = ompd_parallel(
38                self.get_enclosing_parallel_handle()
39            )
40        return self.enclosing_parallel
41
42    def get_task_in_parallel(self, thread_num):
43        """Obtains handles for the implicit tasks associated with the
44        parallel region specified by parallel_handle."""
45        if not thread_num in self.itasks:
46            task_handle = ompdModule.call_ompd_get_task_in_parallel(
47                self.parallel_handle, thread_num
48            )
49            self.itasks[thread_num] = ompd_task(task_handle)
50        return self.itasks[thread_num]
51
52    def __del__(self):
53        """Releases the parallel handle."""
54        pass  # let capsule destructors do the job
55
56
57class ompd_task(object):
58    def __init__(self, task_handle):
59        """Initializes a new ompd_task_handle object and sets the attribute
60        to the task handle specified."""
61        self.task_handle = task_handle
62        self.task_parallel_handle = False
63        self.generating_task_handle = False
64        self.scheduling_task_handle = False
65        self.task_parallel = False
66        self.generating_task = False
67        self.scheduling_task = False
68        self.task_frames = None
69        self.task_frame_flags = None
70
71    def get_task_parallel_handle(self):
72        """Obtains a task parallel handle for the parallel region enclosing
73        the task region specified."""
74        if not self.task_parallel_handle:
75            self.task_parallel_handle = ompdModule.call_ompd_get_task_parallel_handle(
76                self.task_handle
77            )
78        return self.task_parallel_handle
79
80    def get_task_parallel(self):
81        if not self.task_parallel:
82            self.task_parallel = ompd_parallel(self.get_task_parallel_handle())
83        return self.task_parallel
84
85    def get_generating_task_handle(self):
86        """Obtains the task handle for the task that created the task specified
87        by the task handle."""
88        if not self.generating_task_handle:
89            self.generating_task_handle = (
90                ompdModule.call_ompd_get_generating_task_handle(self.task_handle)
91            )
92        return self.generating_task_handle
93
94    def get_generating_task(self):
95        if not self.generating_task:
96            self.generating_task = ompd_task(
97                ompdModule.call_ompd_get_generating_task_handle(self.task_handle)
98            )
99        return self.generating_task
100
101    def get_scheduling_task_handle(self):
102        """Obtains the task handle for the task that scheduled the task specified."""
103        if not self.scheduling_task_handle:
104            self.scheduling_task_handle = (
105                ompdModule.call_ompd_get_scheduling_task_handle(self.task_handle)
106            )
107        return self.scheduling_task_handle
108
109    def get_scheduling_task(self):
110        """Returns ompd_task object for the task that scheduled the current task."""
111        if not self.scheduling_task:
112            self.scheduling_task = ompd_task(self.get_scheduling_task_handle())
113        return self.scheduling_task
114
115    def get_task_function(self):
116        """Returns long with address of function entry point."""
117        return ompdModule.call_ompd_get_task_function(self.task_handle)
118
119    def get_task_frame_with_flags(self):
120        """Returns enter frame address and flag, exit frame address and flag for current task handle."""
121        if self.task_frames is None or self.task_frame_flags is None:
122            ret_value = ompdModule.call_ompd_get_task_frame(self.task_handle)
123            if isinstance(ret_value, tuple):
124                self.task_frames = (ret_value[0], ret_value[2])
125                self.task_frame_flags = (ret_value[1], ret_value[3])
126            else:
127                return ret_value
128        return (
129            self.task_frames[0],
130            self.task_frame_flags[0],
131            self.task_frames[1],
132            self.task_frame_flags[1],
133        )
134
135    def get_task_frame(self):
136        """Returns enter and exit frame address for current task handle."""
137        if self.task_frames is None:
138            ret_value = ompdModule.call_ompd_get_task_frame(self.task_handle)
139            if isinstance(ret_value, tuple):
140                self.task_frames = (ret_value[0], ret_value[2])
141            else:
142                return ret_value
143        return self.task_frames
144
145    def __del__(self):
146        """Releases the task handle."""
147        pass  # let capsule destructors do the job
148
149
150class ompd_thread(object):
151    def __init__(self, thread_handle):
152        """Initializes an ompd_thread with the data received from
153        GDB."""
154        self.thread_handle = thread_handle
155        self.parallel_handle = None
156        self.task_handle = None
157        self.current_task = False
158        self.current_parallel = False
159        self.thread_id = False
160
161    def get_current_parallel_handle(self):
162        """Obtains the parallel handle for the parallel region associated with
163        the given thread handle."""
164        # TODO: invalidate thread objects based on `gdb.event.cont`. This should invalidate all internal state.
165        self.parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(
166            self.thread_handle
167        )
168        return self.parallel_handle
169
170    def get_current_parallel(self):
171        """Returns parallel object for parallel handle of the parallel region
172        associated with the current thread handle."""
173        if not self.current_parallel:
174            self.current_parallel = ompd_parallel(self.get_current_parallel_handle())
175        return self.current_parallel
176
177    def get_current_task_handle(self):
178        """Obtains the task handle for the current task region of the
179        given thread."""
180        return ompdModule.call_ompd_get_curr_task_handle(self.thread_handle)
181
182    def get_thread_id(self):
183        """Obtains the ID for the given thread."""
184        if not self.thread_id:
185            self.thread_id = ompdModule.call_ompd_get_thread_id(self.thread_handle)
186        return self.thread_id
187
188    def get_current_task(self):
189        """Returns task object for task handle of the current task region."""
190        return ompd_task(self.get_current_task_handle())
191
192    def get_state(self):
193        """Returns tuple with OMPD state (long) and wait_id, in case the thread is in a
194        waiting state. Helper function for 'ompd threads' command."""
195        (state, wait_id) = ompdModule.call_ompd_get_state(self.thread_handle)
196        return (state, wait_id)
197
198    def __del__(self):
199        """Releases the given thread handle."""
200        pass  # let capsule destructors do the job
201