Convert message queue timeouts to hrtimer
cover Convert message queue timeouts to hrtimer
The message queue system calls that may timeout, mq_timedsend() and mq_timedreceive(), still use the old jiffie-based timer interface. Convert them to hrtimer.
The first patch provides the hrtimer infrastructure, the second patch does the actual conversion to hrtimer.
Carsten.
PATCH 1/2 provide-schedule_hrtimeout-for-wallclock.patch
The current version of schedule_hrtimeout() always uses the monotonic clock. Some system calls such as mq_timedsend() and mq_timedreceive(), however, require the use of the wall clock due to the definition of the system call.
This patch provides the infrastructure to use schedule_hrtimeout() with a wallclock timer.
--- include/linux/hrtimer.h | 2 + kernel/hrtimer.c | 66 +++++++++++++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 26 deletions(-)
include/linux/hrtimer.h +2 -0
@@ -422,6 +422,8 @@ extern void hrtimer_init_sleeper(structextern int schedule_hrtimeout_range (ktime_t *expires,unsigned long delta,const enum hrtimer_mode mode); +extern int schedule_hrtimeout_range_clock (ktime_t *expires, +unsigned long delta,const enum hrtimer_mode mode,int clock);extern int schedule_hrtimeout (ktime_t *expires,const enum hrtimer_mode mode);/* Soft interrupt function to run the hrtimer queues: */
kernel/hrtimer.c +40 -26
88 lines not on this page · raw message
[tip:timers/core] hrtimers: Provide schedule_hrtimeout for CLOCK_REALTIME
Commit-ID: 351b3f7a21e413a9b14d0393171497d2373bd702 Gitweb: http://git.kernel.org/tip/351b3f7a21e413a9b14d0393171497d2373bd702 Author: Carsten Emde <[email protected]> AuthorDate: Fri, 2 Apr 2010 22:40:19 +0200 Committer: Thomas Gleixner <[email protected]> CommitDate: Tue, 6 Apr 2010 21:50:03 +0200
hrtimers: Provide schedule_hrtimeout for CLOCK_REALTIME
The current version of schedule_hrtimeout() always uses the monotonic clock. Some system calls such as mq_timedsend() and mq_timedreceive(), however, require the use of the wall clock due to the definition of the system call.
This patch provides the infrastructure to use schedule_hrtimeout() with a CLOCK_REALTIME timer.
LKML-Reference: <[email protected]>
--- include/linux/hrtimer.h | 2 + kernel/hrtimer.c | 67 ++++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 26 deletions(-)
include/linux/hrtimer.h +2 -0
@@ -422,6 +422,8 @@ extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,extern int schedule_hrtimeout_range (ktime_t *expires,unsigned long delta,const enum hrtimer_mode mode); +extern int schedule_hrtimeout_range_clock (ktime_t *expires, +unsigned long delta,const enum hrtimer_mode mode,int clock);extern int schedule_hrtimeout (ktime_t *expires,const enum hrtimer_mode mode);/* Soft interrupt function to run the hrtimer queues: */
kernel/hrtimer.c +41 -26
89 lines not on this page · raw message
PATCH 2/2 let-message-queue-timeout-use-hrtimer.patch
In reply to Carsten EmdeThe message queue functions mq_timedsend() and mq_timedreceive() have not yet been converted to use the hrtimer interface.
This patch replaces the call to schedule_timeout() by a call to schedule_hrtimeout() and transforms the expiration time from timespec to ktime as required.
--- ipc/mqueue.c | 74 +++++++++++++++++++---------------------------------------- 1 file changed, 25 insertions(+), 49 deletions(-)
ipc/mqueue.c +25 -49
@@ -428,7 +428,7 @@ static void wq_add(struct mqueue_inode_i* sr: SEND or RECV */ static int wq_sleep (struct mqueue_inode_info *info,int sr, -long timeout,struct ext_wait_queue *ewp) +ktime_t *timeout,struct ext_wait_queue *ewp) {int retval;signed long time;
@@ -439,7 +439,8 @@ static int wq_sleep(struct mqueue_inode_set_current_state (TASK_INTERRUPTIBLE );spin_unlock (&info->lock); - time =schedule_timeout (timeout); + time =schedule_hrtimeout_range_clock (timeout, +HRTIMER_MODE_ABS ,0 ,CLOCK_REALTIME );while (ewp->state ==STATE_PENDING )cpu_relax ();
@@ -551,31 +552,16 @@ static void __do_notify(struct mqueue_inwake_up (&info->wait_q); } -static long prepare_timeout (struct timespec *p) +static int prepare_timeout (const struct timespec __user *u_abs_timeout, +ktime_t *expires,struct timespec *ts) { -struct timespec nowts; -long timeout; - -if (p) { -if (unlikely (p->tv_nsec <0 || p->tv_sec <0 - || p->tv_nsec >=NSEC_PER_SEC )) -return -EINVAL ; - nowts =CURRENT_TIME ; -/* first subtract as jiffies can't be too big */ - p->tv_sec -= nowts.tv_sec; -if (p->tv_nsec < nowts.tv_nsec) { - p->tv_nsec +=NSEC_PER_SEC ; - p->tv_sec--; - } - p->tv_nsec -= nowts.tv_nsec; -if (p->tv_sec <0 ) -return 0 ; - - timeout =timespec_to_jiffies (p) +1 ; - }else -return MAX_SCHEDULE_TIMEOUT ; +if (copy_from_user (ts, u_abs_timeout,sizeof (struct timespec ))) +return -EFAULT ; +if (!timespec_valid (ts)) +return -EINVAL ; -return timeout; + *expires =timespec_to_ktime (*ts); +return 0 ; }static void remove_notification (struct mqueue_inode_info *info)
@@ -861,22 +847,21 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdstruct ext_wait_queue *receiver;struct msg_msg *msg_ptr;struct mqueue_inode_info *info; -struct timespec ts, *p =NULL ; -long timeout; +ktime_t expires, *timeout =NULL ; +struct timespec ts;int ret;if (u_abs_timeout) { -if (copy_from_user (&ts, u_abs_timeout, -sizeof (struct timespec ))) -return -EFAULT ; - p = &ts; +int res =prepare_timeout (u_abs_timeout, &expires, &ts); +if (res) +return res; + timeout = &expires; }if (unlikely (msg_prio >= (unsigned long )MQ_PRIO_MAX ))return -EINVAL ; -audit_mq_sendrecv (mqdes, msg_len, msg_prio, p); - timeout =prepare_timeout (p); +audit_mq_sendrecv (mqdes, msg_len, msg_prio, timeout ? &ts :NULL ); filp =fget (mqdes);if (unlikely (!filp)) {
@@ -918,9 +903,6 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdif (filp->f_flags &O_NONBLOCK ) {spin_unlock (&info->lock); ret = -EAGAIN ; - }else if (unlikely (timeout <0 )) { -spin_unlock (&info->lock); - ret = timeout; }else { wait.task = current; wait.msg = (void *) msg_ptr;
@@ -953,24 +935,23 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, size_t, msg_len, unsigned int __user *, u_msg_prio, const struct timespec __user *, u_abs_timeout) { - long timeout; ssize_t ret;struct msg_msg *msg_ptr;struct file *filp;struct inode *inode;struct mqueue_inode_info *info;struct ext_wait_queue wait; -struct timespec ts, *p =NULL ; +ktime_t expires, *timeout =NULL ; +struct timespec ts;if (u_abs_timeout) { -if (copy_from_user (&ts, u_abs_timeout, -sizeof (struct timespec ))) -return -EFAULT ; - p = &ts; +int res =prepare_timeout (u_abs_timeout, &expires, &ts); +if (res) +return res; + timeout = &expires; } -audit_mq_sendrecv (mqdes, msg_len,0 , p); - timeout =prepare_timeout (p); +audit_mq_sendrecv (mqdes, msg_len,0 , timeout ? &ts :NULL ); filp =fget (mqdes);if (unlikely (!filp)) {
@@ -1002,11 +983,6 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t,if (filp->f_flags &O_NONBLOCK ) {spin_unlock (&info->lock); ret = -EAGAIN ; - msg_ptr =NULL ; - }else if (unlikely (timeout <0 )) { -spin_unlock (&info->lock); - ret = timeout; - msg_ptr =NULL ; }else { wait.task = current; wait.state =STATE_NONE ;
[tip:timers/core] mqueue: Convert message queue timeout to use hrtimers
Commit-ID: 9ca7d8e6834c40a99622bbe4a88aaf64313ae43c Gitweb: http://git.kernel.org/tip/9ca7d8e6834c40a99622bbe4a88aaf64313ae43c Author: Carsten Emde <[email protected]> AuthorDate: Fri, 2 Apr 2010 22:40:20 +0200 Committer: Thomas Gleixner <[email protected]> CommitDate: Tue, 6 Apr 2010 21:50:03 +0200
mqueue: Convert message queue timeout to use hrtimers
The message queue functions mq_timedsend() and mq_timedreceive() have not yet been converted to use the hrtimer interface.
This patch replaces the call to schedule_timeout() by a call to schedule_hrtimeout() and transforms the expiration time from timespec to ktime as required.
[ tglx: Fixed whitespace wreckage ]
LKML-Reference: <[email protected]>
--- ipc/mqueue.c | 74 +++++++++++++++++++-------------------------------------- 1 files changed, 25 insertions(+), 49 deletions(-)
ipc/mqueue.c +25 -49
@@ -428,7 +428,7 @@ static void wq_add(struct mqueue_inode_info *info, int sr,* sr: SEND or RECV */ static int wq_sleep (struct mqueue_inode_info *info,int sr, -long timeout,struct ext_wait_queue *ewp) +ktime_t *timeout,struct ext_wait_queue *ewp) {int retval;signed long time;
@@ -439,7 +439,8 @@ static int wq_sleep(struct mqueue_inode_info *info, int sr,set_current_state (TASK_INTERRUPTIBLE );spin_unlock (&info->lock); - time =schedule_timeout (timeout); + time =schedule_hrtimeout_range_clock (timeout, +HRTIMER_MODE_ABS ,0 ,CLOCK_REALTIME );while (ewp->state ==STATE_PENDING )cpu_relax ();
@@ -551,31 +552,16 @@ static void __do_notify(struct mqueue_inode_info *info)wake_up (&info->wait_q); } -static long prepare_timeout (struct timespec *p) +static int prepare_timeout (const struct timespec __user *u_abs_timeout, +ktime_t *expires,struct timespec *ts) { -struct timespec nowts; -long timeout; - -if (p) { -if (unlikely (p->tv_nsec <0 || p->tv_sec <0 - || p->tv_nsec >=NSEC_PER_SEC )) -return -EINVAL ; - nowts =CURRENT_TIME ; -/* first subtract as jiffies can't be too big */ - p->tv_sec -= nowts.tv_sec; -if (p->tv_nsec < nowts.tv_nsec) { - p->tv_nsec +=NSEC_PER_SEC ; - p->tv_sec--; - } - p->tv_nsec -= nowts.tv_nsec; -if (p->tv_sec <0 ) -return 0 ; - - timeout =timespec_to_jiffies (p) +1 ; - }else -return MAX_SCHEDULE_TIMEOUT ; +if (copy_from_user (ts, u_abs_timeout,sizeof (struct timespec ))) +return -EFAULT ; +if (!timespec_valid (ts)) +return -EINVAL ; -return timeout; + *expires =timespec_to_ktime (*ts); +return 0 ; }static void remove_notification (struct mqueue_inode_info *info)
@@ -861,22 +847,21 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,struct ext_wait_queue *receiver;struct msg_msg *msg_ptr;struct mqueue_inode_info *info; -struct timespec ts, *p =NULL ; -long timeout; +ktime_t expires, *timeout =NULL ; +struct timespec ts;int ret;if (u_abs_timeout) { -if (copy_from_user (&ts, u_abs_timeout, -sizeof (struct timespec ))) -return -EFAULT ; - p = &ts; +int res =prepare_timeout (u_abs_timeout, &expires, &ts); +if (res) +return res; + timeout = &expires; }if (unlikely (msg_prio >= (unsigned long )MQ_PRIO_MAX ))return -EINVAL ; -audit_mq_sendrecv (mqdes, msg_len, msg_prio, p); - timeout =prepare_timeout (p); +audit_mq_sendrecv (mqdes, msg_len, msg_prio, timeout ? &ts :NULL ); filp =fget (mqdes);if (unlikely (!filp)) {
@@ -918,9 +903,6 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,if (filp->f_flags &O_NONBLOCK ) {spin_unlock (&info->lock); ret = -EAGAIN ; - }else if (unlikely (timeout <0 )) { -spin_unlock (&info->lock); - ret = timeout; }else { wait.task = current; wait.msg = (void *) msg_ptr;
@@ -953,24 +935,23 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, size_t, msg_len, unsigned int __user *, u_msg_prio, const struct timespec __user *, u_abs_timeout) { - long timeout; ssize_t ret;struct msg_msg *msg_ptr;struct file *filp;struct inode *inode;struct mqueue_inode_info *info;struct ext_wait_queue wait; -struct timespec ts, *p =NULL ; +ktime_t expires, *timeout =NULL ; +struct timespec ts;if (u_abs_timeout) { -if (copy_from_user (&ts, u_abs_timeout, -sizeof (struct timespec ))) -return -EFAULT ; - p = &ts; +int res =prepare_timeout (u_abs_timeout, &expires, &ts); +if (res) +return res; + timeout = &expires; } -audit_mq_sendrecv (mqdes, msg_len,0 , p); - timeout =prepare_timeout (p); +audit_mq_sendrecv (mqdes, msg_len,0 , timeout ? &ts :NULL ); filp =fget (mqdes);if (unlikely (!filp)) {
@@ -1002,11 +983,6 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,if (filp->f_flags &O_NONBLOCK ) {spin_unlock (&info->lock); ret = -EAGAIN ; - msg_ptr =NULL ; - }else if (unlikely (timeout <0 )) { -spin_unlock (&info->lock); - ret = timeout; - msg_ptr =NULL ; }else { wait.task = current; wait.state =STATE_NONE ;