Even though we can get a lot of information about processes (above), in QNX Neutrino a process doesn't actually do anything on its own — it acts as a container for multiple threads. Therefore, to find out about the threads, we can call devctl() with the following commands:
There are other commands available for manipulating the thread status (such as starting or stopping a thread, etc.), which we won't discuss here.
First we need a way of iterating through all the threads in a process. Earlier in this chapter, we called out to a function do_process(), which was responsible for the per-process processing. Let's now see what this function does and how it relates to finding all the threads in the process:
void do_process (int pid, int fd, char *name) { procfs_status status; printf ("PROCESS ID %d\n", pid); // dump out per-process information dump_procfs_info (fd, pid); dump_procfs_map_info (fd, pid); dump_procfs_timer (fd, pid); dump_procfs_irq (fd, pid); // now iterate through all the threads status.tid = 1; while (1) { if (devctl (fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0) != EOK) { break; } else { do_thread (fd, status.tid, &status); status.tid++; } } }
The do_process() function dumps out all the per-process information that we discussed above, and then iterates through the threads, calling do_thread() for each one. The trick here is to start with thread number 1 and call devctl() with DCMD_PROC_TIDSTATUS until it returns something other than EOK. (QNX Neutrino starts numbering threads at 1.)
The magic that happens is that the kernel will return information about the thread specified in the tid member of status if it has it; otherwise, it will return information on the next available thread ID (or return something other than EOK to indicate it's done).