Imported Upstream version 7.9
[platform/upstream/gdb.git] / gdb / python / py-infthread.c
1 /* Python interface to inferior threads.
2
3    Copyright (C) 2009-2015 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "gdbthread.h"
22 #include "inferior.h"
23 #include "python-internal.h"
24
25 static PyTypeObject thread_object_type
26     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object");
27
28 /* Require that INFERIOR be a valid inferior ID.  */
29 #define THPY_REQUIRE_VALID(Thread)                              \
30   do {                                                          \
31     if (!Thread->thread)                                        \
32       {                                                         \
33         PyErr_SetString (PyExc_RuntimeError,                    \
34                          _("Thread no longer exists."));        \
35         return NULL;                                            \
36       }                                                         \
37   } while (0)
38
39 thread_object *
40 create_thread_object (struct thread_info *tp)
41 {
42   thread_object *thread_obj;
43
44   thread_obj = PyObject_New (thread_object, &thread_object_type);
45   if (!thread_obj)
46     return NULL;
47
48   thread_obj->thread = tp;
49   thread_obj->inf_obj = find_inferior_object (ptid_get_pid (tp->ptid));
50
51   return thread_obj;
52 }
53
54 static void
55 thpy_dealloc (PyObject *self)
56 {
57   Py_DECREF (((thread_object *) self)->inf_obj);
58   Py_TYPE (self)->tp_free (self);
59 }
60
61 static PyObject *
62 thpy_get_name (PyObject *self, void *ignore)
63 {
64   thread_object *thread_obj = (thread_object *) self;
65   char *name;
66
67   THPY_REQUIRE_VALID (thread_obj);
68
69   name = thread_obj->thread->name;
70   if (name == NULL)
71     name = target_thread_name (thread_obj->thread);
72
73   if (name == NULL)
74     Py_RETURN_NONE;
75
76   return PyString_FromString (name);
77 }
78
79 static int
80 thpy_set_name (PyObject *self, PyObject *newvalue, void *ignore)
81 {
82   thread_object *thread_obj = (thread_object *) self;
83   char *name;
84
85   if (! thread_obj->thread)
86     {
87       PyErr_SetString (PyExc_RuntimeError, _("Thread no longer exists."));
88       return -1;
89     }
90
91   if (newvalue == NULL)
92     {
93       PyErr_SetString (PyExc_TypeError,
94                        _("Cannot delete `name' attribute."));
95       return -1;
96     }
97   else if (newvalue == Py_None)
98     name = NULL;
99   else if (! gdbpy_is_string (newvalue))
100     {
101       PyErr_SetString (PyExc_TypeError,
102                        _("The value of `name' must be a string."));
103       return -1;
104     }
105   else
106     {
107       name = python_string_to_host_string (newvalue);
108       if (! name)
109         return -1;
110     }
111
112   xfree (thread_obj->thread->name);
113   thread_obj->thread->name = name;
114
115   return 0;
116 }
117
118 static PyObject *
119 thpy_get_num (PyObject *self, void *closure)
120 {
121   thread_object *thread_obj = (thread_object *) self;
122
123   THPY_REQUIRE_VALID (thread_obj);
124
125   return PyLong_FromLong (thread_obj->thread->num);
126 }
127
128 /* Getter for InferiorThread.ptid  -> (pid, lwp, tid).
129    Returns a tuple with the thread's ptid components.  */
130
131 static PyObject *
132 thpy_get_ptid (PyObject *self, void *closure)
133 {
134   int pid;
135   long tid, lwp;
136   thread_object *thread_obj = (thread_object *) self;
137
138   THPY_REQUIRE_VALID (thread_obj);
139
140   return gdbpy_create_ptid_object (thread_obj->thread->ptid);
141 }
142
143 /* Implementation of InferiorThread.switch ().
144    Makes this the GDB selected thread.  */
145
146 static PyObject *
147 thpy_switch (PyObject *self, PyObject *args)
148 {
149   thread_object *thread_obj = (thread_object *) self;
150   volatile struct gdb_exception except;
151
152   THPY_REQUIRE_VALID (thread_obj);
153
154   TRY_CATCH (except, RETURN_MASK_ALL)
155     {
156       switch_to_thread (thread_obj->thread->ptid);
157     }
158   GDB_PY_HANDLE_EXCEPTION (except);
159
160   Py_RETURN_NONE;
161 }
162
163 /* Implementation of InferiorThread.is_stopped () -> Boolean.
164    Return whether the thread is stopped.  */
165
166 static PyObject *
167 thpy_is_stopped (PyObject *self, PyObject *args)
168 {
169   thread_object *thread_obj = (thread_object *) self;
170
171   THPY_REQUIRE_VALID (thread_obj);
172
173   if (is_stopped (thread_obj->thread->ptid))
174     Py_RETURN_TRUE;
175
176   Py_RETURN_FALSE;
177 }
178
179 /* Implementation of InferiorThread.is_running () -> Boolean.
180    Return whether the thread is running.  */
181
182 static PyObject *
183 thpy_is_running (PyObject *self, PyObject *args)
184 {
185   thread_object *thread_obj = (thread_object *) self;
186
187   THPY_REQUIRE_VALID (thread_obj);
188
189   if (is_running (thread_obj->thread->ptid))
190     Py_RETURN_TRUE;
191
192   Py_RETURN_FALSE;
193 }
194
195 /* Implementation of InferiorThread.is_exited () -> Boolean.
196    Return whether the thread is exited.  */
197
198 static PyObject *
199 thpy_is_exited (PyObject *self, PyObject *args)
200 {
201   thread_object *thread_obj = (thread_object *) self;
202
203   THPY_REQUIRE_VALID (thread_obj);
204
205   if (is_exited (thread_obj->thread->ptid))
206     Py_RETURN_TRUE;
207
208   Py_RETURN_FALSE;
209 }
210
211 /* Implementation of gdb.InfThread.is_valid (self) -> Boolean.
212    Returns True if this inferior Thread object still exists
213    in GDB.  */
214
215 static PyObject *
216 thpy_is_valid (PyObject *self, PyObject *args)
217 {
218   thread_object *thread_obj = (thread_object *) self;
219
220   if (! thread_obj->thread)
221     Py_RETURN_FALSE;
222
223   Py_RETURN_TRUE;
224 }
225
226 /* Return a reference to a new Python object representing a ptid_t.
227    The object is a tuple containing (pid, lwp, tid). */
228 PyObject *
229 gdbpy_create_ptid_object (ptid_t ptid)
230 {
231   int pid;
232   long tid, lwp;
233   PyObject *ret;
234
235   ret = PyTuple_New (3);
236   if (!ret)
237     return NULL;
238
239   pid = ptid_get_pid (ptid);
240   lwp = ptid_get_lwp (ptid);
241   tid = ptid_get_tid (ptid);
242
243   PyTuple_SET_ITEM (ret, 0, PyInt_FromLong (pid));
244   PyTuple_SET_ITEM (ret, 1, PyInt_FromLong (lwp));
245   PyTuple_SET_ITEM (ret, 2, PyInt_FromLong (tid));
246  
247   return ret;
248 }
249
250 /* Implementation of gdb.selected_thread () -> gdb.InferiorThread.
251    Returns the selected thread object.  */
252
253 PyObject *
254 gdbpy_selected_thread (PyObject *self, PyObject *args)
255 {
256   PyObject *thread_obj;
257
258   thread_obj = (PyObject *) find_thread_object (inferior_ptid);
259   if (thread_obj)
260     {
261       Py_INCREF (thread_obj);
262       return thread_obj;
263     }
264
265   Py_RETURN_NONE;
266 }
267
268 int
269 gdbpy_initialize_thread (void)
270 {
271   if (PyType_Ready (&thread_object_type) < 0)
272     return -1;
273
274   return gdb_pymodule_addobject (gdb_module, "InferiorThread",
275                                  (PyObject *) &thread_object_type);
276 }
277
278 static PyGetSetDef thread_object_getset[] =
279 {
280   { "name", thpy_get_name, thpy_set_name,
281     "The name of the thread, as set by the user or the OS.", NULL },
282   { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL },
283   { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.",
284     NULL },
285
286   { NULL }
287 };
288
289 static PyMethodDef thread_object_methods[] =
290 {
291   { "is_valid", thpy_is_valid, METH_NOARGS,
292     "is_valid () -> Boolean.\n\
293 Return true if this inferior thread is valid, false if not." },
294   { "switch", thpy_switch, METH_NOARGS,
295     "switch ()\n\
296 Makes this the GDB selected thread." },
297   { "is_stopped", thpy_is_stopped, METH_NOARGS,
298     "is_stopped () -> Boolean\n\
299 Return whether the thread is stopped." },
300   { "is_running", thpy_is_running, METH_NOARGS,
301     "is_running () -> Boolean\n\
302 Return whether the thread is running." },
303   { "is_exited", thpy_is_exited, METH_NOARGS,
304     "is_exited () -> Boolean\n\
305 Return whether the thread is exited." },
306
307   { NULL }
308 };
309
310 static PyTypeObject thread_object_type =
311 {
312   PyVarObject_HEAD_INIT (NULL, 0)
313   "gdb.InferiorThread",           /*tp_name*/
314   sizeof (thread_object),         /*tp_basicsize*/
315   0,                              /*tp_itemsize*/
316   thpy_dealloc,                   /*tp_dealloc*/
317   0,                              /*tp_print*/
318   0,                              /*tp_getattr*/
319   0,                              /*tp_setattr*/
320   0,                              /*tp_compare*/
321   0,                              /*tp_repr*/
322   0,                              /*tp_as_number*/
323   0,                              /*tp_as_sequence*/
324   0,                              /*tp_as_mapping*/
325   0,                              /*tp_hash */
326   0,                              /*tp_call*/
327   0,                              /*tp_str*/
328   0,                              /*tp_getattro*/
329   0,                              /*tp_setattro*/
330   0,                              /*tp_as_buffer*/
331   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
332   "GDB thread object",            /* tp_doc */
333   0,                              /* tp_traverse */
334   0,                              /* tp_clear */
335   0,                              /* tp_richcompare */
336   0,                              /* tp_weaklistoffset */
337   0,                              /* tp_iter */
338   0,                              /* tp_iternext */
339   thread_object_methods,          /* tp_methods */
340   0,                              /* tp_members */
341   thread_object_getset,           /* tp_getset */
342   0,                              /* tp_base */
343   0,                              /* tp_dict */
344   0,                              /* tp_descr_get */
345   0,                              /* tp_descr_set */
346   0,                              /* tp_dictoffset */
347   0,                              /* tp_init */
348   0                               /* tp_alloc */
349 };