linux-bk/kernel/pid.c
<<
>>
Prefs
   1/*
   2 * Generic pidhash and scalable, time-bounded PID allocator
   3 *
   4 * (C) 2002 William Irwin, IBM
   5 * (C) 2002 Ingo Molnar, Red Hat
   6 *
   7 * pid-structures are backing objects for tasks sharing a given ID to chain
   8 * against. There is very little to them aside from hashing them and
   9 * parking tasks using given ID's on a list.
  10 *
  11 * The hash is always changed with the tasklist_lock write-acquired,
  12 * and the hash is only accessed with the tasklist_lock at least
  13 * read-acquired, so there's no additional SMP locking needed here.
  14 *
  15 * We have a list of bitmap pages, which bitmaps represent the PID space.
  16 * Allocating and freeing PIDs is completely lockless. The worst-case
  17 * allocation scenario when all but one out of 1 million PIDs possible are
  18 * allocated already: the scanning of 32 list entries and at most PAGE_SIZE
  19 * bytes. The typical fastpath is a single successful setbit. Freeing is O(1).
  20 */
  21
  22#include <linux/mm.h>
  23#include <linux/slab.h>
  24#include <linux/init.h>
  25#include <linux/bootmem.h>
  26
  27#define PIDHASH_SIZE 4096
  28#define pid_hashfn(nr) ((nr >> 8) ^ nr) & (PIDHASH_SIZE - 1)
  29static struct list_head pid_hash[PIDTYPE_MAX][PIDHASH_SIZE];
  30
  31int pid_max = PID_MAX_DEFAULT;
  32int last_pid;
  33
  34#define RESERVED_PIDS           300
  35
  36#define PIDMAP_ENTRIES          (PID_MAX_LIMIT/PAGE_SIZE/8)
  37#define BITS_PER_PAGE           (PAGE_SIZE*8)
  38#define BITS_PER_PAGE_MASK      (BITS_PER_PAGE-1)
  39
  40/*
  41 * PID-map pages start out as NULL, they get allocated upon
  42 * first use and are never deallocated. This way a low pid_max
  43 * value does not cause lots of bitmaps to be allocated, but
  44 * the scheme scales to up to 4 million PIDs, runtime.
  45 */
  46typedef struct pidmap {
  47        atomic_t nr_free;
  48        void *page;
  49} pidmap_t;
  50
  51static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
  52         { [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };
  53
  54static pidmap_t *map_limit = pidmap_array + PIDMAP_ENTRIES;
  55
  56inline void free_pidmap(int pid)
  57{
  58        pidmap_t *map = pidmap_array + pid / BITS_PER_PAGE;
  59        int offset = pid & BITS_PER_PAGE_MASK;
  60
  61        clear_bit(offset, map->page);
  62        atomic_inc(&map->nr_free);
  63}
  64
  65/*
  66 * Here we search for the next map that has free bits left.
  67 * Normally the next map has free PIDs.
  68 */
  69static inline pidmap_t *next_free_map(pidmap_t *map, int *max_steps)
  70{
  71        while (--*max_steps) {
  72                if (++map == map_limit)
  73                        map = pidmap_array;
  74                if (unlikely(!map->page)) {
  75                        unsigned long page = get_zeroed_page(GFP_KERNEL);
  76                        /*
  77                         * Free the page if someone raced with us
  78                         * installing it:
  79                         */
  80                        if (cmpxchg(&map->page, NULL, (void *) page))
  81                                free_page(page);
  82                        if (!map->page)
  83                                break;
  84                }
  85                if (atomic_read(&map->nr_free))
  86                        return map;
  87        }
  88        return NULL;
  89}
  90
  91int alloc_pidmap(void)
  92{
  93        int pid, offset, max_steps = PIDMAP_ENTRIES + 1;
  94        pidmap_t *map;
  95
  96        pid = last_pid + 1;
  97        if (pid >= pid_max)
  98                pid = RESERVED_PIDS;
  99
 100        offset = pid & BITS_PER_PAGE_MASK;
 101        map = pidmap_array + pid / BITS_PER_PAGE;
 102
 103        if (likely(map->page && !test_and_set_bit(offset, map->page))) {
 104                /*
 105                 * There is a small window for last_pid updates to race,
 106                 * but in that case the next allocation will go into the
 107                 * slowpath and that fixes things up.
 108                 */
 109return_pid:
 110                atomic_dec(&map->nr_free);
 111                last_pid = pid;
 112                return pid;
 113        }
 114        
 115        if (!offset || !atomic_read(&map->nr_free)) {
 116next_map:
 117                map = next_free_map(map, &max_steps);
 118                if (!map)
 119                        goto failure;
 120                offset = 0;
 121        }
 122        /*
 123         * Find the next zero bit:
 124         */
 125scan_more:
 126        offset = find_next_zero_bit(map->page, BITS_PER_PAGE, offset);
 127        if (offset == BITS_PER_PAGE)
 128                goto next_map;
 129        if (test_and_set_bit(offset, map->page))
 130                goto scan_more;
 131
 132        /* we got the PID: */
 133        pid = (map - pidmap_array) * BITS_PER_PAGE + offset;
 134        goto return_pid;
 135
 136failure:
 137        return -1;
 138}
 139
 140inline struct pid *find_pid(enum pid_type type, int nr)
 141{
 142        struct list_head *elem, *bucket = &pid_hash[type][pid_hashfn(nr)];
 143        struct pid *pid;
 144
 145        list_for_each_noprefetch(elem, bucket) {
 146                pid = list_entry(elem, struct pid, hash_chain);
 147                if (pid->nr == nr)
 148                        return pid;
 149        }
 150        return NULL;
 151}
 152
 153int attach_pid(task_t *task, enum pid_type type, int nr)
 154{
 155        struct pid *pid = find_pid(type, nr);
 156
 157        if (pid)
 158                atomic_inc(&pid->count);
 159        else {
 160                pid = &task->pids[type].pid;
 161                pid->nr = nr;
 162                atomic_set(&pid->count, 1);
 163                INIT_LIST_HEAD(&pid->task_list);
 164                pid->task = task;
 165                get_task_struct(task);
 166                list_add(&pid->hash_chain, &pid_hash[type][pid_hashfn(nr)]);
 167        }
 168        list_add(&task->pids[type].pid_chain, &pid->task_list);
 169        task->pids[type].pidptr = pid;
 170
 171        return 0;
 172}
 173
 174void detach_pid(task_t *task, enum pid_type type)
 175{
 176        struct pid_link *link = task->pids + type;
 177        struct pid *pid = link->pidptr;
 178        int nr;
 179
 180        list_del(&link->pid_chain);
 181        if (!atomic_dec_and_test(&pid->count))
 182                return;
 183
 184        nr = pid->nr;
 185        list_del(&pid->hash_chain);
 186        put_task_struct(pid->task);
 187
 188        for (type = 0; type < PIDTYPE_MAX; ++type)
 189                if (find_pid(type, nr))
 190                        return;
 191        free_pidmap(nr);
 192}
 193
 194extern task_t *find_task_by_pid(int nr)
 195{
 196        struct pid *pid = find_pid(PIDTYPE_PID, nr);
 197
 198        if (!pid)
 199                return NULL;
 200        return pid_task(pid->task_list.next, PIDTYPE_PID);
 201}
 202
 203void __init pidhash_init(void)
 204{
 205        int i, j;
 206
 207        /*
 208         * Allocate PID 0, and hash it via all PID types:
 209         */
 210        pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL);
 211        set_bit(0, pidmap_array->page);
 212        atomic_dec(&pidmap_array->nr_free);
 213
 214        for (i = 0; i < PIDTYPE_MAX; i++) {
 215                for (j = 0; j < PIDHASH_SIZE; j++)
 216                        INIT_LIST_HEAD(&pid_hash[i][j]);
 217                attach_pid(current, i, 0);
 218        }
 219}
 220
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.