| |   |
| 31 | 31 | #include "symtab.h" |
| 32 | 32 | #include "source.h" |
| 33 | 33 | #include "version.h" |
| 34 | #include "inferior.h" |
| 35 | #include "gdbthread.h" |
| 34 | 36 | |
| 35 | 37 | #include <ctype.h> |
| 36 | 38 | |
| … | … | |
| 43 | 43 | static PyObject *gdbpy_solib_address (PyObject *, PyObject *); |
| 44 | 44 | static PyObject *gdbpy_decode_line (PyObject *, PyObject *); |
| 45 | 45 | static PyObject *gdbpy_find_pc_function (PyObject *, PyObject *); |
| 46 | static PyObject *gdbpy_get_threads (PyObject *, PyObject *); |
| 47 | static PyObject *gdbpy_get_current_thread (PyObject *, PyObject *); |
| 48 | static PyObject *gdbpy_switch_to_thread (PyObject *, PyObject *); |
| 46 | 49 | |
| 47 | 50 | |
| 48 | 51 | void |
| … | … | |
| 90 | 90 | Return a tuple holding the file name (or None) and line number (or None).\n\ |
| 91 | 91 | Note: may later change to return an object." }, |
| 92 | 92 | |
| 93 | { "get_threads", gdbpy_get_threads, METH_NOARGS, |
| 94 | "Return a tuple holding all the valid thread IDs." }, |
| 95 | { "get_current_thread", gdbpy_get_current_thread, METH_NOARGS, |
| 96 | "Return the thread ID of the current thread." }, |
| 97 | { "switch_to_thread", gdbpy_switch_to_thread, METH_VARARGS, |
| 98 | "Switch to a thread, given the thread ID." }, |
| 99 | |
| 93 | 100 | {NULL, NULL, 0, NULL} |
| 94 | 101 | }; |
| 95 | 102 | |
| … | … | |
| 486 | 486 | |
| 487 | 487 | |
| 488 | 488 | |
| 489 | /* Threads. */ |
| 490 | |
| 491 | static int |
| 492 | count_callback (struct thread_info *info, void *user_data) |
| 493 | { |
| 494 | int *count = (int *) user_data; |
| 495 | ++*count; |
| 496 | return 0; |
| 497 | } |
| 498 | |
| 499 | struct set_thread_info |
| 500 | { |
| 501 | PyObject *tuple; |
| 502 | int index; |
| 503 | }; |
| 504 | |
| 505 | static int |
| 506 | update_tuple_callback (struct thread_info *info, void *user_data) |
| 507 | { |
| 508 | struct set_thread_info *tinfo = (struct set_thread_info *) user_data; |
| 509 | PyTuple_SetItem (tinfo->tuple, tinfo->index, PyInt_FromLong (info->num)); |
| 510 | ++tinfo->index; |
| 511 | return 0; |
| 512 | } |
| 513 | |
| 514 | static PyObject * |
| 515 | gdbpy_get_threads (PyObject *unused1, PyObject *unused2) |
| 516 | { |
| 517 | int thread_count = 0; |
| 518 | struct set_thread_info info; |
| 519 | PyObject *result; |
| 520 | |
| 521 | prune_threads (); |
| 522 | target_find_new_threads (); |
| 523 | |
| 524 | iterate_over_threads (count_callback, &thread_count); |
| 525 | |
| 526 | if (!thread_count) |
| 527 | Py_RETURN_NONE; |
| 528 | |
| 529 | result = PyTuple_New (thread_count); |
| 530 | info.tuple = result; |
| 531 | info.index = 0; |
| 532 | iterate_over_threads (update_tuple_callback, &info); |
| 533 | return result; |
| 534 | } |
| 535 | |
| 536 | static PyObject * |
| 537 | gdbpy_get_current_thread (PyObject *unused1, PyObject *unused2) |
| 538 | { |
| 539 | if (PIDGET (inferior_ptid) == 0) |
| 540 | Py_RETURN_NONE; |
| 541 | return PyInt_FromLong (pid_to_thread_id (inferior_ptid)); |
| 542 | } |
| 543 | |
| 544 | static PyObject * |
| 545 | gdbpy_switch_to_thread (PyObject *self, PyObject *args) |
| 546 | { |
| 547 | int id; |
| 548 | if (! PyArg_ParseTuple (args, "i", &id)) |
| 549 | return NULL; |
| 550 | if (! valid_thread_id (id)) |
| 551 | return PyErr_Format (PyExc_RuntimeError, "invalid thread id"); |
| 552 | switch_to_thread (thread_id_to_pid (id)); |
| 553 | Py_RETURN_NONE; |
| 554 | } |
| 555 | |
| 556 | |
| 557 | |
| 489 | 558 | void |
| 490 | 559 | _initialize_python (void) |
| 491 | 560 | { |
| toggle raw diff |
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -31,6 +31,8 @@
#include "symtab.h"
#include "source.h"
#include "version.h"
+#include "inferior.h"
+#include "gdbthread.h"
#include <ctype.h>
@@ -41,6 +43,9 @@ static PyObject *execute_gdb_command (PyObject *, PyObject *);
static PyObject *gdbpy_solib_address (PyObject *, PyObject *);
static PyObject *gdbpy_decode_line (PyObject *, PyObject *);
static PyObject *gdbpy_find_pc_function (PyObject *, PyObject *);
+static PyObject *gdbpy_get_threads (PyObject *, PyObject *);
+static PyObject *gdbpy_get_current_thread (PyObject *, PyObject *);
+static PyObject *gdbpy_switch_to_thread (PyObject *, PyObject *);
void
@@ -85,6 +90,13 @@ demand_python ()
Return a tuple holding the file name (or None) and line number (or None).\n\
Note: may later change to return an object." },
+ { "get_threads", gdbpy_get_threads, METH_NOARGS,
+ "Return a tuple holding all the valid thread IDs." },
+ { "get_current_thread", gdbpy_get_current_thread, METH_NOARGS,
+ "Return the thread ID of the current thread." },
+ { "switch_to_thread", gdbpy_switch_to_thread, METH_VARARGS,
+ "Switch to a thread, given the thread ID." },
+
{NULL, NULL, 0, NULL}
};
@@ -474,6 +486,75 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
+/* Threads. */
+
+static int
+count_callback (struct thread_info *info, void *user_data)
+{
+ int *count = (int *) user_data;
+ ++*count;
+ return 0;
+}
+
+struct set_thread_info
+{
+ PyObject *tuple;
+ int index;
+};
+
+static int
+update_tuple_callback (struct thread_info *info, void *user_data)
+{
+ struct set_thread_info *tinfo = (struct set_thread_info *) user_data;
+ PyTuple_SetItem (tinfo->tuple, tinfo->index, PyInt_FromLong (info->num));
+ ++tinfo->index;
+ return 0;
+}
+
+static PyObject *
+gdbpy_get_threads (PyObject *unused1, PyObject *unused2)
+{
+ int thread_count = 0;
+ struct set_thread_info info;
+ PyObject *result;
+
+ prune_threads ();
+ target_find_new_threads ();
+
+ iterate_over_threads (count_callback, &thread_count);
+
+ if (!thread_count)
+ Py_RETURN_NONE;
+
+ result = PyTuple_New (thread_count);
+ info.tuple = result;
+ info.index = 0;
+ iterate_over_threads (update_tuple_callback, &info);
+ return result;
+}
+
+static PyObject *
+gdbpy_get_current_thread (PyObject *unused1, PyObject *unused2)
+{
+ if (PIDGET (inferior_ptid) == 0)
+ Py_RETURN_NONE;
+ return PyInt_FromLong (pid_to_thread_id (inferior_ptid));
+}
+
+static PyObject *
+gdbpy_switch_to_thread (PyObject *self, PyObject *args)
+{
+ int id;
+ if (! PyArg_ParseTuple (args, "i", &id))
+ return NULL;
+ if (! valid_thread_id (id))
+ return PyErr_Format (PyExc_RuntimeError, "invalid thread id");
+ switch_to_thread (thread_id_to_pid (id));
+ Py_RETURN_NONE;
+}
+
+
+
void
_initialize_python (void)
{ |
| |   |
| 60 | 60 | static void info_threads_command (char *, int); |
| 61 | 61 | static void thread_apply_command (char *, int); |
| 62 | 62 | static void restore_current_thread (ptid_t); |
| 63 | | static void prune_threads (void); |
| 64 | 63 | |
| 65 | 64 | void |
| 66 | 65 | delete_step_resume_breakpoint (void *arg) |
| … | … | |
| 399 | 399 | return 1; |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | | static void |
| 402 | void |
| 403 | 403 | prune_threads (void) |
| 404 | 404 | { |
| 405 | | struct thread_info *tp, *next; |
| 405 | struct thread_info *tp; |
| 406 | struct thread_info **prevp = &thread_list; |
| 406 | 407 | |
| 407 | | for (tp = thread_list; tp; tp = next) |
| 408 | for (tp = *prevp; tp; tp = *prevp) |
| 408 | 409 | { |
| 409 | | next = tp->next; |
| 410 | /* If the thread has died, free it and unlink it from the list. |
| 411 | Otherwise, advance to the next thread. */ |
| 410 | 412 | if (!thread_alive (tp)) |
| 411 | | delete_thread (tp->ptid); |
| 413 | { |
| 414 | (*prevp)->next = tp->next; |
| 415 | free_thread (tp); |
| 416 | } |
| 417 | else |
| 418 | prevp = &tp->next; |
| 412 | 419 | } |
| 413 | 420 | } |
| 414 | 421 | |
| toggle raw diff |
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -60,7 +60,6 @@ static int thread_alive (struct thread_info *);
static void info_threads_command (char *, int);
static void thread_apply_command (char *, int);
static void restore_current_thread (ptid_t);
-static void prune_threads (void);
void
delete_step_resume_breakpoint (void *arg)
@@ -400,16 +399,23 @@ thread_alive (struct thread_info *tp)
return 1;
}
-static void
+void
prune_threads (void)
{
- struct thread_info *tp, *next;
+ struct thread_info *tp;
+ struct thread_info **prevp = &thread_list;
- for (tp = thread_list; tp; tp = next)
+ for (tp = *prevp; tp; tp = *prevp)
{
- next = tp->next;
+ /* If the thread has died, free it and unlink it from the list.
+ Otherwise, advance to the next thread. */
if (!thread_alive (tp))
- delete_thread (tp->ptid);
+ {
+ (*prevp)->next = tp->next;
+ free_thread (tp);
+ }
+ else
+ prevp = &tp->next;
}
}
|