[patch] run_task_queue(&tq_disk) overhead in __wait_on_xxx

Andrea Arcangeli (andrea@e-mind.com)
Wed, 28 Apr 1999 22:31:54 +0200 (CEST)


I think the implementation of wait_on_page() and wait_on_buffer() are not
too much friendly with the I/O subsystem. The problem is that such two
functions does a run_task_queue() even if after the wakeup the page was
just unlocked. So they are probably going to do I/O too early even if not
needed.

Index: fs/buffer.c
===================================================================
RCS file: /var/cvs/linux/fs/buffer.c,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 buffer.c
--- linux/fs/buffer.c 1999/03/29 21:38:51 1.1.1.8
+++ linux/fs/buffer.c 1999/04/28 20:09:41
@@ -134,13 +134,13 @@
bh->b_count++;
wait.task = tsk;
add_wait_queue(&bh->b_wait, &wait);
-repeat:
- tsk->state = TASK_UNINTERRUPTIBLE;
- run_task_queue(&tq_disk);
- if (buffer_locked(bh)) {
+ do {
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ run_task_queue(&tq_disk);
+ if (!buffer_locked(bh))
+ break;
schedule();
- goto repeat;
- }
+ } while (buffer_locked(bh));
tsk->state = TASK_RUNNING;
remove_wait_queue(&bh->b_wait, &wait);
bh->b_count--;
Index: mm/filemap.c
===================================================================
RCS file: /var/cvs/linux/mm/filemap.c,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 filemap.c
--- linux/mm/filemap.c 1999/03/24 00:53:22 1.1.1.8
+++ linux/mm/filemap.c 1999/04/28 20:08:23
@@ -310,13 +310,13 @@

wait.task = tsk;
add_wait_queue(&page->wait, &wait);
-repeat:
- tsk->state = TASK_UNINTERRUPTIBLE;
- run_task_queue(&tq_disk);
- if (PageLocked(page)) {
+ do {
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ run_task_queue(&tq_disk);
+ if (!PageLocked(page))
+ break;
schedule();
- goto repeat;
- }
+ } while (PageLocked(page));
tsk->state = TASK_RUNNING;
remove_wait_queue(&page->wait, &wait);
}

It would be interesting to know if this patch does any performance
difference in real world... the patch make sense to me thoguh, so I am
posting it.

This second patch instead fix a subtle race I seen some month ago in the
swap code, the problem was that we was running a sleep_on but the wakeup
is going to happen in a irq handler beween the test and the sleep_on).

Index: mm/page_io.c
===================================================================
RCS file: /var/cvs/linux/mm/page_io.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 page_io.c
--- linux/mm/page_io.c 1999/01/18 01:27:01 1.1.1.1
+++ linux/mm/page_io.c 1999/04/28 20:15:17
@@ -86,9 +86,22 @@

if (PageSwapCache(page)) {
/* Make sure we are the only process doing I/O with this swap page. */
- while (test_and_set_bit(offset,p->swap_lockmap)) {
- run_task_queue(&tq_disk);
- sleep_on(&lock_queue);
+ if (test_and_set_bit(offset,p->swap_lockmap))
+ {
+ struct task_struct *tsk = current;
+ struct wait_queue wait;
+
+ wait.task = tsk;
+ add_wait_queue(&lock_queue, &wait);
+ do {
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ run_task_queue(&tq_disk);
+ if (!test_and_set_bit(offset, p->swap_lockmap))
+ break;
+ schedule();
+ } while (test_and_set_bit(offset, p->swap_lockmap));
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(&lock_queue, &wait);
}

/*

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/