aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 4c14942a0ee3..bf9fef6d1bfe 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -165,6 +165,18 @@ void free_task(struct task_struct *tsk)
165} 165}
166EXPORT_SYMBOL(free_task); 166EXPORT_SYMBOL(free_task);
167 167
168static inline void free_signal_struct(struct signal_struct *sig)
169{
170 taskstats_tgid_free(sig);
171 kmem_cache_free(signal_cachep, sig);
172}
173
174static inline void put_signal_struct(struct signal_struct *sig)
175{
176 if (atomic_dec_and_test(&sig->sigcnt))
177 free_signal_struct(sig);
178}
179
168void __put_task_struct(struct task_struct *tsk) 180void __put_task_struct(struct task_struct *tsk)
169{ 181{
170 WARN_ON(!tsk->exit_state); 182 WARN_ON(!tsk->exit_state);
@@ -173,6 +185,7 @@ void __put_task_struct(struct task_struct *tsk)
173 185
174 exit_creds(tsk); 186 exit_creds(tsk);
175 delayacct_tsk_free(tsk); 187 delayacct_tsk_free(tsk);
188 put_signal_struct(tsk->signal);
176 189
177 if (!profile_handoff_task(tsk)) 190 if (!profile_handoff_task(tsk))
178 free_task(tsk); 191 free_task(tsk);
@@ -864,8 +877,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
864 if (!sig) 877 if (!sig)
865 return -ENOMEM; 878 return -ENOMEM;
866 879
867 atomic_set(&sig->count, 1); 880 sig->nr_threads = 1;
868 atomic_set(&sig->live, 1); 881 atomic_set(&sig->live, 1);
882 atomic_set(&sig->sigcnt, 1);
869 init_waitqueue_head(&sig->wait_chldexit); 883 init_waitqueue_head(&sig->wait_chldexit);
870 if (clone_flags & CLONE_NEWPID) 884 if (clone_flags & CLONE_NEWPID)
871 sig->flags |= SIGNAL_UNKILLABLE; 885 sig->flags |= SIGNAL_UNKILLABLE;
@@ -889,13 +903,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
889 return 0; 903 return 0;
890} 904}
891 905
892void __cleanup_signal(struct signal_struct *sig)
893{
894 thread_group_cputime_free(sig);
895 tty_kref_put(sig->tty);
896 kmem_cache_free(signal_cachep, sig);
897}
898
899static void copy_flags(unsigned long clone_flags, struct task_struct *p) 906static void copy_flags(unsigned long clone_flags, struct task_struct *p)
900{ 907{
901 unsigned long new_flags = p->flags; 908 unsigned long new_flags = p->flags;
@@ -1079,6 +1086,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1079 } 1086 }
1080 mpol_fix_fork_child_flag(p); 1087 mpol_fix_fork_child_flag(p);
1081#endif 1088#endif
1089#ifdef CONFIG_CPUSETS
1090 p->cpuset_mem_spread_rotor = node_random(p->mems_allowed);
1091 p->cpuset_slab_spread_rotor = node_random(p->mems_allowed);
1092#endif
1082#ifdef CONFIG_TRACE_IRQFLAGS 1093#ifdef CONFIG_TRACE_IRQFLAGS
1083 p->irq_events = 0; 1094 p->irq_events = 0;
1084#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW 1095#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
@@ -1112,8 +1123,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1112 p->memcg_batch.memcg = NULL; 1123 p->memcg_batch.memcg = NULL;
1113#endif 1124#endif
1114 1125
1115 p->bts = NULL;
1116
1117 /* Perform scheduler related setup. Assign this task to a CPU. */ 1126 /* Perform scheduler related setup. Assign this task to a CPU. */
1118 sched_fork(p, clone_flags); 1127 sched_fork(p, clone_flags);
1119 1128
@@ -1247,8 +1256,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1247 } 1256 }
1248 1257
1249 if (clone_flags & CLONE_THREAD) { 1258 if (clone_flags & CLONE_THREAD) {
1250 atomic_inc(&current->signal->count); 1259 current->signal->nr_threads++;
1251 atomic_inc(&current->signal->live); 1260 atomic_inc(&current->signal->live);
1261 atomic_inc(&current->signal->sigcnt);
1252 p->group_leader = current->group_leader; 1262 p->group_leader = current->group_leader;
1253 list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); 1263 list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
1254 } 1264 }
@@ -1261,7 +1271,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1261 p->nsproxy->pid_ns->child_reaper = p; 1271 p->nsproxy->pid_ns->child_reaper = p;
1262 1272
1263 p->signal->leader_pid = pid; 1273 p->signal->leader_pid = pid;
1264 tty_kref_put(p->signal->tty);
1265 p->signal->tty = tty_kref_get(current->signal->tty); 1274 p->signal->tty = tty_kref_get(current->signal->tty);
1266 attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); 1275 attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
1267 attach_pid(p, PIDTYPE_SID, task_session(current)); 1276 attach_pid(p, PIDTYPE_SID, task_session(current));
@@ -1294,7 +1303,7 @@ bad_fork_cleanup_mm:
1294 mmput(p->mm); 1303 mmput(p->mm);
1295bad_fork_cleanup_signal: 1304bad_fork_cleanup_signal:
1296 if (!(clone_flags & CLONE_THREAD)) 1305 if (!(clone_flags & CLONE_THREAD))
1297 __cleanup_signal(p->signal); 1306 free_signal_struct(p->signal);
1298bad_fork_cleanup_sighand: 1307bad_fork_cleanup_sighand:
1299 __cleanup_sighand(p->sighand); 1308 __cleanup_sighand(p->sighand);
1300bad_fork_cleanup_fs: 1309bad_fork_cleanup_fs:
@@ -1329,6 +1338,16 @@ noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_re
1329 return regs; 1338 return regs;
1330} 1339}
1331 1340
1341static inline void init_idle_pids(struct pid_link *links)
1342{
1343 enum pid_type type;
1344
1345 for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type) {
1346 INIT_HLIST_NODE(&links[type].node); /* not really needed */
1347 links[type].pid = &init_struct_pid;
1348 }
1349}
1350
1332struct task_struct * __cpuinit fork_idle(int cpu) 1351struct task_struct * __cpuinit fork_idle(int cpu)
1333{ 1352{
1334 struct task_struct *task; 1353 struct task_struct *task;
@@ -1336,8 +1355,10 @@ struct task_struct * __cpuinit fork_idle(int cpu)
1336 1355
1337 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, 1356 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
1338 &init_struct_pid, 0); 1357 &init_struct_pid, 0);
1339 if (!IS_ERR(task)) 1358 if (!IS_ERR(task)) {
1359 init_idle_pids(task->pids);
1340 init_idle(task, cpu); 1360 init_idle(task, cpu);
1361 }
1341 1362
1342 return task; 1363 return task;
1343} 1364}
@@ -1509,14 +1530,6 @@ static void check_unshare_flags(unsigned long *flags_ptr)
1509 *flags_ptr |= CLONE_SIGHAND; 1530 *flags_ptr |= CLONE_SIGHAND;
1510 1531
1511 /* 1532 /*
1512 * If unsharing signal handlers and the task was created
1513 * using CLONE_THREAD, then must unshare the thread
1514 */
1515 if ((*flags_ptr & CLONE_SIGHAND) &&
1516 (atomic_read(&current->signal->count) > 1))
1517 *flags_ptr |= CLONE_THREAD;
1518
1519 /*
1520 * If unsharing namespace, must also unshare filesystem information. 1533 * If unsharing namespace, must also unshare filesystem information.
1521 */ 1534 */
1522 if (*flags_ptr & CLONE_NEWNS) 1535 if (*flags_ptr & CLONE_NEWNS)