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