[PATCH] Add debugging feature /proc/timer_list
[pandora-kernel.git] / kernel / sys.c
index c7675c1..123b165 100644 (file)
@@ -215,7 +215,7 @@ EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
  *     This routine uses RCU to synchronize with changes to the chain.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then atomic_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -313,7 +313,7 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
  *     run in a process context, so they are allowed to block.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then blocking_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -323,11 +323,18 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
                unsigned long val, void *v)
 {
-       int ret;
+       int ret = NOTIFY_DONE;
 
-       down_read(&nh->rwsem);
-       ret = notifier_call_chain(&nh->head, val, v);
-       up_read(&nh->rwsem);
+       /*
+        * We check the head outside the lock, but if this access is
+        * racy then it does not matter what the result of the test
+        * is, we re-check the list after having taken the lock anyway:
+        */
+       if (rcu_dereference(nh->head)) {
+               down_read(&nh->rwsem);
+               ret = notifier_call_chain(&nh->head, val, v);
+               up_read(&nh->rwsem);
+       }
        return ret;
 }
 
@@ -386,7 +393,7 @@ EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
  *     All locking must be provided by the caller.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then raw_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -480,7 +487,7 @@ EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
  *     run in a process context, so they are allowed to block.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then srcu_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -531,7 +538,7 @@ EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
  *     Registers a function with the list of functions
  *     to be called at reboot time.
  *
- *     Currently always returns zero, as blocking_notifier_chain_register
+ *     Currently always returns zero, as blocking_notifier_chain_register()
  *     always returns zero.
  */
  
@@ -589,6 +596,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
        struct task_struct *g, *p;
        struct user_struct *user;
        int error = -EINVAL;
+       struct pid *pgrp;
 
        if (which > 2 || which < 0)
                goto out;
@@ -603,18 +611,21 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
        read_lock(&tasklist_lock);
        switch (which) {
                case PRIO_PROCESS:
-                       if (!who)
-                               who = current->pid;
-                       p = find_task_by_pid(who);
+                       if (who)
+                               p = find_task_by_pid(who);
+                       else
+                               p = current;
                        if (p)
                                error = set_one_prio(p, niceval, error);
                        break;
                case PRIO_PGRP:
-                       if (!who)
-                               who = process_group(current);
-                       do_each_task_pid(who, PIDTYPE_PGID, p) {
+                       if (who)
+                               pgrp = find_pid(who);
+                       else
+                               pgrp = task_pgrp(current);
+                       do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
                                error = set_one_prio(p, niceval, error);
-                       } while_each_task_pid(who, PIDTYPE_PGID, p);
+                       } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
                        break;
                case PRIO_USER:
                        user = current->user;
@@ -649,6 +660,7 @@ asmlinkage long sys_getpriority(int which, int who)
        struct task_struct *g, *p;
        struct user_struct *user;
        long niceval, retval = -ESRCH;
+       struct pid *pgrp;
 
        if (which > 2 || which < 0)
                return -EINVAL;
@@ -656,9 +668,10 @@ asmlinkage long sys_getpriority(int which, int who)
        read_lock(&tasklist_lock);
        switch (which) {
                case PRIO_PROCESS:
-                       if (!who)
-                               who = current->pid;
-                       p = find_task_by_pid(who);
+                       if (who)
+                               p = find_task_by_pid(who);
+                       else
+                               p = current;
                        if (p) {
                                niceval = 20 - task_nice(p);
                                if (niceval > retval)
@@ -666,13 +679,15 @@ asmlinkage long sys_getpriority(int which, int who)
                        }
                        break;
                case PRIO_PGRP:
-                       if (!who)
-                               who = process_group(current);
-                       do_each_task_pid(who, PIDTYPE_PGID, p) {
+                       if (who)
+                               pgrp = find_pid(who);
+                       else
+                               pgrp = task_pgrp(current);
+                       do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
                                niceval = 20 - task_nice(p);
                                if (niceval > retval)
                                        retval = niceval;
-                       } while_each_task_pid(who, PIDTYPE_PGID, p);
+                       } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
                        break;
                case PRIO_USER:
                        user = current->user;
@@ -1381,7 +1396,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
 
        if (p->real_parent == group_leader) {
                err = -EPERM;
-               if (process_session(p) != process_session(group_leader))
+               if (task_session(p) != task_session(group_leader))
                        goto out;
                err = -EACCES;
                if (p->did_exec)
@@ -1400,7 +1415,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
                struct task_struct *g =
                        find_task_by_pid_type(PIDTYPE_PGID, pgid);
 
-               if (!g || process_session(g) != process_session(group_leader))
+               if (!g || task_session(g) != task_session(group_leader))
                        goto out;
        }
 
@@ -1503,7 +1518,6 @@ asmlinkage long sys_setsid(void)
 
        spin_lock(&group_leader->sighand->siglock);
        group_leader->signal->tty = NULL;
-       group_leader->signal->tty_old_pgrp = 0;
        spin_unlock(&group_leader->sighand->siglock);
 
        err = process_group(group_leader);