A bit about lists

Why lists are hard

Here is a typical list field declaration — include/sched.h.

struct list_head tasks;

The list_head, defined in include/type.h, is a generic two-way list.

struct list_head {
	struct list_head *next, *prev;
};

In include/schedule.h one task structure is defined for the init task.

  extern struct task_struct init_task;

This are several more macro definitions in include/sched.h

#define next_task(p) \
	list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
#define for_each_process(p) \
	for (p = &init_task ; (p = next_task(p)) != &init_task ; )

rcu means read-copy-update. Here is the definition of list_entry_rcu for include/rculist.h.

#define list_entry_rcu(ptr, type, member) \
	({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \
	 container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
	})

Here is container_of from include/kernel.h

#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})

Here is an interesting defintion from include/stddef.h

#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

And one from include/compiler-gcc.h

#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)

There are sources of information about this throughout the internet.

There are also some ugly defines in include/rcupdate. to deal with these list.

#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
#define rcu_dereference_check(p, c) \
	__rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
#define __rcu_dereference_check(p, c, space) \
	({ \
		typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
		rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \
				      " usage"); \
		rcu_dereference_sparse(p, space); \
		smp_read_barrier_depends(); \
		((typeof(*p) __force __kernel *)(_________p1)); \
	})

All of this to get a linked list of all the running processes.

Getting a process id by number

The file kernel/pid.c contains a routine to look up processes by id.

#define pid_hashfn(nr, ns)	\
	hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
static struct hlist_head *pid_hash;

Here’s a big a hashing.

struct pid *find_pid_ns(int nr, struct pid_namespace *ns)
{
	struct hlist_node *elem;
	struct upid *pnr;

	hlist_for_each_entry_rcu(pnr, elem,
			&pid_hash[pid_hashfn(nr, ns)], pid_chain)
		if (pnr->nr == nr && pnr->ns == ns)
			return container_of(pnr, struct pid,
					numbers[ns->level]);

	return NULL;
}

Families

Look at include/linux/sched.h for the list for process familities.

Waiting channels

Try the following command to look for process wait channels.

ps -gal