|
@@ -1393,22 +1393,12 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
|
|
|
|
- struct timespec *rqtp, struct timespec __user *rmtp)
|
|
|
|
|
|
+static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
|
|
|
|
+ struct timespec *rqtp, struct itimerspec *it)
|
|
{
|
|
{
|
|
- struct restart_block *restart_block =
|
|
|
|
- ¤t_thread_info()->restart_block;
|
|
|
|
struct k_itimer timer;
|
|
struct k_itimer timer;
|
|
int error;
|
|
int error;
|
|
|
|
|
|
- /*
|
|
|
|
- * Diagnose required errors first.
|
|
|
|
- */
|
|
|
|
- if (CPUCLOCK_PERTHREAD(which_clock) &&
|
|
|
|
- (CPUCLOCK_PID(which_clock) == 0 ||
|
|
|
|
- CPUCLOCK_PID(which_clock) == current->pid))
|
|
|
|
- return -EINVAL;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Set up a temporary timer and then wait for it to go off.
|
|
* Set up a temporary timer and then wait for it to go off.
|
|
*/
|
|
*/
|
|
@@ -1420,11 +1410,12 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
|
|
timer.it_process = current;
|
|
timer.it_process = current;
|
|
if (!error) {
|
|
if (!error) {
|
|
static struct itimerspec zero_it;
|
|
static struct itimerspec zero_it;
|
|
- struct itimerspec it = { .it_value = *rqtp,
|
|
|
|
- .it_interval = {} };
|
|
|
|
|
|
+
|
|
|
|
+ memset(it, 0, sizeof *it);
|
|
|
|
+ it->it_value = *rqtp;
|
|
|
|
|
|
spin_lock_irq(&timer.it_lock);
|
|
spin_lock_irq(&timer.it_lock);
|
|
- error = posix_cpu_timer_set(&timer, flags, &it, NULL);
|
|
|
|
|
|
+ error = posix_cpu_timer_set(&timer, flags, it, NULL);
|
|
if (error) {
|
|
if (error) {
|
|
spin_unlock_irq(&timer.it_lock);
|
|
spin_unlock_irq(&timer.it_lock);
|
|
return error;
|
|
return error;
|
|
@@ -1452,33 +1443,56 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
|
|
* We were interrupted by a signal.
|
|
* We were interrupted by a signal.
|
|
*/
|
|
*/
|
|
sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
|
|
sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
|
|
- posix_cpu_timer_set(&timer, 0, &zero_it, &it);
|
|
|
|
|
|
+ posix_cpu_timer_set(&timer, 0, &zero_it, it);
|
|
spin_unlock_irq(&timer.it_lock);
|
|
spin_unlock_irq(&timer.it_lock);
|
|
|
|
|
|
- if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
|
|
|
|
|
|
+ if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
|
|
/*
|
|
/*
|
|
* It actually did fire already.
|
|
* It actually did fire already.
|
|
*/
|
|
*/
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ error = -ERESTART_RESTARTBLOCK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return error;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
|
|
|
|
+ struct timespec *rqtp, struct timespec __user *rmtp)
|
|
|
|
+{
|
|
|
|
+ struct restart_block *restart_block =
|
|
|
|
+ ¤t_thread_info()->restart_block;
|
|
|
|
+ struct itimerspec it;
|
|
|
|
+ int error;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Diagnose required errors first.
|
|
|
|
+ */
|
|
|
|
+ if (CPUCLOCK_PERTHREAD(which_clock) &&
|
|
|
|
+ (CPUCLOCK_PID(which_clock) == 0 ||
|
|
|
|
+ CPUCLOCK_PID(which_clock) == current->pid))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
|
|
|
|
+
|
|
|
|
+ if (error == -ERESTART_RESTARTBLOCK) {
|
|
|
|
+
|
|
|
|
+ if (flags & TIMER_ABSTIME)
|
|
|
|
+ return -ERESTARTNOHAND;
|
|
/*
|
|
/*
|
|
- * Report back to the user the time still remaining.
|
|
|
|
- */
|
|
|
|
- if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
|
|
|
|
- copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
|
|
|
|
|
|
+ * Report back to the user the time still remaining.
|
|
|
|
+ */
|
|
|
|
+ if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
|
|
|
|
restart_block->fn = posix_cpu_nsleep_restart;
|
|
restart_block->fn = posix_cpu_nsleep_restart;
|
|
- /* Caller already set restart_block->arg1 */
|
|
|
|
restart_block->arg0 = which_clock;
|
|
restart_block->arg0 = which_clock;
|
|
restart_block->arg1 = (unsigned long) rmtp;
|
|
restart_block->arg1 = (unsigned long) rmtp;
|
|
restart_block->arg2 = rqtp->tv_sec;
|
|
restart_block->arg2 = rqtp->tv_sec;
|
|
restart_block->arg3 = rqtp->tv_nsec;
|
|
restart_block->arg3 = rqtp->tv_nsec;
|
|
-
|
|
|
|
- error = -ERESTART_RESTARTBLOCK;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1487,13 +1501,31 @@ long posix_cpu_nsleep_restart(struct restart_block *restart_block)
|
|
clockid_t which_clock = restart_block->arg0;
|
|
clockid_t which_clock = restart_block->arg0;
|
|
struct timespec __user *rmtp;
|
|
struct timespec __user *rmtp;
|
|
struct timespec t;
|
|
struct timespec t;
|
|
|
|
+ struct itimerspec it;
|
|
|
|
+ int error;
|
|
|
|
|
|
rmtp = (struct timespec __user *) restart_block->arg1;
|
|
rmtp = (struct timespec __user *) restart_block->arg1;
|
|
t.tv_sec = restart_block->arg2;
|
|
t.tv_sec = restart_block->arg2;
|
|
t.tv_nsec = restart_block->arg3;
|
|
t.tv_nsec = restart_block->arg3;
|
|
|
|
|
|
restart_block->fn = do_no_restart_syscall;
|
|
restart_block->fn = do_no_restart_syscall;
|
|
- return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
|
|
|
|
|
|
+ error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
|
|
|
|
+
|
|
|
|
+ if (error == -ERESTART_RESTARTBLOCK) {
|
|
|
|
+ /*
|
|
|
|
+ * Report back to the user the time still remaining.
|
|
|
|
+ */
|
|
|
|
+ if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+
|
|
|
|
+ restart_block->fn = posix_cpu_nsleep_restart;
|
|
|
|
+ restart_block->arg0 = which_clock;
|
|
|
|
+ restart_block->arg1 = (unsigned long) rmtp;
|
|
|
|
+ restart_block->arg2 = t.tv_sec;
|
|
|
|
+ restart_block->arg3 = t.tv_nsec;
|
|
|
|
+ }
|
|
|
|
+ return error;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|