aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/posix-cpu-timers.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-09-30 23:55:03 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-30 23:55:03 -0400
commite993835441734c184d70d3716eed78a08eeb71c2 (patch)
tree583aa17813cdae1c4640e353f8c6df3f197e7548 /kernel/posix-cpu-timers.c
parent360f654e7cda850034f3f6252a7a7cff3fa77356 (diff)
parent1bdfd554be94def718323659173517c5d4a69d25 (diff)
Merge branch 'master' into upstream
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r--kernel/posix-cpu-timers.c101
1 files changed, 70 insertions, 31 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index d38d9ec3276c..479b16b44f79 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1393,25 +1393,13 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
1393 } 1393 }
1394} 1394}
1395 1395
1396static long posix_cpu_clock_nanosleep_restart(struct restart_block *); 1396static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
1397 1397 struct timespec *rqtp, struct itimerspec *it)
1398int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1399 struct timespec *rqtp, struct timespec __user *rmtp)
1400{ 1398{
1401 struct restart_block *restart_block =
1402 &current_thread_info()->restart_block;
1403 struct k_itimer timer; 1399 struct k_itimer timer;
1404 int error; 1400 int error;
1405 1401
1406 /* 1402 /*
1407 * Diagnose required errors first.
1408 */
1409 if (CPUCLOCK_PERTHREAD(which_clock) &&
1410 (CPUCLOCK_PID(which_clock) == 0 ||
1411 CPUCLOCK_PID(which_clock) == current->pid))
1412 return -EINVAL;
1413
1414 /*
1415 * Set up a temporary timer and then wait for it to go off. 1403 * Set up a temporary timer and then wait for it to go off.
1416 */ 1404 */
1417 memset(&timer, 0, sizeof timer); 1405 memset(&timer, 0, sizeof timer);
@@ -1422,11 +1410,12 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1422 timer.it_process = current; 1410 timer.it_process = current;
1423 if (!error) { 1411 if (!error) {
1424 static struct itimerspec zero_it; 1412 static struct itimerspec zero_it;
1425 struct itimerspec it = { .it_value = *rqtp, 1413
1426 .it_interval = {} }; 1414 memset(it, 0, sizeof *it);
1415 it->it_value = *rqtp;
1427 1416
1428 spin_lock_irq(&timer.it_lock); 1417 spin_lock_irq(&timer.it_lock);
1429 error = posix_cpu_timer_set(&timer, flags, &it, NULL); 1418 error = posix_cpu_timer_set(&timer, flags, it, NULL);
1430 if (error) { 1419 if (error) {
1431 spin_unlock_irq(&timer.it_lock); 1420 spin_unlock_irq(&timer.it_lock);
1432 return error; 1421 return error;
@@ -1454,49 +1443,89 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1454 * We were interrupted by a signal. 1443 * We were interrupted by a signal.
1455 */ 1444 */
1456 sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp); 1445 sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
1457 posix_cpu_timer_set(&timer, 0, &zero_it, &it); 1446 posix_cpu_timer_set(&timer, 0, &zero_it, it);
1458 spin_unlock_irq(&timer.it_lock); 1447 spin_unlock_irq(&timer.it_lock);
1459 1448
1460 if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) { 1449 if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
1461 /* 1450 /*
1462 * It actually did fire already. 1451 * It actually did fire already.
1463 */ 1452 */
1464 return 0; 1453 return 0;
1465 } 1454 }
1466 1455
1456 error = -ERESTART_RESTARTBLOCK;
1457 }
1458
1459 return error;
1460}
1461
1462int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1463 struct timespec *rqtp, struct timespec __user *rmtp)
1464{
1465 struct restart_block *restart_block =
1466 &current_thread_info()->restart_block;
1467 struct itimerspec it;
1468 int error;
1469
1470 /*
1471 * Diagnose required errors first.
1472 */
1473 if (CPUCLOCK_PERTHREAD(which_clock) &&
1474 (CPUCLOCK_PID(which_clock) == 0 ||
1475 CPUCLOCK_PID(which_clock) == current->pid))
1476 return -EINVAL;
1477
1478 error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
1479
1480 if (error == -ERESTART_RESTARTBLOCK) {
1481
1482 if (flags & TIMER_ABSTIME)
1483 return -ERESTARTNOHAND;
1467 /* 1484 /*
1468 * Report back to the user the time still remaining. 1485 * Report back to the user the time still remaining.
1469 */ 1486 */
1470 if (rmtp != NULL && !(flags & TIMER_ABSTIME) && 1487 if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
1471 copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
1472 return -EFAULT; 1488 return -EFAULT;
1473 1489
1474 restart_block->fn = posix_cpu_clock_nanosleep_restart; 1490 restart_block->fn = posix_cpu_nsleep_restart;
1475 /* Caller already set restart_block->arg1 */
1476 restart_block->arg0 = which_clock; 1491 restart_block->arg0 = which_clock;
1477 restart_block->arg1 = (unsigned long) rmtp; 1492 restart_block->arg1 = (unsigned long) rmtp;
1478 restart_block->arg2 = rqtp->tv_sec; 1493 restart_block->arg2 = rqtp->tv_sec;
1479 restart_block->arg3 = rqtp->tv_nsec; 1494 restart_block->arg3 = rqtp->tv_nsec;
1480
1481 error = -ERESTART_RESTARTBLOCK;
1482 } 1495 }
1483
1484 return error; 1496 return error;
1485} 1497}
1486 1498
1487static long 1499long posix_cpu_nsleep_restart(struct restart_block *restart_block)
1488posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
1489{ 1500{
1490 clockid_t which_clock = restart_block->arg0; 1501 clockid_t which_clock = restart_block->arg0;
1491 struct timespec __user *rmtp; 1502 struct timespec __user *rmtp;
1492 struct timespec t; 1503 struct timespec t;
1504 struct itimerspec it;
1505 int error;
1493 1506
1494 rmtp = (struct timespec __user *) restart_block->arg1; 1507 rmtp = (struct timespec __user *) restart_block->arg1;
1495 t.tv_sec = restart_block->arg2; 1508 t.tv_sec = restart_block->arg2;
1496 t.tv_nsec = restart_block->arg3; 1509 t.tv_nsec = restart_block->arg3;
1497 1510
1498 restart_block->fn = do_no_restart_syscall; 1511 restart_block->fn = do_no_restart_syscall;
1499 return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp); 1512 error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
1513
1514 if (error == -ERESTART_RESTARTBLOCK) {
1515 /*
1516 * Report back to the user the time still remaining.
1517 */
1518 if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
1519 return -EFAULT;
1520
1521 restart_block->fn = posix_cpu_nsleep_restart;
1522 restart_block->arg0 = which_clock;
1523 restart_block->arg1 = (unsigned long) rmtp;
1524 restart_block->arg2 = t.tv_sec;
1525 restart_block->arg3 = t.tv_nsec;
1526 }
1527 return error;
1528
1500} 1529}
1501 1530
1502 1531
@@ -1524,6 +1553,10 @@ static int process_cpu_nsleep(const clockid_t which_clock, int flags,
1524{ 1553{
1525 return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp); 1554 return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
1526} 1555}
1556static long process_cpu_nsleep_restart(struct restart_block *restart_block)
1557{
1558 return -EINVAL;
1559}
1527static int thread_cpu_clock_getres(const clockid_t which_clock, 1560static int thread_cpu_clock_getres(const clockid_t which_clock,
1528 struct timespec *tp) 1561 struct timespec *tp)
1529{ 1562{
@@ -1544,6 +1577,10 @@ static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
1544{ 1577{
1545 return -EINVAL; 1578 return -EINVAL;
1546} 1579}
1580static long thread_cpu_nsleep_restart(struct restart_block *restart_block)
1581{
1582 return -EINVAL;
1583}
1547 1584
1548static __init int init_posix_cpu_timers(void) 1585static __init int init_posix_cpu_timers(void)
1549{ 1586{
@@ -1553,6 +1590,7 @@ static __init int init_posix_cpu_timers(void)
1553 .clock_set = do_posix_clock_nosettime, 1590 .clock_set = do_posix_clock_nosettime,
1554 .timer_create = process_cpu_timer_create, 1591 .timer_create = process_cpu_timer_create,
1555 .nsleep = process_cpu_nsleep, 1592 .nsleep = process_cpu_nsleep,
1593 .nsleep_restart = process_cpu_nsleep_restart,
1556 }; 1594 };
1557 struct k_clock thread = { 1595 struct k_clock thread = {
1558 .clock_getres = thread_cpu_clock_getres, 1596 .clock_getres = thread_cpu_clock_getres,
@@ -1560,6 +1598,7 @@ static __init int init_posix_cpu_timers(void)
1560 .clock_set = do_posix_clock_nosettime, 1598 .clock_set = do_posix_clock_nosettime,
1561 .timer_create = thread_cpu_timer_create, 1599 .timer_create = thread_cpu_timer_create,
1562 .nsleep = thread_cpu_nsleep, 1600 .nsleep = thread_cpu_nsleep,
1601 .nsleep_restart = thread_cpu_nsleep_restart,
1563 }; 1602 };
1564 1603
1565 register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process); 1604 register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);