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