Casey Kuball
Casey Kuball

Reputation: 7965

List all threads within the current process?

I'm trying to implement a syscall which allows me to get the number of threads for the current process. I am new to the Linux kernel, and so my understanding of it is limited.

Currently, I am trying to iterate through all the task_structs, and compare their thread group leader's PID with the current thread group leader's PID:

// ...
int nthreads = 0;
struct task_struct *task_it;
for_each_process(task_it) {
    if (task_it->group_leader->pid == current->group_leader->pid) {
        nthreads++;
    }
}
// ...

However, this doesn't seem to be working (a quick test spawning some pthreads is still giving 1. What about the group_leader is common to all threads in the same process?

Upvotes: 3

Views: 3767

Answers (2)

caf
caf

Reputation: 239341

The problem with your code is that what the kernel calls a PID (the pid field of task_struct) is what userspace calls a TID (ie. it's what's returned by sys_gettid() and is unique per thread). What userspace calls a PID is called a TGID in the kernel (for "task group ID") - that's what the sys_getpid() syscall returns.

You don't need to actually check the TGID, though - just comparing the struct task_struct * pointers is enough:

if (task_it->group_leader == current->group_leader) {

By the way, you could just iterate over the thread_group list that current is a member of (with while_each_thread()), then you wouldn't need any test at all. Or even better, just use get_nr_threads(current).

Note that all methods that loop over the task lists need to be wrapped in rcu_read_lock(); / rcu_read_unlock(); to be correct.

Upvotes: 4

davepmiller
davepmiller

Reputation: 2708

This chunk of code is a good demonstration.

The following C program creates a list of all processes in the process table of a node and shows in one column the number of threads for any single process. Using this tool, it was possible to identify that the network daemon created a new thread anytime a network problem occurred. A severe network problem was responsible for the logon problems.

#include "sys/param.h"
#include "sys/pstat.h"

int main ( void )
{

  struct pst_status * psa = NULL;   
  struct pst_status * prc = NULL;    
  struct pst_dynamic  psd;
  long                nproc = 0;      
  long                thsum = 0;       
  long                i;                

  if ( pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1 )
    (void)perror("pstat_getdynamic failed");

  // Get the number of active processes from pst_dynamic 
  nproc  = psd.psd_activeprocs;  
  psa    = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));

  // Read the info about the active processes into the array 'psa' 
  if ( pstat_getproc(psa, sizeof(struct pst_status), nproc, 0) == -1 )
    (void)perror("pstat_getproc failed");

  (void)printf("\n\n------------------------------------------------------------------------------");
  (void)printf("\n %5s | %5s |%7s| %5s | %s", "PID", "UID", "Threads", "RSS", "Command");
  (void)printf("\n------------------------------------------------------------------------------");

  // Report the process info as required
  prc = (struct pst_status *)psa;       
  for (i=0; i < nproc; i++) 
  {
    (void)printf("\n %5ld | ", prc->pst_pid);
    (void)printf("%5ld | ", prc->pst_uid);
    (void)printf("%5ld | ", prc->pst_nlwps);
    (void)printf("%5ld | ", prc->pst_rssize);
    (void)printf("%s ", prc->pst_cmd);
    thsum += prc->pst_nlwps;
    ++prc;         
  } 

  (void)printf("\n\n*** %ld processes, %ld threads running\n\n", nproc, thsum);
  (void)free(psa);       
  (void)exit(0);
} 

Found here: http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=060818f70fe0211018f70fe02110275d6e10RCRD

Here's another link using task_struct: http://tuxthink.blogspot.com/2011/03/using-foreachprocess-in-proc-entry.html

Upvotes: 1

Related Questions