Commit 9ca7d8e6834c40a99622bbe4a88aaf64313ae43c
Committed by
Thomas Gleixner
1 parent
351b3f7a21
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 ] Signed-off-by: Carsten Emde <C.Emde@osadl.org> Tested-by: Pradyumna Sampath <pradysam@gmail.com> Cc: Arjan van de Veen <arjan@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> LKML-Reference: <20100402204331.715783034@osadl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 1 changed file with 25 additions and 49 deletions Side-by-side Diff
ipc/mqueue.c
... | ... | @@ -428,7 +428,7 @@ |
428 | 428 | * sr: SEND or RECV |
429 | 429 | */ |
430 | 430 | static int wq_sleep(struct mqueue_inode_info *info, int sr, |
431 | - long timeout, struct ext_wait_queue *ewp) | |
431 | + ktime_t *timeout, struct ext_wait_queue *ewp) | |
432 | 432 | { |
433 | 433 | int retval; |
434 | 434 | signed long time; |
... | ... | @@ -439,7 +439,8 @@ |
439 | 439 | set_current_state(TASK_INTERRUPTIBLE); |
440 | 440 | |
441 | 441 | spin_unlock(&info->lock); |
442 | - time = schedule_timeout(timeout); | |
442 | + time = schedule_hrtimeout_range_clock(timeout, | |
443 | + HRTIMER_MODE_ABS, 0, CLOCK_REALTIME); | |
443 | 444 | |
444 | 445 | while (ewp->state == STATE_PENDING) |
445 | 446 | cpu_relax(); |
446 | 447 | |
447 | 448 | |
... | ... | @@ -551,31 +552,16 @@ |
551 | 552 | wake_up(&info->wait_q); |
552 | 553 | } |
553 | 554 | |
554 | -static long prepare_timeout(struct timespec *p) | |
555 | +static int prepare_timeout(const struct timespec __user *u_abs_timeout, | |
556 | + ktime_t *expires, struct timespec *ts) | |
555 | 557 | { |
556 | - struct timespec nowts; | |
557 | - long timeout; | |
558 | + if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec))) | |
559 | + return -EFAULT; | |
560 | + if (!timespec_valid(ts)) | |
561 | + return -EINVAL; | |
558 | 562 | |
559 | - if (p) { | |
560 | - if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0 | |
561 | - || p->tv_nsec >= NSEC_PER_SEC)) | |
562 | - return -EINVAL; | |
563 | - nowts = CURRENT_TIME; | |
564 | - /* first subtract as jiffies can't be too big */ | |
565 | - p->tv_sec -= nowts.tv_sec; | |
566 | - if (p->tv_nsec < nowts.tv_nsec) { | |
567 | - p->tv_nsec += NSEC_PER_SEC; | |
568 | - p->tv_sec--; | |
569 | - } | |
570 | - p->tv_nsec -= nowts.tv_nsec; | |
571 | - if (p->tv_sec < 0) | |
572 | - return 0; | |
573 | - | |
574 | - timeout = timespec_to_jiffies(p) + 1; | |
575 | - } else | |
576 | - return MAX_SCHEDULE_TIMEOUT; | |
577 | - | |
578 | - return timeout; | |
563 | + *expires = timespec_to_ktime(*ts); | |
564 | + return 0; | |
579 | 565 | } |
580 | 566 | |
581 | 567 | static void remove_notification(struct mqueue_inode_info *info) |
582 | 568 | |
583 | 569 | |
... | ... | @@ -861,22 +847,21 @@ |
861 | 847 | struct ext_wait_queue *receiver; |
862 | 848 | struct msg_msg *msg_ptr; |
863 | 849 | struct mqueue_inode_info *info; |
864 | - struct timespec ts, *p = NULL; | |
865 | - long timeout; | |
850 | + ktime_t expires, *timeout = NULL; | |
851 | + struct timespec ts; | |
866 | 852 | int ret; |
867 | 853 | |
868 | 854 | if (u_abs_timeout) { |
869 | - if (copy_from_user(&ts, u_abs_timeout, | |
870 | - sizeof(struct timespec))) | |
871 | - return -EFAULT; | |
872 | - p = &ts; | |
855 | + int res = prepare_timeout(u_abs_timeout, &expires, &ts); | |
856 | + if (res) | |
857 | + return res; | |
858 | + timeout = &expires; | |
873 | 859 | } |
874 | 860 | |
875 | 861 | if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) |
876 | 862 | return -EINVAL; |
877 | 863 | |
878 | - audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); | |
879 | - timeout = prepare_timeout(p); | |
864 | + audit_mq_sendrecv(mqdes, msg_len, msg_prio, timeout ? &ts : NULL); | |
880 | 865 | |
881 | 866 | filp = fget(mqdes); |
882 | 867 | if (unlikely(!filp)) { |
... | ... | @@ -918,9 +903,6 @@ |
918 | 903 | if (filp->f_flags & O_NONBLOCK) { |
919 | 904 | spin_unlock(&info->lock); |
920 | 905 | ret = -EAGAIN; |
921 | - } else if (unlikely(timeout < 0)) { | |
922 | - spin_unlock(&info->lock); | |
923 | - ret = timeout; | |
924 | 906 | } else { |
925 | 907 | wait.task = current; |
926 | 908 | wait.msg = (void *) msg_ptr; |
927 | 909 | |
928 | 910 | |
929 | 911 | |
... | ... | @@ -953,24 +935,23 @@ |
953 | 935 | size_t, msg_len, unsigned int __user *, u_msg_prio, |
954 | 936 | const struct timespec __user *, u_abs_timeout) |
955 | 937 | { |
956 | - long timeout; | |
957 | 938 | ssize_t ret; |
958 | 939 | struct msg_msg *msg_ptr; |
959 | 940 | struct file *filp; |
960 | 941 | struct inode *inode; |
961 | 942 | struct mqueue_inode_info *info; |
962 | 943 | struct ext_wait_queue wait; |
963 | - struct timespec ts, *p = NULL; | |
944 | + ktime_t expires, *timeout = NULL; | |
945 | + struct timespec ts; | |
964 | 946 | |
965 | 947 | if (u_abs_timeout) { |
966 | - if (copy_from_user(&ts, u_abs_timeout, | |
967 | - sizeof(struct timespec))) | |
968 | - return -EFAULT; | |
969 | - p = &ts; | |
948 | + int res = prepare_timeout(u_abs_timeout, &expires, &ts); | |
949 | + if (res) | |
950 | + return res; | |
951 | + timeout = &expires; | |
970 | 952 | } |
971 | 953 | |
972 | - audit_mq_sendrecv(mqdes, msg_len, 0, p); | |
973 | - timeout = prepare_timeout(p); | |
954 | + audit_mq_sendrecv(mqdes, msg_len, 0, timeout ? &ts : NULL); | |
974 | 955 | |
975 | 956 | filp = fget(mqdes); |
976 | 957 | if (unlikely(!filp)) { |
... | ... | @@ -1002,11 +983,6 @@ |
1002 | 983 | if (filp->f_flags & O_NONBLOCK) { |
1003 | 984 | spin_unlock(&info->lock); |
1004 | 985 | ret = -EAGAIN; |
1005 | - msg_ptr = NULL; | |
1006 | - } else if (unlikely(timeout < 0)) { | |
1007 | - spin_unlock(&info->lock); | |
1008 | - ret = timeout; | |
1009 | - msg_ptr = NULL; | |
1010 | 986 | } else { |
1011 | 987 | wait.task = current; |
1012 | 988 | wait.state = STATE_NONE; |