aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@ZenIV.linux.org.uk>2017-06-07 04:42:29 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-06-13 18:00:41 -0400
commita7602681fc63f1a3ddd3da336296c9634c2ff974 (patch)
tree5b845e7c95f763609080fa9d5e5f0b5f859add93
parent192a82f9003fe8fabd6088aa646e829225a94c55 (diff)
hrtimer: Move copyout of remaining time to do_nanosleep()
The hrtimer nanosleep() implementation can be simplified by moving the copy out of the remaining time to do_nanosleep() which is shared between the real nanosleep function and the restart function. The pointer to the timespec64 which is updated is already stored in the restart block at the call site, so the seperate handling of nanosleep and restart function can be avoided. [ tglx: Added changelog ] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: John Stultz <john.stultz@linaro.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20170607084241.28657-4-viro@ZenIV.linux.org.uk
-rw-r--r--kernel/time/hrtimer.c62
1 files changed, 20 insertions, 42 deletions
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 4ae777f159de..baa7b846b6e3 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1441,6 +1441,7 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
1441 1441
1442static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) 1442static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
1443{ 1443{
1444 struct timespec __user *rmtp;
1444 hrtimer_init_sleeper(t, current); 1445 hrtimer_init_sleeper(t, current);
1445 1446
1446 do { 1447 do {
@@ -1457,48 +1458,33 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
1457 1458
1458 __set_current_state(TASK_RUNNING); 1459 __set_current_state(TASK_RUNNING);
1459 1460
1460 return t->task == NULL; 1461 if (!t->task)
1461}
1462
1463static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
1464{
1465 struct timespec rmt;
1466 ktime_t rem;
1467
1468 rem = hrtimer_expires_remaining(timer);
1469 if (rem <= 0)
1470 return 0; 1462 return 0;
1471 rmt = ktime_to_timespec(rem);
1472 1463
1473 if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) 1464 rmtp = current->restart_block.nanosleep.rmtp;
1474 return -EFAULT; 1465 if (rmtp) {
1475 1466 struct timespec rmt;
1476 return 1; 1467 ktime_t rem = hrtimer_expires_remaining(&t->timer);
1468 if (rem <= 0)
1469 return 0;
1470 rmt = ktime_to_timespec(rem);
1471
1472 if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
1473 return -EFAULT;
1474 }
1475 return -ERESTART_RESTARTBLOCK;
1477} 1476}
1478 1477
1479long __sched hrtimer_nanosleep_restart(struct restart_block *restart) 1478long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
1480{ 1479{
1481 struct hrtimer_sleeper t; 1480 struct hrtimer_sleeper t;
1482 struct timespec __user *rmtp; 1481 int ret;
1483 int ret = 0;
1484 1482
1485 hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid, 1483 hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid,
1486 HRTIMER_MODE_ABS); 1484 HRTIMER_MODE_ABS);
1487 hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires); 1485 hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
1488 1486
1489 if (do_nanosleep(&t, HRTIMER_MODE_ABS)) 1487 ret = do_nanosleep(&t, HRTIMER_MODE_ABS);
1490 goto out;
1491
1492 rmtp = restart->nanosleep.rmtp;
1493 if (rmtp) {
1494 ret = update_rmtp(&t.timer, rmtp);
1495 if (ret <= 0)
1496 goto out;
1497 }
1498
1499 /* The other values in restart are already filled in */
1500 ret = -ERESTART_RESTARTBLOCK;
1501out:
1502 destroy_hrtimer_on_stack(&t.timer); 1488 destroy_hrtimer_on_stack(&t.timer);
1503 return ret; 1489 return ret;
1504} 1490}
@@ -1506,8 +1492,7 @@ out:
1506long hrtimer_nanosleep(struct timespec64 *rqtp, 1492long hrtimer_nanosleep(struct timespec64 *rqtp,
1507 const enum hrtimer_mode mode, const clockid_t clockid) 1493 const enum hrtimer_mode mode, const clockid_t clockid)
1508{ 1494{
1509 struct restart_block *restart = &current->restart_block; 1495 struct restart_block *restart;
1510 struct timespec __user *rmtp;
1511 struct hrtimer_sleeper t; 1496 struct hrtimer_sleeper t;
1512 int ret = 0; 1497 int ret = 0;
1513 u64 slack; 1498 u64 slack;
@@ -1518,7 +1503,8 @@ long hrtimer_nanosleep(struct timespec64 *rqtp,
1518 1503
1519 hrtimer_init_on_stack(&t.timer, clockid, mode); 1504 hrtimer_init_on_stack(&t.timer, clockid, mode);
1520 hrtimer_set_expires_range_ns(&t.timer, timespec64_to_ktime(*rqtp), slack); 1505 hrtimer_set_expires_range_ns(&t.timer, timespec64_to_ktime(*rqtp), slack);
1521 if (do_nanosleep(&t, mode)) 1506 ret = do_nanosleep(&t, mode);
1507 if (ret != -ERESTART_RESTARTBLOCK)
1522 goto out; 1508 goto out;
1523 1509
1524 /* Absolute timers do not update the rmtp value and restart: */ 1510 /* Absolute timers do not update the rmtp value and restart: */
@@ -1527,18 +1513,10 @@ long hrtimer_nanosleep(struct timespec64 *rqtp,
1527 goto out; 1513 goto out;
1528 } 1514 }
1529 1515
1530 rmtp = restart->nanosleep.rmtp; 1516 restart = &current->restart_block;
1531 if (rmtp) {
1532 ret = update_rmtp(&t.timer, rmtp);
1533 if (ret <= 0)
1534 goto out;
1535 }
1536
1537 restart->fn = hrtimer_nanosleep_restart; 1517 restart->fn = hrtimer_nanosleep_restart;
1538 restart->nanosleep.clockid = t.timer.base->clockid; 1518 restart->nanosleep.clockid = t.timer.base->clockid;
1539 restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer); 1519 restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
1540
1541 ret = -ERESTART_RESTARTBLOCK;
1542out: 1520out:
1543 destroy_hrtimer_on_stack(&t.timer); 1521 destroy_hrtimer_on_stack(&t.timer);
1544 return ret; 1522 return ret;