diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-06 18:53:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-06 18:53:47 -0500 |
commit | e252f4db187ef02d06c8551069d944d327b8bb9a (patch) | |
tree | 0e704cc34161fc839ef203fbf71106de52e19a7d | |
parent | 2e93960c4d712096902c16fe5511fc91502c2527 (diff) | |
parent | 7838c15b8dd18e78a523513749e5b54bda07b0cb (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
Block: use round_jiffies_up()
Add round_jiffies_up and related routines
block: fix __blkdev_get() for removable devices
generic-ipi: fix the smp_mb() placement
blk: move blk_delete_timer call in end_that_request_last
block: add timer on blkdev_dequeue_request() not elv_next_request()
bio: define __BIOVEC_PHYS_MERGEABLE
block: remove unused ll_new_mergeable()
-rw-r--r-- | block/blk-core.c | 4 | ||||
-rw-r--r-- | block/blk-merge.c | 21 | ||||
-rw-r--r-- | block/blk-timeout.c | 20 | ||||
-rw-r--r-- | block/elevator.c | 12 | ||||
-rw-r--r-- | fs/block_dev.c | 23 | ||||
-rw-r--r-- | include/linux/bio.h | 6 | ||||
-rw-r--r-- | include/linux/timer.h | 5 | ||||
-rw-r--r-- | kernel/smp.c | 18 | ||||
-rw-r--r-- | kernel/timer.c | 129 |
9 files changed, 143 insertions, 95 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index c3df30cfb3fc..10e8a64a5a5b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1770,8 +1770,6 @@ static void end_that_request_last(struct request *req, int error) | |||
1770 | { | 1770 | { |
1771 | struct gendisk *disk = req->rq_disk; | 1771 | struct gendisk *disk = req->rq_disk; |
1772 | 1772 | ||
1773 | blk_delete_timer(req); | ||
1774 | |||
1775 | if (blk_rq_tagged(req)) | 1773 | if (blk_rq_tagged(req)) |
1776 | blk_queue_end_tag(req->q, req); | 1774 | blk_queue_end_tag(req->q, req); |
1777 | 1775 | ||
@@ -1781,6 +1779,8 @@ static void end_that_request_last(struct request *req, int error) | |||
1781 | if (unlikely(laptop_mode) && blk_fs_request(req)) | 1779 | if (unlikely(laptop_mode) && blk_fs_request(req)) |
1782 | laptop_io_completion(); | 1780 | laptop_io_completion(); |
1783 | 1781 | ||
1782 | blk_delete_timer(req); | ||
1783 | |||
1784 | /* | 1784 | /* |
1785 | * Account IO completion. bar_rq isn't accounted as a normal | 1785 | * Account IO completion. bar_rq isn't accounted as a normal |
1786 | * IO on queueing nor completion. Accounting the containing | 1786 | * IO on queueing nor completion. Accounting the containing |
diff --git a/block/blk-merge.c b/block/blk-merge.c index 8681cd6f9911..b92f5b0866b0 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -222,27 +222,6 @@ new_segment: | |||
222 | } | 222 | } |
223 | EXPORT_SYMBOL(blk_rq_map_sg); | 223 | EXPORT_SYMBOL(blk_rq_map_sg); |
224 | 224 | ||
225 | static inline int ll_new_mergeable(struct request_queue *q, | ||
226 | struct request *req, | ||
227 | struct bio *bio) | ||
228 | { | ||
229 | int nr_phys_segs = bio_phys_segments(q, bio); | ||
230 | |||
231 | if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { | ||
232 | req->cmd_flags |= REQ_NOMERGE; | ||
233 | if (req == q->last_merge) | ||
234 | q->last_merge = NULL; | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * A hw segment is just getting larger, bump just the phys | ||
240 | * counter. | ||
241 | */ | ||
242 | req->nr_phys_segments += nr_phys_segs; | ||
243 | return 1; | ||
244 | } | ||
245 | |||
246 | static inline int ll_new_hw_segment(struct request_queue *q, | 225 | static inline int ll_new_hw_segment(struct request_queue *q, |
247 | struct request *req, | 226 | struct request *req, |
248 | struct bio *bio) | 227 | struct bio *bio) |
diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 972a63f848fb..69185ea9fae2 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c | |||
@@ -75,14 +75,7 @@ void blk_delete_timer(struct request *req) | |||
75 | { | 75 | { |
76 | struct request_queue *q = req->q; | 76 | struct request_queue *q = req->q; |
77 | 77 | ||
78 | /* | ||
79 | * Nothing to detach | ||
80 | */ | ||
81 | if (!q->rq_timed_out_fn || !req->deadline) | ||
82 | return; | ||
83 | |||
84 | list_del_init(&req->timeout_list); | 78 | list_del_init(&req->timeout_list); |
85 | |||
86 | if (list_empty(&q->timeout_list)) | 79 | if (list_empty(&q->timeout_list)) |
87 | del_timer(&q->timeout); | 80 | del_timer(&q->timeout); |
88 | } | 81 | } |
@@ -142,7 +135,7 @@ void blk_rq_timed_out_timer(unsigned long data) | |||
142 | } | 135 | } |
143 | 136 | ||
144 | if (next_set && !list_empty(&q->timeout_list)) | 137 | if (next_set && !list_empty(&q->timeout_list)) |
145 | mod_timer(&q->timeout, round_jiffies(next)); | 138 | mod_timer(&q->timeout, round_jiffies_up(next)); |
146 | 139 | ||
147 | spin_unlock_irqrestore(q->queue_lock, flags); | 140 | spin_unlock_irqrestore(q->queue_lock, flags); |
148 | } | 141 | } |
@@ -198,17 +191,10 @@ void blk_add_timer(struct request *req) | |||
198 | 191 | ||
199 | /* | 192 | /* |
200 | * If the timer isn't already pending or this timeout is earlier | 193 | * If the timer isn't already pending or this timeout is earlier |
201 | * than an existing one, modify the timer. Round to next nearest | 194 | * than an existing one, modify the timer. Round up to next nearest |
202 | * second. | 195 | * second. |
203 | */ | 196 | */ |
204 | expiry = round_jiffies(req->deadline); | 197 | expiry = round_jiffies_up(req->deadline); |
205 | |||
206 | /* | ||
207 | * We use ->deadline == 0 to detect whether a timer was added or | ||
208 | * not, so just increase to next jiffy for that specific case | ||
209 | */ | ||
210 | if (unlikely(!req->deadline)) | ||
211 | req->deadline = 1; | ||
212 | 198 | ||
213 | if (!timer_pending(&q->timeout) || | 199 | if (!timer_pending(&q->timeout) || |
214 | time_before(expiry, q->timeout.expires)) | 200 | time_before(expiry, q->timeout.expires)) |
diff --git a/block/elevator.c b/block/elevator.c index 59173a69ebdf..9ac82dde99dd 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -773,12 +773,6 @@ struct request *elv_next_request(struct request_queue *q) | |||
773 | */ | 773 | */ |
774 | rq->cmd_flags |= REQ_STARTED; | 774 | rq->cmd_flags |= REQ_STARTED; |
775 | blk_add_trace_rq(q, rq, BLK_TA_ISSUE); | 775 | blk_add_trace_rq(q, rq, BLK_TA_ISSUE); |
776 | |||
777 | /* | ||
778 | * We are now handing the request to the hardware, | ||
779 | * add the timeout handler | ||
780 | */ | ||
781 | blk_add_timer(rq); | ||
782 | } | 776 | } |
783 | 777 | ||
784 | if (!q->boundary_rq || q->boundary_rq == rq) { | 778 | if (!q->boundary_rq || q->boundary_rq == rq) { |
@@ -850,6 +844,12 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq) | |||
850 | */ | 844 | */ |
851 | if (blk_account_rq(rq)) | 845 | if (blk_account_rq(rq)) |
852 | q->in_flight++; | 846 | q->in_flight++; |
847 | |||
848 | /* | ||
849 | * We are now handing the request to the hardware, add the | ||
850 | * timeout handler. | ||
851 | */ | ||
852 | blk_add_timer(rq); | ||
853 | } | 853 | } |
854 | EXPORT_SYMBOL(elv_dequeue_request); | 854 | EXPORT_SYMBOL(elv_dequeue_request); |
855 | 855 | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 88a776fa0ef6..db831efbdbbd 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -986,7 +986,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part); | |||
986 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | 986 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) |
987 | { | 987 | { |
988 | struct gendisk *disk; | 988 | struct gendisk *disk; |
989 | struct hd_struct *part = NULL; | ||
990 | int ret; | 989 | int ret; |
991 | int partno; | 990 | int partno; |
992 | int perm = 0; | 991 | int perm = 0; |
@@ -1004,24 +1003,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1004 | return ret; | 1003 | return ret; |
1005 | } | 1004 | } |
1006 | 1005 | ||
1007 | ret = -ENXIO; | ||
1008 | |||
1009 | lock_kernel(); | 1006 | lock_kernel(); |
1010 | 1007 | ||
1008 | ret = -ENXIO; | ||
1011 | disk = get_gendisk(bdev->bd_dev, &partno); | 1009 | disk = get_gendisk(bdev->bd_dev, &partno); |
1012 | if (!disk) | 1010 | if (!disk) |
1013 | goto out_unlock_kernel; | 1011 | goto out_unlock_kernel; |
1014 | part = disk_get_part(disk, partno); | ||
1015 | if (!part) | ||
1016 | goto out_unlock_kernel; | ||
1017 | 1012 | ||
1018 | mutex_lock_nested(&bdev->bd_mutex, for_part); | 1013 | mutex_lock_nested(&bdev->bd_mutex, for_part); |
1019 | if (!bdev->bd_openers) { | 1014 | if (!bdev->bd_openers) { |
1020 | bdev->bd_disk = disk; | 1015 | bdev->bd_disk = disk; |
1021 | bdev->bd_part = part; | ||
1022 | bdev->bd_contains = bdev; | 1016 | bdev->bd_contains = bdev; |
1023 | if (!partno) { | 1017 | if (!partno) { |
1024 | struct backing_dev_info *bdi; | 1018 | struct backing_dev_info *bdi; |
1019 | |||
1020 | ret = -ENXIO; | ||
1021 | bdev->bd_part = disk_get_part(disk, partno); | ||
1022 | if (!bdev->bd_part) | ||
1023 | goto out_clear; | ||
1024 | |||
1025 | if (disk->fops->open) { | 1025 | if (disk->fops->open) { |
1026 | ret = disk->fops->open(bdev, mode); | 1026 | ret = disk->fops->open(bdev, mode); |
1027 | if (ret) | 1027 | if (ret) |
@@ -1049,18 +1049,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1049 | bdev->bd_contains = whole; | 1049 | bdev->bd_contains = whole; |
1050 | bdev->bd_inode->i_data.backing_dev_info = | 1050 | bdev->bd_inode->i_data.backing_dev_info = |
1051 | whole->bd_inode->i_data.backing_dev_info; | 1051 | whole->bd_inode->i_data.backing_dev_info; |
1052 | bdev->bd_part = disk_get_part(disk, partno); | ||
1052 | if (!(disk->flags & GENHD_FL_UP) || | 1053 | if (!(disk->flags & GENHD_FL_UP) || |
1053 | !part || !part->nr_sects) { | 1054 | !bdev->bd_part || !bdev->bd_part->nr_sects) { |
1054 | ret = -ENXIO; | 1055 | ret = -ENXIO; |
1055 | goto out_clear; | 1056 | goto out_clear; |
1056 | } | 1057 | } |
1057 | bd_set_size(bdev, (loff_t)part->nr_sects << 9); | 1058 | bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9); |
1058 | } | 1059 | } |
1059 | } else { | 1060 | } else { |
1060 | disk_put_part(part); | ||
1061 | put_disk(disk); | 1061 | put_disk(disk); |
1062 | module_put(disk->fops->owner); | 1062 | module_put(disk->fops->owner); |
1063 | part = NULL; | ||
1064 | disk = NULL; | 1063 | disk = NULL; |
1065 | if (bdev->bd_contains == bdev) { | 1064 | if (bdev->bd_contains == bdev) { |
1066 | if (bdev->bd_disk->fops->open) { | 1065 | if (bdev->bd_disk->fops->open) { |
@@ -1080,6 +1079,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1080 | return 0; | 1079 | return 0; |
1081 | 1080 | ||
1082 | out_clear: | 1081 | out_clear: |
1082 | disk_put_part(bdev->bd_part); | ||
1083 | bdev->bd_disk = NULL; | 1083 | bdev->bd_disk = NULL; |
1084 | bdev->bd_part = NULL; | 1084 | bdev->bd_part = NULL; |
1085 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1085 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
@@ -1091,7 +1091,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1091 | out_unlock_kernel: | 1091 | out_unlock_kernel: |
1092 | unlock_kernel(); | 1092 | unlock_kernel(); |
1093 | 1093 | ||
1094 | disk_put_part(part); | ||
1095 | if (disk) | 1094 | if (disk) |
1096 | module_put(disk->fops->owner); | 1095 | module_put(disk->fops->owner); |
1097 | put_disk(disk); | 1096 | put_disk(disk); |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 1c91a176b9ae..6a642098e5c3 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -236,12 +236,16 @@ static inline void *bio_data(struct bio *bio) | |||
236 | #define __BVEC_END(bio) bio_iovec_idx((bio), (bio)->bi_vcnt - 1) | 236 | #define __BVEC_END(bio) bio_iovec_idx((bio), (bio)->bi_vcnt - 1) |
237 | #define __BVEC_START(bio) bio_iovec_idx((bio), (bio)->bi_idx) | 237 | #define __BVEC_START(bio) bio_iovec_idx((bio), (bio)->bi_idx) |
238 | 238 | ||
239 | /* Default implementation of BIOVEC_PHYS_MERGEABLE */ | ||
240 | #define __BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ | ||
241 | ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) | ||
242 | |||
239 | /* | 243 | /* |
240 | * allow arch override, for eg virtualized architectures (put in asm/io.h) | 244 | * allow arch override, for eg virtualized architectures (put in asm/io.h) |
241 | */ | 245 | */ |
242 | #ifndef BIOVEC_PHYS_MERGEABLE | 246 | #ifndef BIOVEC_PHYS_MERGEABLE |
243 | #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ | 247 | #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ |
244 | ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) | 248 | __BIOVEC_PHYS_MERGEABLE(vec1, vec2) |
245 | #endif | 249 | #endif |
246 | 250 | ||
247 | #define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \ | 251 | #define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \ |
diff --git a/include/linux/timer.h b/include/linux/timer.h index d4ba79248a27..daf9685b861c 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h | |||
@@ -186,4 +186,9 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu); | |||
186 | unsigned long round_jiffies(unsigned long j); | 186 | unsigned long round_jiffies(unsigned long j); |
187 | unsigned long round_jiffies_relative(unsigned long j); | 187 | unsigned long round_jiffies_relative(unsigned long j); |
188 | 188 | ||
189 | unsigned long __round_jiffies_up(unsigned long j, int cpu); | ||
190 | unsigned long __round_jiffies_up_relative(unsigned long j, int cpu); | ||
191 | unsigned long round_jiffies_up(unsigned long j); | ||
192 | unsigned long round_jiffies_up_relative(unsigned long j); | ||
193 | |||
189 | #endif | 194 | #endif |
diff --git a/kernel/smp.c b/kernel/smp.c index f362a8553777..75c8dde58c55 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
@@ -51,10 +51,6 @@ static void csd_flag_wait(struct call_single_data *data) | |||
51 | { | 51 | { |
52 | /* Wait for response */ | 52 | /* Wait for response */ |
53 | do { | 53 | do { |
54 | /* | ||
55 | * We need to see the flags store in the IPI handler | ||
56 | */ | ||
57 | smp_mb(); | ||
58 | if (!(data->flags & CSD_FLAG_WAIT)) | 54 | if (!(data->flags & CSD_FLAG_WAIT)) |
59 | break; | 55 | break; |
60 | cpu_relax(); | 56 | cpu_relax(); |
@@ -76,6 +72,11 @@ static void generic_exec_single(int cpu, struct call_single_data *data) | |||
76 | list_add_tail(&data->list, &dst->list); | 72 | list_add_tail(&data->list, &dst->list); |
77 | spin_unlock_irqrestore(&dst->lock, flags); | 73 | spin_unlock_irqrestore(&dst->lock, flags); |
78 | 74 | ||
75 | /* | ||
76 | * Make the list addition visible before sending the ipi. | ||
77 | */ | ||
78 | smp_mb(); | ||
79 | |||
79 | if (ipi) | 80 | if (ipi) |
80 | arch_send_call_function_single_ipi(cpu); | 81 | arch_send_call_function_single_ipi(cpu); |
81 | 82 | ||
@@ -157,7 +158,7 @@ void generic_smp_call_function_single_interrupt(void) | |||
157 | * Need to see other stores to list head for checking whether | 158 | * Need to see other stores to list head for checking whether |
158 | * list is empty without holding q->lock | 159 | * list is empty without holding q->lock |
159 | */ | 160 | */ |
160 | smp_mb(); | 161 | smp_read_barrier_depends(); |
161 | while (!list_empty(&q->list)) { | 162 | while (!list_empty(&q->list)) { |
162 | unsigned int data_flags; | 163 | unsigned int data_flags; |
163 | 164 | ||
@@ -191,7 +192,7 @@ void generic_smp_call_function_single_interrupt(void) | |||
191 | /* | 192 | /* |
192 | * See comment on outer loop | 193 | * See comment on outer loop |
193 | */ | 194 | */ |
194 | smp_mb(); | 195 | smp_read_barrier_depends(); |
195 | } | 196 | } |
196 | } | 197 | } |
197 | 198 | ||
@@ -370,6 +371,11 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info, | |||
370 | list_add_tail_rcu(&data->csd.list, &call_function_queue); | 371 | list_add_tail_rcu(&data->csd.list, &call_function_queue); |
371 | spin_unlock_irqrestore(&call_function_lock, flags); | 372 | spin_unlock_irqrestore(&call_function_lock, flags); |
372 | 373 | ||
374 | /* | ||
375 | * Make the list addition visible before sending the ipi. | ||
376 | */ | ||
377 | smp_mb(); | ||
378 | |||
373 | /* Send a message to all CPUs in the map */ | 379 | /* Send a message to all CPUs in the map */ |
374 | arch_send_call_function_ipi(mask); | 380 | arch_send_call_function_ipi(mask); |
375 | 381 | ||
diff --git a/kernel/timer.c b/kernel/timer.c index 56becf373c58..dbd50fabe4c7 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base) | |||
112 | tbase_get_deferrable(timer->base)); | 112 | tbase_get_deferrable(timer->base)); |
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | static unsigned long round_jiffies_common(unsigned long j, int cpu, |
116 | * __round_jiffies - function to round jiffies to a full second | 116 | bool force_up) |
117 | * @j: the time in (absolute) jiffies that should be rounded | ||
118 | * @cpu: the processor number on which the timeout will happen | ||
119 | * | ||
120 | * __round_jiffies() rounds an absolute time in the future (in jiffies) | ||
121 | * up or down to (approximately) full seconds. This is useful for timers | ||
122 | * for which the exact time they fire does not matter too much, as long as | ||
123 | * they fire approximately every X seconds. | ||
124 | * | ||
125 | * By rounding these timers to whole seconds, all such timers will fire | ||
126 | * at the same time, rather than at various times spread out. The goal | ||
127 | * of this is to have the CPU wake up less, which saves power. | ||
128 | * | ||
129 | * The exact rounding is skewed for each processor to avoid all | ||
130 | * processors firing at the exact same time, which could lead | ||
131 | * to lock contention or spurious cache line bouncing. | ||
132 | * | ||
133 | * The return value is the rounded version of the @j parameter. | ||
134 | */ | ||
135 | unsigned long __round_jiffies(unsigned long j, int cpu) | ||
136 | { | 117 | { |
137 | int rem; | 118 | int rem; |
138 | unsigned long original = j; | 119 | unsigned long original = j; |
@@ -154,8 +135,9 @@ unsigned long __round_jiffies(unsigned long j, int cpu) | |||
154 | * due to delays of the timer irq, long irq off times etc etc) then | 135 | * due to delays of the timer irq, long irq off times etc etc) then |
155 | * we should round down to the whole second, not up. Use 1/4th second | 136 | * we should round down to the whole second, not up. Use 1/4th second |
156 | * as cutoff for this rounding as an extreme upper bound for this. | 137 | * as cutoff for this rounding as an extreme upper bound for this. |
138 | * But never round down if @force_up is set. | ||
157 | */ | 139 | */ |
158 | if (rem < HZ/4) /* round down */ | 140 | if (rem < HZ/4 && !force_up) /* round down */ |
159 | j = j - rem; | 141 | j = j - rem; |
160 | else /* round up */ | 142 | else /* round up */ |
161 | j = j - rem + HZ; | 143 | j = j - rem + HZ; |
@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu) | |||
167 | return original; | 149 | return original; |
168 | return j; | 150 | return j; |
169 | } | 151 | } |
152 | |||
153 | /** | ||
154 | * __round_jiffies - function to round jiffies to a full second | ||
155 | * @j: the time in (absolute) jiffies that should be rounded | ||
156 | * @cpu: the processor number on which the timeout will happen | ||
157 | * | ||
158 | * __round_jiffies() rounds an absolute time in the future (in jiffies) | ||
159 | * up or down to (approximately) full seconds. This is useful for timers | ||
160 | * for which the exact time they fire does not matter too much, as long as | ||
161 | * they fire approximately every X seconds. | ||
162 | * | ||
163 | * By rounding these timers to whole seconds, all such timers will fire | ||
164 | * at the same time, rather than at various times spread out. The goal | ||
165 | * of this is to have the CPU wake up less, which saves power. | ||
166 | * | ||
167 | * The exact rounding is skewed for each processor to avoid all | ||
168 | * processors firing at the exact same time, which could lead | ||
169 | * to lock contention or spurious cache line bouncing. | ||
170 | * | ||
171 | * The return value is the rounded version of the @j parameter. | ||
172 | */ | ||
173 | unsigned long __round_jiffies(unsigned long j, int cpu) | ||
174 | { | ||
175 | return round_jiffies_common(j, cpu, false); | ||
176 | } | ||
170 | EXPORT_SYMBOL_GPL(__round_jiffies); | 177 | EXPORT_SYMBOL_GPL(__round_jiffies); |
171 | 178 | ||
172 | /** | 179 | /** |
@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies); | |||
191 | */ | 198 | */ |
192 | unsigned long __round_jiffies_relative(unsigned long j, int cpu) | 199 | unsigned long __round_jiffies_relative(unsigned long j, int cpu) |
193 | { | 200 | { |
194 | /* | 201 | unsigned long j0 = jiffies; |
195 | * In theory the following code can skip a jiffy in case jiffies | 202 | |
196 | * increments right between the addition and the later subtraction. | 203 | /* Use j0 because jiffies might change while we run */ |
197 | * However since the entire point of this function is to use approximate | 204 | return round_jiffies_common(j + j0, cpu, false) - j0; |
198 | * timeouts, it's entirely ok to not handle that. | ||
199 | */ | ||
200 | return __round_jiffies(j + jiffies, cpu) - jiffies; | ||
201 | } | 205 | } |
202 | EXPORT_SYMBOL_GPL(__round_jiffies_relative); | 206 | EXPORT_SYMBOL_GPL(__round_jiffies_relative); |
203 | 207 | ||
@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative); | |||
218 | */ | 222 | */ |
219 | unsigned long round_jiffies(unsigned long j) | 223 | unsigned long round_jiffies(unsigned long j) |
220 | { | 224 | { |
221 | return __round_jiffies(j, raw_smp_processor_id()); | 225 | return round_jiffies_common(j, raw_smp_processor_id(), false); |
222 | } | 226 | } |
223 | EXPORT_SYMBOL_GPL(round_jiffies); | 227 | EXPORT_SYMBOL_GPL(round_jiffies); |
224 | 228 | ||
@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j) | |||
243 | } | 247 | } |
244 | EXPORT_SYMBOL_GPL(round_jiffies_relative); | 248 | EXPORT_SYMBOL_GPL(round_jiffies_relative); |
245 | 249 | ||
250 | /** | ||
251 | * __round_jiffies_up - function to round jiffies up to a full second | ||
252 | * @j: the time in (absolute) jiffies that should be rounded | ||
253 | * @cpu: the processor number on which the timeout will happen | ||
254 | * | ||
255 | * This is the same as __round_jiffies() except that it will never | ||
256 | * round down. This is useful for timeouts for which the exact time | ||
257 | * of firing does not matter too much, as long as they don't fire too | ||
258 | * early. | ||
259 | */ | ||
260 | unsigned long __round_jiffies_up(unsigned long j, int cpu) | ||
261 | { | ||
262 | return round_jiffies_common(j, cpu, true); | ||
263 | } | ||
264 | EXPORT_SYMBOL_GPL(__round_jiffies_up); | ||
265 | |||
266 | /** | ||
267 | * __round_jiffies_up_relative - function to round jiffies up to a full second | ||
268 | * @j: the time in (relative) jiffies that should be rounded | ||
269 | * @cpu: the processor number on which the timeout will happen | ||
270 | * | ||
271 | * This is the same as __round_jiffies_relative() except that it will never | ||
272 | * round down. This is useful for timeouts for which the exact time | ||
273 | * of firing does not matter too much, as long as they don't fire too | ||
274 | * early. | ||
275 | */ | ||
276 | unsigned long __round_jiffies_up_relative(unsigned long j, int cpu) | ||
277 | { | ||
278 | unsigned long j0 = jiffies; | ||
279 | |||
280 | /* Use j0 because jiffies might change while we run */ | ||
281 | return round_jiffies_common(j + j0, cpu, true) - j0; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(__round_jiffies_up_relative); | ||
284 | |||
285 | /** | ||
286 | * round_jiffies_up - function to round jiffies up to a full second | ||
287 | * @j: the time in (absolute) jiffies that should be rounded | ||
288 | * | ||
289 | * This is the same as round_jiffies() except that it will never | ||
290 | * round down. This is useful for timeouts for which the exact time | ||
291 | * of firing does not matter too much, as long as they don't fire too | ||
292 | * early. | ||
293 | */ | ||
294 | unsigned long round_jiffies_up(unsigned long j) | ||
295 | { | ||
296 | return round_jiffies_common(j, raw_smp_processor_id(), true); | ||
297 | } | ||
298 | EXPORT_SYMBOL_GPL(round_jiffies_up); | ||
299 | |||
300 | /** | ||
301 | * round_jiffies_up_relative - function to round jiffies up to a full second | ||
302 | * @j: the time in (relative) jiffies that should be rounded | ||
303 | * | ||
304 | * This is the same as round_jiffies_relative() except that it will never | ||
305 | * round down. This is useful for timeouts for which the exact time | ||
306 | * of firing does not matter too much, as long as they don't fire too | ||
307 | * early. | ||
308 | */ | ||
309 | unsigned long round_jiffies_up_relative(unsigned long j) | ||
310 | { | ||
311 | return __round_jiffies_up_relative(j, raw_smp_processor_id()); | ||
312 | } | ||
313 | EXPORT_SYMBOL_GPL(round_jiffies_up_relative); | ||
314 | |||
246 | 315 | ||
247 | static inline void set_running_timer(struct tvec_base *base, | 316 | static inline void set_running_timer(struct tvec_base *base, |
248 | struct timer_list *timer) | 317 | struct timer_list *timer) |