lkml.org 
[lkml]   [2006]   [Mar]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 01/23] tref: Implement task references.
    I think I have a really good idea.

    Forget about task ref for a moment. I thinks we can greatly
    simplify the pids management. We don't PIDTYPE_MAX hash tables,
    we need only one.

    The plan:

    kill PIDTYPE_TGID
    (copy_process/unhash_process need a simple fix)

    kill 'struct pid'

    Now,

    struct task_struct
    {
    ...
    struct list_head pids[PIDTYPE_MAX];
    struct list_head tgrp;
    ...
    };

    static inline struct task_struct *next_thread(struct task_struct *p)
    {
    return list_entry(p->tgrp.next, struct task_struct, tgrp);
    }

    struct pid_head
    {
    pid_t nr;
    struct hlist_node chain;
    struct list_head tasks[PIDTYPE_MAX];
    };

    kernel/pid.c:

    static kmem_cache_t *pid_cachep;

    static struct hlist_head *pid_hash;
    #define pid_bucket(nr) (pid_hash + pid_hashfn(nr))

    // alloc_pidmap() becomes static,
    // do_fork() calls this instead
    struct pid_head *alloc_pid(void)
    {
    struct pid_head *pid;

    pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);

    if (likely(pid)) {
    enum pid_type type;

    for (type = 0; type < PIDTYPE_MAX; ++type)
    INIT_LIST_HEAD(pid->tasks + type);

    pid->nr = alloc_pidmap();
    hlist_add_head_rcu(&pid->chain, pid_bucket(pid->nr));
    }

    return pid;
    }

    void free_pid(struct pid_head *pid)
    {
    free_pidmap(pid->nr);
    kmem_cache_free(pid_cachep, pid);
    }

    static struct pid_head *find_pid(pid_t nr)
    {
    struct hlist_node *node;
    struct pid_head *pid;

    hlist_for_each_entry_rcu(pid, node, pid_bucket(nr), chain)
    if (pid->nr == nr)
    return pid;

    return NULL;
    }

    struct list_head *find_pid_list(enum pid_type type, pid_t nr)
    {
    struct pid_head *pid;

    pid = find_pid(nr);
    if (pid)
    return pid->tasks + type;

    return NULL;
    }

    void attach_pid(struct task_struct *task, enum pid_type type, pid_t nr)
    {
    struct list_head *list;

    list = find_pid_list(type, nr);
    BUG_ON(!list);
    list_add_tail_rcu(task->pids + type, list);
    }

    static inline struct list_head *__detach_pid(struct task_struct *task,
    enum pid_type type)
    {
    struct list_head *list;

    list = task->pids + type;
    list_del_rcu(list); // it doesn't touch ->next
    return list->next;
    }

    void detach_pid(struct task_struct *task, enum pid_type type)
    {
    struct list_head *head;
    struct pid_head *pid;

    head = __detach_pid(task, type);
    if (!list_empty(head))
    return;

    pid = list_entry(head, struct pid_head, tasks[type]);

    for (type = 0; type < PIDTYPE_MAX; ++type)
    if (!list_empty(pid->tasks + type))
    return;

    free_pid(pid);
    }

    We don't need ugly do_each_task_pid/while_each_task_pid anymore:

    #define for_each_task_pid(head, pid, type, task) \
    if ((head = find_pid_list(type, pid))) \
    list_for_each_entry(task, head, pids[type])


    And noe we can inplement pid_ref almost for free, just add ->count
    to 'struct pid_head'.

    What do you think?

    Oleg.
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2006-03-06 22:41    [W:2.577 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site