aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2008-10-21 14:42:20 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-10-21 14:42:20 -0400
commitb876d08f816527af257e13d89fb0d3b4b849223c (patch)
tree40569f568230f918ca55f04b355e251747f913ed /kernel/fork.c
parentb364776ad1208a71f0c53578c84619a395412a8d (diff)
parent2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/pci/dmar.c
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c95
1 files changed, 53 insertions, 42 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 30de644a40c4..4d093552dd6e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -58,6 +58,7 @@
58#include <linux/tty.h> 58#include <linux/tty.h>
59#include <linux/proc_fs.h> 59#include <linux/proc_fs.h>
60#include <linux/blkdev.h> 60#include <linux/blkdev.h>
61#include <trace/sched.h>
61 62
62#include <asm/pgtable.h> 63#include <asm/pgtable.h>
63#include <asm/pgalloc.h> 64#include <asm/pgalloc.h>
@@ -759,15 +760,44 @@ void __cleanup_sighand(struct sighand_struct *sighand)
759 kmem_cache_free(sighand_cachep, sighand); 760 kmem_cache_free(sighand_cachep, sighand);
760} 761}
761 762
763
764/*
765 * Initialize POSIX timer handling for a thread group.
766 */
767static void posix_cpu_timers_init_group(struct signal_struct *sig)
768{
769 /* Thread group counters. */
770 thread_group_cputime_init(sig);
771
772 /* Expiration times and increments. */
773 sig->it_virt_expires = cputime_zero;
774 sig->it_virt_incr = cputime_zero;
775 sig->it_prof_expires = cputime_zero;
776 sig->it_prof_incr = cputime_zero;
777
778 /* Cached expiration times. */
779 sig->cputime_expires.prof_exp = cputime_zero;
780 sig->cputime_expires.virt_exp = cputime_zero;
781 sig->cputime_expires.sched_exp = 0;
782
783 /* The timer lists. */
784 INIT_LIST_HEAD(&sig->cpu_timers[0]);
785 INIT_LIST_HEAD(&sig->cpu_timers[1]);
786 INIT_LIST_HEAD(&sig->cpu_timers[2]);
787}
788
762static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) 789static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
763{ 790{
764 struct signal_struct *sig; 791 struct signal_struct *sig;
765 int ret; 792 int ret;
766 793
767 if (clone_flags & CLONE_THREAD) { 794 if (clone_flags & CLONE_THREAD) {
768 atomic_inc(&current->signal->count); 795 ret = thread_group_cputime_clone_thread(current);
769 atomic_inc(&current->signal->live); 796 if (likely(!ret)) {
770 return 0; 797 atomic_inc(&current->signal->count);
798 atomic_inc(&current->signal->live);
799 }
800 return ret;
771 } 801 }
772 sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); 802 sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
773 tsk->signal = sig; 803 tsk->signal = sig;
@@ -795,40 +825,25 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
795 sig->it_real_incr.tv64 = 0; 825 sig->it_real_incr.tv64 = 0;
796 sig->real_timer.function = it_real_fn; 826 sig->real_timer.function = it_real_fn;
797 827
798 sig->it_virt_expires = cputime_zero;
799 sig->it_virt_incr = cputime_zero;
800 sig->it_prof_expires = cputime_zero;
801 sig->it_prof_incr = cputime_zero;
802
803 sig->leader = 0; /* session leadership doesn't inherit */ 828 sig->leader = 0; /* session leadership doesn't inherit */
804 sig->tty_old_pgrp = NULL; 829 sig->tty_old_pgrp = NULL;
805 sig->tty = NULL; 830 sig->tty = NULL;
806 831
807 sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; 832 sig->cutime = sig->cstime = cputime_zero;
808 sig->gtime = cputime_zero; 833 sig->gtime = cputime_zero;
809 sig->cgtime = cputime_zero; 834 sig->cgtime = cputime_zero;
810 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; 835 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
811 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; 836 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
812 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; 837 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
813 task_io_accounting_init(&sig->ioac); 838 task_io_accounting_init(&sig->ioac);
814 sig->sum_sched_runtime = 0;
815 INIT_LIST_HEAD(&sig->cpu_timers[0]);
816 INIT_LIST_HEAD(&sig->cpu_timers[1]);
817 INIT_LIST_HEAD(&sig->cpu_timers[2]);
818 taskstats_tgid_init(sig); 839 taskstats_tgid_init(sig);
819 840
820 task_lock(current->group_leader); 841 task_lock(current->group_leader);
821 memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); 842 memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim);
822 task_unlock(current->group_leader); 843 task_unlock(current->group_leader);
823 844
824 if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { 845 posix_cpu_timers_init_group(sig);
825 /* 846
826 * New sole thread in the process gets an expiry time
827 * of the whole CPU time limit.
828 */
829 tsk->it_prof_expires =
830 secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
831 }
832 acct_init_pacct(&sig->pacct); 847 acct_init_pacct(&sig->pacct);
833 848
834 tty_audit_fork(sig); 849 tty_audit_fork(sig);
@@ -838,6 +853,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
838 853
839void __cleanup_signal(struct signal_struct *sig) 854void __cleanup_signal(struct signal_struct *sig)
840{ 855{
856 thread_group_cputime_free(sig);
841 exit_thread_group_keys(sig); 857 exit_thread_group_keys(sig);
842 tty_kref_put(sig->tty); 858 tty_kref_put(sig->tty);
843 kmem_cache_free(signal_cachep, sig); 859 kmem_cache_free(signal_cachep, sig);
@@ -888,6 +904,19 @@ void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
888#endif /* CONFIG_MM_OWNER */ 904#endif /* CONFIG_MM_OWNER */
889 905
890/* 906/*
907 * Initialize POSIX timer handling for a single task.
908 */
909static void posix_cpu_timers_init(struct task_struct *tsk)
910{
911 tsk->cputime_expires.prof_exp = cputime_zero;
912 tsk->cputime_expires.virt_exp = cputime_zero;
913 tsk->cputime_expires.sched_exp = 0;
914 INIT_LIST_HEAD(&tsk->cpu_timers[0]);
915 INIT_LIST_HEAD(&tsk->cpu_timers[1]);
916 INIT_LIST_HEAD(&tsk->cpu_timers[2]);
917}
918
919/*
891 * This creates a new process as a copy of the old one, 920 * This creates a new process as a copy of the old one,
892 * but does not actually start it yet. 921 * but does not actually start it yet.
893 * 922 *
@@ -997,12 +1026,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
997 task_io_accounting_init(&p->ioac); 1026 task_io_accounting_init(&p->ioac);
998 acct_clear_integrals(p); 1027 acct_clear_integrals(p);
999 1028
1000 p->it_virt_expires = cputime_zero; 1029 posix_cpu_timers_init(p);
1001 p->it_prof_expires = cputime_zero;
1002 p->it_sched_expires = 0;
1003 INIT_LIST_HEAD(&p->cpu_timers[0]);
1004 INIT_LIST_HEAD(&p->cpu_timers[1]);
1005 INIT_LIST_HEAD(&p->cpu_timers[2]);
1006 1030
1007 p->lock_depth = -1; /* -1 = no lock */ 1031 p->lock_depth = -1; /* -1 = no lock */
1008 do_posix_clock_monotonic_gettime(&p->start_time); 1032 do_posix_clock_monotonic_gettime(&p->start_time);
@@ -1203,21 +1227,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1203 if (clone_flags & CLONE_THREAD) { 1227 if (clone_flags & CLONE_THREAD) {
1204 p->group_leader = current->group_leader; 1228 p->group_leader = current->group_leader;
1205 list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); 1229 list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
1206
1207 if (!cputime_eq(current->signal->it_virt_expires,
1208 cputime_zero) ||
1209 !cputime_eq(current->signal->it_prof_expires,
1210 cputime_zero) ||
1211 current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY ||
1212 !list_empty(&current->signal->cpu_timers[0]) ||
1213 !list_empty(&current->signal->cpu_timers[1]) ||
1214 !list_empty(&current->signal->cpu_timers[2])) {
1215 /*
1216 * Have child wake up on its first tick to check
1217 * for process CPU timers.
1218 */
1219 p->it_prof_expires = jiffies_to_cputime(1);
1220 }
1221 } 1230 }
1222 1231
1223 if (likely(p->pid)) { 1232 if (likely(p->pid)) {
@@ -1364,6 +1373,8 @@ long do_fork(unsigned long clone_flags,
1364 if (!IS_ERR(p)) { 1373 if (!IS_ERR(p)) {
1365 struct completion vfork; 1374 struct completion vfork;
1366 1375
1376 trace_sched_process_fork(current, p);
1377
1367 nr = task_pid_vnr(p); 1378 nr = task_pid_vnr(p);
1368 1379
1369 if (clone_flags & CLONE_PARENT_SETTID) 1380 if (clone_flags & CLONE_PARENT_SETTID)