diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-21 14:42:20 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-21 14:42:20 -0400 |
commit | b876d08f816527af257e13d89fb0d3b4b849223c (patch) | |
tree | 40569f568230f918ca55f04b355e251747f913ed /kernel/fork.c | |
parent | b364776ad1208a71f0c53578c84619a395412a8d (diff) | |
parent | 2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (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.c | 95 |
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 | */ | ||
767 | static 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 | |||
762 | static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | 789 | static 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(¤t->signal->count); | 795 | ret = thread_group_cputime_clone_thread(current); |
769 | atomic_inc(¤t->signal->live); | 796 | if (likely(!ret)) { |
770 | return 0; | 797 | atomic_inc(¤t->signal->count); |
798 | atomic_inc(¤t->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 | ||
839 | void __cleanup_signal(struct signal_struct *sig) | 854 | void __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 | */ | ||
909 | static 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(¤t->signal->cpu_timers[0]) || | ||
1213 | !list_empty(¤t->signal->cpu_timers[1]) || | ||
1214 | !list_empty(¤t->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) |