]> Pileus Git - ~andy/linux/blobdiff - kernel/pid.c
[PATCH] Move pidmap to pspace.h
[~andy/linux] / kernel / pid.c
index eeb836b65ca4ec887e6dc83c73e73004ac066978..8234bd08a3cb32d44a12f3efe865830443fa86b6 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/hash.h>
+#include <linux/pspace.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
 static struct hlist_head *pid_hash;
@@ -40,7 +41,6 @@ int last_pid;
 int pid_max_min = RESERVED_PIDS + 1;
 int pid_max_max = PID_MAX_LIMIT;
 
-#define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
 #define BITS_PER_PAGE          (PAGE_SIZE*8)
 #define BITS_PER_PAGE_MASK     (BITS_PER_PAGE-1)
 #define mk_pid(map, off)       (((map) - pidmap_array)*BITS_PER_PAGE + (off))
@@ -53,12 +53,7 @@ int pid_max_max = PID_MAX_LIMIT;
  * value does not cause lots of bitmaps to be allocated, but
  * the scheme scales to up to 4 million PIDs, runtime.
  */
-typedef struct pidmap {
-       atomic_t nr_free;
-       void *page;
-} pidmap_t;
-
-static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
+static struct pidmap pidmap_array[PIDMAP_ENTRIES] =
         { [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };
 
 /*
@@ -78,7 +73,7 @@ static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
 
 static fastcall void free_pidmap(int pid)
 {
-       pidmap_t *map = pidmap_array + pid / BITS_PER_PAGE;
+       struct pidmap *map = pidmap_array + pid / BITS_PER_PAGE;
        int offset = pid & BITS_PER_PAGE_MASK;
 
        clear_bit(offset, map->page);
@@ -88,7 +83,7 @@ static fastcall void free_pidmap(int pid)
 static int alloc_pidmap(void)
 {
        int i, offset, max_scan, pid, last = last_pid;
-       pidmap_t *map;
+       struct pidmap *map;
 
        pid = last + 1;
        if (pid >= pid_max)
@@ -145,6 +140,23 @@ static int alloc_pidmap(void)
        return -1;
 }
 
+static int next_pidmap(int last)
+{
+       int offset;
+       struct pidmap *map;
+
+       offset = (last + 1) & BITS_PER_PAGE_MASK;
+       map = &pidmap_array[(last + 1)/BITS_PER_PAGE];
+       for (; map < &pidmap_array[PIDMAP_ENTRIES]; map++, offset = 0) {
+               if (unlikely(!map->page))
+                       continue;
+               offset = find_next_bit((map)->page, BITS_PER_PAGE, offset);
+               if (offset < BITS_PER_PAGE)
+                       return mk_pid(map, offset);
+       }
+       return -1;
+}
+
 fastcall void put_pid(struct pid *pid)
 {
        if (!pid)
@@ -153,6 +165,7 @@ fastcall void put_pid(struct pid *pid)
             atomic_dec_and_test(&pid->count))
                kmem_cache_free(pid_cachep, pid);
 }
+EXPORT_SYMBOL_GPL(put_pid);
 
 static void delayed_put_pid(struct rcu_head *rhp)
 {
@@ -217,15 +230,13 @@ struct pid * fastcall find_pid(int nr)
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(find_pid);
 
-int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
+int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr)
 {
        struct pid_link *link;
        struct pid *pid;
 
-       WARN_ON(!task->pid); /* to be removed soon */
-       WARN_ON(!nr); /* to be removed soon */
-
        link = &task->pids[type];
        link->pid = pid = find_pid(nr);
        hlist_add_head_rcu(&link->node, &pid->tasks[type]);
@@ -233,7 +244,7 @@ int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
        return 0;
 }
 
-void fastcall detach_pid(task_t *task, enum pid_type type)
+void fastcall detach_pid(struct task_struct *task, enum pid_type type)
 {
        struct pid_link *link;
        struct pid *pid;
@@ -252,6 +263,15 @@ void fastcall detach_pid(task_t *task, enum pid_type type)
        free_pid(pid);
 }
 
+/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
+void fastcall transfer_pid(struct task_struct *old, struct task_struct *new,
+                          enum pid_type type)
+{
+       new->pids[type].pid = old->pids[type].pid;
+       hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
+       old->pids[type].pid = NULL;
+}
+
 struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
 {
        struct task_struct *result = NULL;
@@ -267,7 +287,7 @@ struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
 /*
  * Must be called under rcu_read_lock() or with tasklist_lock read-held.
  */
-task_t *find_task_by_pid_type(int type, int nr)
+struct task_struct *find_task_by_pid_type(int type, int nr)
 {
        return pid_task(find_pid(nr), type);
 }
@@ -296,6 +316,26 @@ struct pid *find_get_pid(pid_t nr)
        return pid;
 }
 
+/*
+ * Used by proc to find the first pid that is greater then or equal to nr.
+ *
+ * If there is a pid at nr this function is exactly the same as find_pid.
+ */
+struct pid *find_ge_pid(int nr)
+{
+       struct pid *pid;
+
+       do {
+               pid = find_pid(nr);
+               if (pid)
+                       break;
+               nr = next_pidmap(nr);
+       } while (nr > 0);
+
+       return pid;
+}
+EXPORT_SYMBOL_GPL(find_get_pid);
+
 /*
  * The pid hash table is scaled according to the amount of memory in the
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or