[PATCH] Add debugging feature /proc/timer_list
[pandora-kernel.git] / kernel / sys.c
index a0c1a29..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 (p->signal->session != group_leader->signal->session)
+               if (task_session(p) != task_session(group_leader))
                        goto out;
                err = -EACCES;
                if (p->did_exec)
@@ -1397,16 +1412,13 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
                goto out;
 
        if (pgid != pid) {
-               struct task_struct *p;
+               struct task_struct *g =
+                       find_task_by_pid_type(PIDTYPE_PGID, pgid);
 
-               do_each_task_pid(pgid, PIDTYPE_PGID, p) {
-                       if (p->signal->session == group_leader->signal->session)
-                               goto ok_pgid;
-               } while_each_task_pid(pgid, PIDTYPE_PGID, p);
-               goto out;
+               if (!g || task_session(g) != task_session(group_leader))
+                       goto out;
        }
 
-ok_pgid:
        err = security_task_setpgid(p, pgid);
        if (err)
                goto out;
@@ -1459,7 +1471,7 @@ asmlinkage long sys_getpgrp(void)
 asmlinkage long sys_getsid(pid_t pid)
 {
        if (!pid)
-               return current->signal->session;
+               return process_session(current);
        else {
                int retval;
                struct task_struct *p;
@@ -1471,7 +1483,7 @@ asmlinkage long sys_getsid(pid_t pid)
                if (p) {
                        retval = security_task_getsid(p);
                        if (!retval)
-                               retval = p->signal->session;
+                               retval = process_session(p);
                }
                read_unlock(&tasklist_lock);
                return retval;
@@ -1484,7 +1496,6 @@ asmlinkage long sys_setsid(void)
        pid_t session;
        int err = -EPERM;
 
-       mutex_lock(&tty_mutex);
        write_lock_irq(&tasklist_lock);
 
        /* Fail if I am already a session leader */
@@ -1504,12 +1515,14 @@ asmlinkage long sys_setsid(void)
 
        group_leader->signal->leader = 1;
        __set_special_pids(session, session);
+
+       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);
 out:
        write_unlock_irq(&tasklist_lock);
-       mutex_unlock(&tty_mutex);
        return err;
 }