[PATCH] taskstats: cleanup do_exit() path
Oleg Nesterov [Thu, 7 Dec 2006 04:36:51 +0000 (20:36 -0800)]
do_exit:
taskstats_exit_alloc()
...
taskstats_exit_send()
taskstats_exit_free()

I think this is not good, let it be a single function exported to the core
kernel, taskstats_exit(), which does alloc + send + free itself.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Shailabh Nagar <nagar@watson.ibm.com>
Cc: Jay Lan <jlan@engr.sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

include/linux/taskstats_kern.h
kernel/exit.c
kernel/taskstats.c

index ce8a912..f1261a5 100644 (file)
 extern struct kmem_cache *taskstats_cache;
 extern struct mutex taskstats_exit_mutex;
 
-static inline void taskstats_exit_free(struct taskstats *tidstats)
-{
-       if (tidstats)
-               kmem_cache_free(taskstats_cache, tidstats);
-}
-
 static inline void taskstats_tgid_init(struct signal_struct *sig)
 {
        sig->stats = NULL;
@@ -54,17 +48,10 @@ static inline void taskstats_tgid_free(struct signal_struct *sig)
                kmem_cache_free(taskstats_cache, sig->stats);
 }
 
-extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
-extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int);
+extern void taskstats_exit(struct task_struct *, int group_dead);
 extern void taskstats_init_early(void);
 #else
-static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
-{}
-static inline void taskstats_exit_free(struct taskstats *ptidstats)
-{}
-static inline void taskstats_exit_send(struct task_struct *tsk,
-                                      struct taskstats *tidstats,
-                                      int group_dead, unsigned int cpu)
+static inline void taskstats_exit(struct task_struct *tsk, int group_dead)
 {}
 static inline void taskstats_tgid_init(struct signal_struct *sig)
 {}
index 06de6c4..4e3f919 100644 (file)
@@ -850,9 +850,7 @@ static void exit_notify(struct task_struct *tsk)
 fastcall NORET_TYPE void do_exit(long code)
 {
        struct task_struct *tsk = current;
-       struct taskstats *tidstats;
        int group_dead;
-       unsigned int mycpu;
 
        profile_task_exit(tsk);
 
@@ -890,8 +888,6 @@ fastcall NORET_TYPE void do_exit(long code)
                                current->comm, current->pid,
                                preempt_count());
 
-       taskstats_exit_alloc(&tidstats, &mycpu);
-
        acct_update_integrals(tsk);
        if (tsk->mm) {
                update_hiwater_rss(tsk->mm);
@@ -911,8 +907,8 @@ fastcall NORET_TYPE void do_exit(long code)
 #endif
        if (unlikely(tsk->audit_context))
                audit_free(tsk);
-       taskstats_exit_send(tsk, tidstats, group_dead, mycpu);
-       taskstats_exit_free(tidstats);
+
+       taskstats_exit(tsk, group_dead);
 
        exit_mm(tsk);
 
index d9d7c35..2654886 100644 (file)
@@ -119,10 +119,10 @@ static int send_reply(struct sk_buff *skb, pid_t pid)
 /*
  * Send taskstats data in @skb to listeners registered for @cpu's exit data
  */
-static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
+static void send_cpu_listeners(struct sk_buff *skb,
+                                       struct listener_list *listeners)
 {
        struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
-       struct listener_list *listeners;
        struct listener *s, *tmp;
        struct sk_buff *skb_next, *skb_cur = skb;
        void *reply = genlmsg_data(genlhdr);
@@ -135,7 +135,6 @@ static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
        }
 
        rc = 0;
-       listeners = &per_cpu(listener_array, cpu);
        down_read(&listeners->sem);
        list_for_each_entry(s, &listeners->list, list) {
                skb_next = NULL;
@@ -413,28 +412,12 @@ err:
        return rc;
 }
 
-void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
-{
-       struct listener_list *listeners;
-       /*
-        * This is the cpu on which the task is exiting currently and will
-        * be the one for which the exit event is sent, even if the cpu
-        * on which this function is running changes later.
-        */
-       *mycpu = raw_smp_processor_id();
-
-       listeners = &per_cpu(listener_array, *mycpu);
-
-       *ptidstats = NULL;
-       if (!list_empty(&listeners->list))
-               *ptidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
-}
-
 /* Send pid data out on exit */
-void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
-                       int group_dead, unsigned int mycpu)
+void taskstats_exit(struct task_struct *tsk, int group_dead)
 {
        int rc;
+       struct listener_list *listeners;
+       struct taskstats *tidstats;
        struct sk_buff *rep_skb;
        void *reply;
        size_t size;
@@ -458,12 +441,17 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
                fill_tgid_exit(tsk);
        }
 
+       listeners = &__raw_get_cpu_var(listener_array);
+       if (list_empty(&listeners->list))
+               return;
+
+       tidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
        if (!tidstats)
                return;
 
        rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
        if (rc < 0)
-               goto ret;
+               goto free_stats;
 
        rc = fill_pid(tsk->pid, tsk, tidstats);
        if (rc < 0)
@@ -492,15 +480,16 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
        nla_nest_end(rep_skb, na);
 
 send:
-       send_cpu_listeners(rep_skb, mycpu);
+       send_cpu_listeners(rep_skb, listeners);
+free_stats:
+       kmem_cache_free(taskstats_cache, tidstats);
        return;
 
 nla_put_failure:
        genlmsg_cancel(rep_skb, reply);
 err_skb:
        nlmsg_free(rep_skb);
-ret:
-       return;
+       goto free_stats;
 }
 
 static struct genl_ops taskstats_ops = {