Commit 5debfa6da5b06954bc79fe8deed0d1062c58dcec

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent dcf560c593

[PATCH] coredump: shutdown current process first

This patch optimizes zap_threads() for the case when there are no ->mm
users except the current's thread group.  In that case we can avoid
'for_each_process()' loop.

It also adds a useful invariant: SIGNAL_GROUP_EXIT (if checked under
->siglock) always implies that all threads (except may be current) have
pending SIGKILL.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 17 additions and 12 deletions Side-by-side Diff

... ... @@ -1371,13 +1371,7 @@
1371 1371 static void zap_process(struct task_struct *start)
1372 1372 {
1373 1373 struct task_struct *t;
1374   - unsigned long flags;
1375 1374  
1376   - /*
1377   - * start->sighand can't disappear, but may be
1378   - * changed by de_thread()
1379   - */
1380   - lock_task_sighand(start, &flags);
1381 1375 start->signal->flags = SIGNAL_GROUP_EXIT;
1382 1376 start->signal->group_stop_count = 0;
1383 1377  
1384 1378  
1385 1379  
1386 1380  
1387 1381  
1388 1382  
1389 1383  
1390 1384  
1391 1385  
... ... @@ -1389,40 +1383,51 @@
1389 1383 signal_wake_up(t, 1);
1390 1384 }
1391 1385 } while ((t = next_thread(t)) != start);
1392   -
1393   - unlock_task_sighand(start, &flags);
1394 1386 }
1395 1387  
1396 1388 static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
1397 1389 int exit_code)
1398 1390 {
1399 1391 struct task_struct *g, *p;
  1392 + unsigned long flags;
1400 1393 int err = -EAGAIN;
1401 1394  
1402 1395 spin_lock_irq(&tsk->sighand->siglock);
1403 1396 if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) {
1404   - tsk->signal->flags = SIGNAL_GROUP_EXIT;
1405 1397 tsk->signal->group_exit_code = exit_code;
1406   - tsk->signal->group_stop_count = 0;
  1398 + zap_process(tsk);
1407 1399 err = 0;
1408 1400 }
1409 1401 spin_unlock_irq(&tsk->sighand->siglock);
1410 1402 if (err)
1411 1403 return err;
1412 1404  
  1405 + if (atomic_read(&mm->mm_users) == mm->core_waiters + 1)
  1406 + goto done;
  1407 +
1413 1408 rcu_read_lock();
1414 1409 for_each_process(g) {
  1410 + if (g == tsk->group_leader)
  1411 + continue;
  1412 +
1415 1413 p = g;
1416 1414 do {
1417 1415 if (p->mm) {
1418   - if (p->mm == mm)
  1416 + if (p->mm == mm) {
  1417 + /*
  1418 + * p->sighand can't disappear, but
  1419 + * may be changed by de_thread()
  1420 + */
  1421 + lock_task_sighand(p, &flags);
1419 1422 zap_process(p);
  1423 + unlock_task_sighand(p, &flags);
  1424 + }
1420 1425 break;
1421 1426 }
1422 1427 } while ((p = next_thread(p)) != g);
1423 1428 }
1424 1429 rcu_read_unlock();
1425   -
  1430 +done:
1426 1431 return mm->core_waiters;
1427 1432 }
1428 1433