procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
{
pid_t tid;
+ pid_t pid;
+ procfs_status status;
+ int err;
tid = ptid_get_tid (ptid);
- if (devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) == EOK)
- return 1;
- return 0;
+ pid = ptid_get_pid (ptid);
+
+ if (kill (pid, 0) == -1)
+ return 0;
+
+ status.tid = tid;
+ if ((err = devctl (ctl_fd, DCMD_PROC_TIDSTATUS,
+ &status, sizeof (status), 0)) != EOK)
+ return 0;
+
+ /* Thread is alive or dead but not yet joined,
+ or dead and there is an alive (or dead unjoined) thread with
+ higher tid.
+
+ If the tid is not the same as requested, requested tid is dead. */
+ return (status.tid == tid) && (status.state != STATE_DEAD);
+}
+
+static void
+update_thread_private_data_name (struct thread_info *new_thread,
+ const char *newname)
+{
+ int newnamelen;
+ struct private_thread_info *pti;
+
+ gdb_assert (newname != NULL);
+ gdb_assert (new_thread != NULL);
+ newnamelen = strlen (newname);
+ if (!new_thread->private)
+ {
+ new_thread->private = xmalloc (offsetof (struct private_thread_info,
+ name)
+ + newnamelen + 1);
+ memcpy (new_thread->private->name, newname, newnamelen + 1);
+ }
+ else if (strcmp (newname, new_thread->private->name) != 0)
+ {
+ /* Reallocate if neccessary. */
+ int oldnamelen = strlen (new_thread->private->name);
+
+ if (oldnamelen < newnamelen)
+ new_thread->private = xrealloc (new_thread->private,
+ offsetof (struct private_thread_info,
+ name)
+ + newnamelen + 1);
+ memcpy (new_thread->private->name, newname, newnamelen + 1);
+ }
+}
+
+static void
+update_thread_private_data (struct thread_info *new_thread,
+ pthread_t tid, int state, int flags)
+{
+ struct private_thread_info *pti;
+ procfs_info pidinfo;
+ struct _thread_name *tn;
+ procfs_threadctl tctl;
+
+#if _NTO_VERSION > 630
+ gdb_assert (new_thread != NULL);
+
+ if (devctl (ctl_fd, DCMD_PROC_INFO, &pidinfo,
+ sizeof(pidinfo), 0) != EOK)
+ return;
+
+ memset (&tctl, 0, sizeof (tctl));
+ tctl.cmd = _NTO_TCTL_NAME;
+ tn = (struct _thread_name *) (&tctl.data);
+
+ /* Fetch name for the given thread. */
+ tctl.tid = tid;
+ tn->name_buf_len = sizeof (tctl.data) - sizeof (*tn);
+ tn->new_name_len = -1; /* Getting, not setting. */
+ if (devctl (ctl_fd, DCMD_PROC_THREADCTL, &tctl, sizeof (tctl), NULL) != EOK)
+ tn->name_buf[0] = '\0';
+
+ tn->name_buf[_NTO_THREAD_NAME_MAX] = '\0';
+
+ update_thread_private_data_name (new_thread, tn->name_buf);
+
+ pti = (struct private_thread_info *) new_thread->private;
+ pti->tid = tid;
+ pti->state = state;
+ pti->flags = flags;
+#endif /* _NTO_VERSION */
}
void
procfs_status status;
pid_t pid;
ptid_t ptid;
+ pthread_t tid;
+ struct thread_info *new_thread;
if (ctl_fd == -1)
return;
pid = ptid_get_pid (inferior_ptid);
- for (status.tid = 1;; ++status.tid)
+ status.tid = 1;
+
+ for (tid = 1;; ++tid)
{
- if (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
- != EOK && status.tid != 0)
+ if (status.tid == tid
+ && (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
+ != EOK))
break;
- ptid = ptid_build (pid, 0, status.tid);
- if (!in_thread_list (ptid))
- add_thread (ptid);
+ if (status.tid != tid)
+ /* The reason why this would not be equal is that devctl might have
+ returned different tid, meaning the requested tid no longer exists
+ (e.g. thread exited). */
+ continue;
+ ptid = ptid_build (pid, 0, tid);
+ new_thread = find_thread_ptid (ptid);
+ if (!new_thread)
+ new_thread = add_thread (ptid);
+ update_thread_private_data (new_thread, tid, status.state, 0);
+ status.tid++;
}
return;
}
procfs_ops.to_has_execution = default_child_has_execution;
procfs_ops.to_magic = OPS_MAGIC;
procfs_ops.to_have_continuable_watchpoint = 1;
+ procfs_ops.to_extra_thread_info = nto_extra_thread_info;
}
#define OSTYPE_NTO 1
return GDB_OSABI_UNKNOWN;
}
+static const char *nto_thread_state_str[] =
+{
+ "DEAD", /* 0 0x00 */
+ "RUNNING", /* 1 0x01 */
+ "READY", /* 2 0x02 */
+ "STOPPED", /* 3 0x03 */
+ "SEND", /* 4 0x04 */
+ "RECEIVE", /* 5 0x05 */
+ "REPLY", /* 6 0x06 */
+ "STACK", /* 7 0x07 */
+ "WAITTHREAD", /* 8 0x08 */
+ "WAITPAGE", /* 9 0x09 */
+ "SIGSUSPEND", /* 10 0x0a */
+ "SIGWAITINFO", /* 11 0x0b */
+ "NANOSLEEP", /* 12 0x0c */
+ "MUTEX", /* 13 0x0d */
+ "CONDVAR", /* 14 0x0e */
+ "JOIN", /* 15 0x0f */
+ "INTR", /* 16 0x10 */
+ "SEM", /* 17 0x11 */
+ "WAITCTX", /* 18 0x12 */
+ "NET_SEND", /* 19 0x13 */
+ "NET_REPLY" /* 20 0x14 */
+};
+
+char *
+nto_extra_thread_info (struct thread_info *ti)
+{
+ if (ti && ti->private
+ && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
+ return (char *)nto_thread_state_str [ti->private->state];
+ return "";
+}
+
void
nto_initialize_signals (void)
{