diff options
| author | Ingo Molnar <mingo@elte.hu> | 2002-09-19 00:25:45 -0700 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2002-09-19 00:25:45 -0700 |
| commit | 64cf8edb62434d9efe3ae4ebdb4d73716ad27d9a (patch) | |
| tree | fc4400a9a94fd7f810d2bacec967aa23c3c2b482 /include/linux | |
| parent | a3a132ea1d82242539aa89143fb70cf864f6a7d5 (diff) | |
[PATCH] generic-pidhash-2.5.36-J2, BK-curr
This is the latest version of the generic pidhash patch. The biggest
change is the removal of separately allocated pid structures: they are
now part of the task structure and the first task that uses a PID will
provide the pid structure. Task refcounting is used to avoid the
freeing of the task structure before every member of a process group or
session has exited.
This approach has a number of advantages besides the performance gains.
Besides simplifying the whole hashing code significantly, attach_pid()
is now fundamentally atomic and can be called during create_process()
without worrying about task-list side-effects. It does not have to
re-search the pidhash to find out about raced PID-adding either, and
attach_pid() cannot fail due to OOM. detach_pid() can do a simple
put_task_struct() instead of the kmem_cache_free().
The only minimal downside is the potential pending task structures after
session leaders or group leaders have exited - but the number of orphan
sessions and process groups is usually very low - and even if it's
higher, this can be regarded as a slow execution of the final
deallocation of the session leader, not some additional burden.
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/list.h | 4 | ||||
| -rw-r--r-- | include/linux/pid.h | 63 | ||||
| -rw-r--r-- | include/linux/sched.h | 41 | ||||
| -rw-r--r-- | include/linux/threads.h | 9 |
4 files changed, 80 insertions, 37 deletions
diff --git a/include/linux/list.h b/include/linux/list.h index 1e311d042cab..7eb1a4de4a75 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -195,6 +195,10 @@ static inline void list_splice_init(struct list_head *list, #define list_for_each(pos, head) \ for (pos = (head)->next, prefetch(pos->next); pos != (head); \ pos = pos->next, prefetch(pos->next)) + +#define list_for_each_noprefetch(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + /** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop counter. diff --git a/include/linux/pid.h b/include/linux/pid.h new file mode 100644 index 000000000000..d5eb20df44c1 --- /dev/null +++ b/include/linux/pid.h @@ -0,0 +1,63 @@ +#ifndef _LINUX_PID_H +#define _LINUX_PID_H + +enum pid_type +{ + PIDTYPE_PID, + PIDTYPE_PGID, + PIDTYPE_SID, + PIDTYPE_MAX +}; + +struct pid +{ + int nr; + atomic_t count; + struct task_struct *task; + struct list_head task_list; + struct list_head hash_chain; +}; + +struct pid_link +{ + struct list_head pid_chain; + struct pid *pidptr; + struct pid pid; +}; + +#define pid_task(elem, type) \ + list_entry(elem, struct task_struct, pids[type].pid_chain) + +/* + * attach_pid() must be called with the tasklist_lock write-held. + * + * It might unlock the tasklist_lock for allocation, so this + * function must be called after installing all other links of + * a new task. + */ +extern int FASTCALL(attach_pid(struct task_struct *, enum pid_type, int)); + +/* + * detach_pid() must be called with the tasklist_lock write-held. + */ +extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type)); + +/* + * look up a PID in the hash table. Must be called with the tasklist_lock + * held. + */ +extern struct pid *FASTCALL(find_pid(enum pid_type, int)); + +extern int alloc_pidmap(void); +extern void FASTCALL(free_pidmap(int)); + +#define for_each_task_pid(who, type, task, elem, pid) \ + if ((pid = find_pid(type, who))) \ + for (elem = pid->task_list.next, \ + prefetch(elem->next), \ + task = pid_task(elem, type); \ + elem != &pid->task_list; \ + elem = elem->next, prefetch(elem->next), \ + task = pid_task(elem, type)) + +#endif /* _LINUX_PID_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index f0cf18022ae2..18dbb67449a4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -28,6 +28,7 @@ extern unsigned long event; #include <linux/fs_struct.h> #include <linux/compiler.h> #include <linux/completion.h> +#include <linux/pid.h> struct exec_domain; @@ -266,6 +267,8 @@ struct user_struct { atomic_inc(&__user->__count); \ __user; }) +extern struct user_struct *find_user(uid_t); + extern struct user_struct root_user; #define INIT_USER (&root_user) @@ -326,9 +329,8 @@ struct task_struct { struct task_struct *group_leader; struct list_head thread_group; - /* PID hash table linkage. */ - struct task_struct *pidhash_next; - struct task_struct **pidhash_pprev; + /* PID/PID hash table linkage. */ + struct pid_link pids[PIDTYPE_MAX]; wait_queue_head_t wait_chldexit; /* for wait4() */ struct completion *vfork_done; /* for vfork() */ @@ -474,38 +476,7 @@ extern struct task_struct init_task; extern struct mm_struct init_mm; -/* PID hashing. (shouldnt this be dynamic?) */ -#define PIDHASH_SZ 8192 -extern struct task_struct *pidhash[PIDHASH_SZ]; - -#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) - -static inline void hash_pid(struct task_struct *p) -{ - struct task_struct **htable = &pidhash[pid_hashfn(p->pid)]; - - if((p->pidhash_next = *htable) != NULL) - (*htable)->pidhash_pprev = &p->pidhash_next; - *htable = p; - p->pidhash_pprev = htable; -} - -static inline void unhash_pid(struct task_struct *p) -{ - if(p->pidhash_next) - p->pidhash_next->pidhash_pprev = p->pidhash_pprev; - *p->pidhash_pprev = p->pidhash_next; -} - -static inline struct task_struct *find_task_by_pid(int pid) -{ - struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)]; - - for(p = *htable; p && p->pid != pid; p = p->pidhash_next) - ; - - return p; -} +extern struct task_struct *find_task_by_pid(int pid); /* per-UID process charging. */ extern struct user_struct * alloc_uid(uid_t); diff --git a/include/linux/threads.h b/include/linux/threads.h index 8e0ddb960524..b04f5c851ed8 100644 --- a/include/linux/threads.h +++ b/include/linux/threads.h @@ -17,8 +17,13 @@ #define MIN_THREADS_LEFT_FOR_ROOT 4 /* - * This controls the maximum pid allocated to a process + * This controls the default maximum pid allocated to a process */ -#define DEFAULT_PID_MAX 0x8000 +#define PID_MAX_DEFAULT 0x8000 + +/* + * A maximum of 4 million PIDs should be enough for a while: + */ +#define PID_MAX_LIMIT (4*1024*1024) #endif |
