summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/common/modules/genunix/ctxop.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/mdb/common/modules/genunix/ctxop.c')
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/ctxop.c77
1 files changed, 60 insertions, 17 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/ctxop.c b/usr/src/cmd/mdb/common/modules/genunix/ctxop.c
index 486113031d..d78432b743 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/ctxop.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/ctxop.c
@@ -23,54 +23,97 @@
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
-#include <sys/mdb_modapi.h>
-#include <sys/thread.h>
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ctf.h>
#include "ctxop.h"
+struct ctxop_walk_state {
+ uintptr_t cws_head;
+ uint_t cws_next_offset;
+};
+
int
ctxop_walk_init(mdb_walk_state_t *wsp)
{
- kthread_t thread, *tp = &thread;
+ struct ctxop_walk_state *priv;
+ int offset;
+ uintptr_t addr;
if (wsp->walk_addr == 0) {
mdb_warn("must specify thread for ctxop walk\n");
return (WALK_ERR);
}
- if (mdb_vread(tp, sizeof (*tp), wsp->walk_addr) == -1) {
- mdb_warn("failed to read thread at %p", wsp->walk_addr);
+
+ offset = mdb_ctf_offsetof_by_name("kthread_t", "t_ctx");
+ if (offset == -1)
+ return (WALK_ERR);
+
+ if (mdb_vread(&addr, sizeof (addr),
+ wsp->walk_addr + offset) != sizeof (addr)) {
+ mdb_warn("failed to read thread %p", wsp->walk_addr);
return (WALK_ERR);
}
- wsp->walk_data = mdb_alloc(sizeof (ctxop_t), UM_SLEEP);
- wsp->walk_addr = (uintptr_t)tp->t_ctx;
+ /* No further work for threads with a NULL t_ctx */
+ if (addr == 0) {
+ wsp->walk_data = NULL;
+ return (WALK_DONE);
+ }
+ /* rely on CTF for the offset of the 'next' pointer */
+ offset = mdb_ctf_offsetof_by_name("struct ctxop", "next");
+ if (offset == -1)
+ return (WALK_ERR);
+
+ priv = mdb_alloc(sizeof (*priv), UM_SLEEP);
+ priv->cws_head = addr;
+ priv->cws_next_offset = (uint_t)offset;
+
+ wsp->walk_data = priv;
+ wsp->walk_addr = addr;
return (WALK_NEXT);
}
int
ctxop_walk_step(mdb_walk_state_t *wsp)
{
+ struct ctxop_walk_state *priv = wsp->walk_data;
+ uintptr_t next;
int status;
- if (wsp->walk_addr == 0)
- return (WALK_DONE);
-
- if (mdb_vread(wsp->walk_data,
- sizeof (ctxop_t), wsp->walk_addr) == -1) {
- mdb_warn("failed to read ctxop at %p", wsp->walk_addr);
+ if (mdb_vread(&next, sizeof (next),
+ wsp->walk_addr + priv->cws_next_offset) == -1) {
+ mdb_warn("failed to read ctxop`next at %p",
+ wsp->walk_addr + priv->cws_next_offset);
return (WALK_DONE);
}
- status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
- wsp->walk_cbdata);
+ status = wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata);
- wsp->walk_addr = (uintptr_t)(((ctxop_t *)wsp->walk_data)->next);
+ if (status == WALK_NEXT) {
+ /*
+ * If a NULL terminator or a loop back to the head element is
+ * encountered, the walk is done.
+ */
+ if (next == 0 || next == priv->cws_head) {
+ status = WALK_DONE;
+ }
+ }
+
+ wsp->walk_addr = next;
return (status);
}
void
ctxop_walk_fini(mdb_walk_state_t *wsp)
{
- mdb_free(wsp->walk_data, sizeof (ctxop_t));
+ struct ctxop_walk_state *priv = wsp->walk_data;
+
+ if (priv != NULL) {
+ mdb_free(priv, sizeof (*priv));
+ }
}