diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-08-31 11:16:57 -0400 |
---|---|---|
committer | Arjan van de Ven <arjan@linux.intel.com> | 2008-09-06 00:34:59 -0400 |
commit | b773ad40aca5bd755ba886620842f16e8fef6d75 (patch) | |
tree | 7065661f6559aff70244f2805ced48f894c9b38c /fs/compat.c | |
parent | df0cc0539b4127bd02f64de2c335b4af1fdb3845 (diff) |
select: add poll_select_set_timeout() and poll_select_copy_remaining() helpers
This patch adds 2 helpers that will be used for the hrtimer based select/poll:
poll_select_set_timeout() is a helper that takes a timeout (as a second, nanosecond
pair) and turns that into a "struct timespec" that represents the absolute end time.
This is a common operation in the many select() and poll() variants and needs various,
common, sanity checks.
poll_select_copy_remaining() is a helper that takes care of copying the remaining
time to userspace, as select(), pselect() and ppoll() do. This function comes in
both a natural and a compat implementation (due to datastructure differences).
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/fs/compat.c b/fs/compat.c index 075d0509970d..424767c954a0 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1436,6 +1436,57 @@ out_ret: | |||
1436 | 1436 | ||
1437 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) | 1437 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) |
1438 | 1438 | ||
1439 | static int poll_select_copy_remaining(struct timespec *end_time, void __user *p, | ||
1440 | int timeval, int ret) | ||
1441 | { | ||
1442 | struct timespec ts; | ||
1443 | |||
1444 | if (!p) | ||
1445 | return ret; | ||
1446 | |||
1447 | if (current->personality & STICKY_TIMEOUTS) | ||
1448 | goto sticky; | ||
1449 | |||
1450 | /* No update for zero timeout */ | ||
1451 | if (!end_time->tv_sec && !end_time->tv_nsec) | ||
1452 | return ret; | ||
1453 | |||
1454 | ktime_get_ts(&ts); | ||
1455 | ts = timespec_sub(*end_time, ts); | ||
1456 | if (ts.tv_sec < 0) | ||
1457 | ts.tv_sec = ts.tv_nsec = 0; | ||
1458 | |||
1459 | if (timeval) { | ||
1460 | struct compat_timeval rtv; | ||
1461 | |||
1462 | rtv.tv_sec = ts.tv_sec; | ||
1463 | rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | ||
1464 | |||
1465 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | ||
1466 | return ret; | ||
1467 | } else { | ||
1468 | struct compat_timespec rts; | ||
1469 | |||
1470 | rts.tv_sec = ts.tv_sec; | ||
1471 | rts.tv_nsec = ts.tv_nsec; | ||
1472 | |||
1473 | if (!copy_to_user(p, &rts, sizeof(rts))) | ||
1474 | return ret; | ||
1475 | } | ||
1476 | /* | ||
1477 | * If an application puts its timeval in read-only memory, we | ||
1478 | * don't want the Linux-specific update to the timeval to | ||
1479 | * cause a fault after the select has completed | ||
1480 | * successfully. However, because we're not updating the | ||
1481 | * timeval, we can't restart the system call. | ||
1482 | */ | ||
1483 | |||
1484 | sticky: | ||
1485 | if (ret == -ERESTARTNOHAND) | ||
1486 | ret = -EINTR; | ||
1487 | return ret; | ||
1488 | } | ||
1489 | |||
1439 | /* | 1490 | /* |
1440 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to | 1491 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to |
1441 | * 64-bit unsigned longs. | 1492 | * 64-bit unsigned longs. |