[PATCH] lockdep: core
[linux-2.6-block.git] / kernel / fork.c
index 49adc0e8d47ccf3b51af4e5b32ffd4210aeaf955..7f48abdd7bb60336b245b897c61e94e9538fb05a 100644 (file)
@@ -11,7 +11,6 @@
  * management can be a bitch. See 'mm/memory.c': 'copy_page_range()'
  */
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/unistd.h>
@@ -104,6 +103,7 @@ static kmem_cache_t *mm_cachep;
 void free_task(struct task_struct *tsk)
 {
        free_thread_info(tsk->thread_info);
+       rt_mutex_debug_task_free(tsk);
        free_task_struct(tsk);
 }
 EXPORT_SYMBOL(free_task);
@@ -874,6 +874,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
                tsk->it_prof_expires =
                        secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
        }
+       acct_init_pacct(&sig->pacct);
 
        return 0;
 }
@@ -912,6 +913,15 @@ asmlinkage long sys_set_tid_address(int __user *tidptr)
        return current->pid;
 }
 
+static inline void rt_mutex_init_task(struct task_struct *p)
+{
+#ifdef CONFIG_RT_MUTEXES
+       spin_lock_init(&p->pi_lock);
+       plist_head_init(&p->pi_waiters, &p->pi_lock);
+       p->pi_blocked_on = NULL;
+#endif
+}
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -958,6 +968,10 @@ static task_t *copy_process(unsigned long clone_flags,
        if (!p)
                goto fork_out;
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+       DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
+       DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
+#endif
        retval = -EAGAIN;
        if (atomic_read(&p->user->processes) >=
                        p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
@@ -992,13 +1006,10 @@ static task_t *copy_process(unsigned long clone_flags,
                if (put_user(p->pid, parent_tidptr))
                        goto bad_fork_cleanup;
 
-       p->proc_dentry = NULL;
-
        INIT_LIST_HEAD(&p->children);
        INIT_LIST_HEAD(&p->sibling);
        p->vfork_done = NULL;
        spin_lock_init(&p->alloc_lock);
-       spin_lock_init(&p->proc_lock);
 
        clear_tsk_thread_flag(p, TIF_SIGPENDING);
        init_sigpending(&p->pending);
@@ -1035,6 +1046,28 @@ static task_t *copy_process(unsigned long clone_flags,
        }
        mpol_fix_fork_child_flag(p);
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+       p->irq_events = 0;
+       p->hardirqs_enabled = 0;
+       p->hardirq_enable_ip = 0;
+       p->hardirq_enable_event = 0;
+       p->hardirq_disable_ip = _THIS_IP_;
+       p->hardirq_disable_event = 0;
+       p->softirqs_enabled = 1;
+       p->softirq_enable_ip = _THIS_IP_;
+       p->softirq_enable_event = 0;
+       p->softirq_disable_ip = 0;
+       p->softirq_disable_event = 0;
+       p->hardirq_context = 0;
+       p->softirq_context = 0;
+#endif
+#ifdef CONFIG_LOCKDEP
+       p->lockdep_depth = 0; /* no locks held yet */
+       p->curr_chain_key = 0;
+       p->lockdep_recursion = 0;
+#endif
+
+       rt_mutex_init_task(p);
 
 #ifdef CONFIG_DEBUG_MUTEXES
        p->blocked_on = NULL; /* not blocked yet */
@@ -1078,6 +1111,9 @@ static task_t *copy_process(unsigned long clone_flags,
 #ifdef CONFIG_COMPAT
        p->compat_robust_list = NULL;
 #endif
+       INIT_LIST_HEAD(&p->pi_state_list);
+       p->pi_state_cache = NULL;
+
        /*
         * sigaltstack should be cleared when sharing the same VM
         */
@@ -1158,18 +1194,6 @@ static task_t *copy_process(unsigned long clone_flags,
        }
 
        if (clone_flags & CLONE_THREAD) {
-               /*
-                * Important: if an exit-all has been started then
-                * do not create this new thread - the whole thread
-                * group is supposed to exit anyway.
-                */
-               if (current->signal->flags & SIGNAL_GROUP_EXIT) {
-                       spin_unlock(&current->sighand->siglock);
-                       write_unlock_irq(&tasklist_lock);
-                       retval = -EAGAIN;
-                       goto bad_fork_cleanup_namespace;
-               }
-
                p->group_leader = current->group_leader;
                list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);