aboutsummaryrefslogtreecommitdiff
path: root/ddb/db_task_thread.c
diff options
context:
space:
mode:
authorPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
committerPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
commit5e0b8d508ed51004bd836384293be00950ee62c9 (patch)
treee3f16b1aa8b7177032ce3ec429fbad2b1d92a876 /ddb/db_task_thread.c
downloadgnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.gz
gnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.bz2
init gnumach copy
Diffstat (limited to 'ddb/db_task_thread.c')
-rw-r--r--ddb/db_task_thread.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/ddb/db_task_thread.c b/ddb/db_task_thread.c
new file mode 100644
index 0000000..fe742c2
--- /dev/null
+++ b/ddb/db_task_thread.c
@@ -0,0 +1,326 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#if MACH_KDB
+
+#include <machine/db_machdep.h>
+#include <ddb/db_command.h>
+#include <ddb/db_expr.h>
+#include <ddb/db_lex.h>
+#include <ddb/db_output.h>
+#include <ddb/db_task_thread.h>
+#include <ddb/db_variables.h>
+
+
+
+/*
+ * Following constants are used to prevent infinite loop of task
+ * or thread search due to the incorrect list.
+ */
+#define DB_MAX_TASKID 0x10000 /* max # of tasks */
+#define DB_MAX_THREADID 0x10000 /* max # of threads in a task */
+#define DB_MAX_PSETS 0x10000 /* max # of processor sets */
+
+task_t db_default_task; /* default target task */
+thread_t db_default_thread; /* default target thread */
+
+/*
+ * search valid task queue, and return the queue position as the task id
+ */
+int
+db_lookup_task(const task_t target_task)
+{
+ task_t task;
+ int task_id;
+ processor_set_t pset;
+ int npset = 0;
+
+ task_id = 0;
+ if (queue_first(&all_psets) == 0)
+ return(-1);
+ queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
+ if (npset++ >= DB_MAX_PSETS)
+ return(-1);
+ if (queue_first(&pset->tasks) == 0)
+ continue;
+ queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
+ if (target_task == task)
+ return(task_id);
+ if (task_id++ >= DB_MAX_TASKID)
+ return(-1);
+ }
+ }
+ return(-1);
+}
+
+/*
+ * search thread queue of the task, and return the queue position
+ */
+int
+db_lookup_task_thread(const task_t task, const thread_t target_thread)
+{
+ thread_t thread;
+ int thread_id;
+
+ thread_id = 0;
+ if (queue_first(&task->thread_list) == 0)
+ return(-1);
+ queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
+ if (target_thread == thread)
+ return(thread_id);
+ if (thread_id++ >= DB_MAX_THREADID)
+ return(-1);
+ }
+ return(-1);
+}
+
+/*
+ * search thread queue of every valid task, and return the queue position
+ * as the thread id.
+ */
+int
+db_lookup_thread(const thread_t target_thread)
+{
+ int thread_id;
+ task_t task;
+ processor_set_t pset;
+ int ntask = 0;
+ int npset = 0;
+
+ if (queue_first(&all_psets) == 0)
+ return(-1);
+ queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
+ if (npset++ >= DB_MAX_PSETS)
+ return(-1);
+ if (queue_first(&pset->tasks) == 0)
+ continue;
+ queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
+ if (ntask++ > DB_MAX_TASKID)
+ return(-1);
+ if (task->thread_count == 0)
+ continue;
+ thread_id = db_lookup_task_thread(task, target_thread);
+ if (thread_id >= 0)
+ return(thread_id);
+ }
+ }
+ return(-1);
+}
+
+/*
+ * check the address is a valid thread address
+ */
+boolean_t
+db_check_thread_address_valid(const thread_t thread)
+{
+ if (db_lookup_thread(thread) < 0) {
+ db_printf("Bad thread address 0x%x\n", thread);
+ db_flush_lex();
+ return(FALSE);
+ } else
+ return(TRUE);
+}
+
+/*
+ * convert task_id(queue position) to task address
+ */
+static task_t
+db_lookup_task_id(int task_id)
+{
+ task_t task;
+ processor_set_t pset;
+ int npset = 0;
+
+ if (task_id > DB_MAX_TASKID)
+ return(TASK_NULL);
+ if (queue_first(&all_psets) == 0)
+ return(TASK_NULL);
+ queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
+ if (npset++ >= DB_MAX_PSETS)
+ return(TASK_NULL);
+ if (queue_first(&pset->tasks) == 0)
+ continue;
+ queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
+ if (task_id-- <= 0)
+ return(task);
+ }
+ }
+ return(TASK_NULL);
+}
+
+/*
+ * convert (task_id, thread_id) pair to thread address
+ */
+static thread_t
+db_lookup_thread_id(
+ task_t task,
+ int thread_id)
+{
+ thread_t thread;
+
+
+ if (thread_id > DB_MAX_THREADID)
+ return(THREAD_NULL);
+ if (queue_first(&task->thread_list) == 0)
+ return(THREAD_NULL);
+ queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
+ if (thread_id-- <= 0)
+ return(thread);
+ }
+ return(THREAD_NULL);
+}
+
+/*
+ * get next parameter from a command line, and check it as a valid
+ * thread address
+ */
+boolean_t
+db_get_next_thread(
+ thread_t *threadp,
+ int position)
+{
+ db_expr_t value;
+ thread_t thread;
+
+ *threadp = THREAD_NULL;
+ if (db_expression(&value)) {
+ thread = (thread_t) value;
+ if (!db_check_thread_address_valid(thread)) {
+ db_flush_lex();
+ return(FALSE);
+ }
+ } else if (position <= 0) {
+ thread = db_default_thread;
+ } else
+ return(FALSE);
+ *threadp = thread;
+ return(TRUE);
+}
+
+/*
+ * check the default thread is still valid
+ * ( it is called in entering DDB session )
+ */
+void
+db_init_default_thread(void)
+{
+ if (db_lookup_thread(db_default_thread) < 0) {
+ db_default_thread = THREAD_NULL;
+ db_default_task = TASK_NULL;
+ } else
+ db_default_task = db_default_thread->task;
+}
+
+/*
+ * set or get default thread which is used when /t or :t option is specified
+ * in the command line
+ */
+/* ARGSUSED */
+void
+db_set_default_thread(
+ struct db_variable *vp,
+ db_expr_t *valuep,
+ int flag,
+ db_var_aux_param_t ap)
+{
+ thread_t thread;
+
+ if (flag != DB_VAR_SET) {
+ *valuep = (db_expr_t) db_default_thread;
+ return;
+ }
+ thread = (thread_t) *valuep;
+ if (thread != THREAD_NULL && !db_check_thread_address_valid(thread))
+ db_error(0);
+ /* NOTREACHED */
+ db_default_thread = thread;
+ if (thread)
+ db_default_task = thread->task;
+ return;
+}
+
+/*
+ * convert $taskXXX[.YYY] type DDB variable to task or thread address
+ */
+void
+db_get_task_thread(
+ struct db_variable *vp,
+ db_expr_t *valuep,
+ int flag,
+ db_var_aux_param_t ap)
+{
+ task_t task;
+ thread_t thread;
+
+ if (flag != DB_VAR_GET) {
+ db_error("Cannot set to $task variable\n");
+ /* NOTREACHED */
+ }
+ if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) {
+ db_printf("no such task($task%d)\n", ap->suffix[0]);
+ db_error(0);
+ /* NOTREACHED */
+ }
+ if (ap->level <= 1) {
+ *valuep = (db_expr_t) task;
+ return;
+ }
+ if ((thread = db_lookup_thread_id(task, ap->suffix[1])) == THREAD_NULL){
+ db_printf("no such thread($task%d.%d)\n",
+ ap->suffix[0], ap->suffix[1]);
+ db_error(0);
+ /* NOTREACHED */
+ }
+ *valuep = (db_expr_t) thread;
+ return;
+}
+
+/*
+ * convert $mapXXX type DDB variable to map address
+ */
+void
+db_get_map(struct db_variable *vp,
+ db_expr_t *valuep,
+ int flag,
+ db_var_aux_param_t ap)
+{
+ task_t task;
+
+ if (flag != DB_VAR_GET) {
+ db_error("Cannot set to $map variable\n");
+ /* NOTREACHED */
+ }
+
+ if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) {
+ db_printf("no such map($map%d)\n", ap->suffix[0]);
+ db_error(0);
+ /* NOTREACHED */
+ }
+
+ *valuep = (db_expr_t) task->map;
+}
+
+#endif /* MACH_KDB */