diff options
Diffstat (limited to 'packages/linux/openzaurus-pxa27x-2.4.20-rmk2-embedix20050228/P14-lowlatency_041221.patch')
-rw-r--r-- | packages/linux/openzaurus-pxa27x-2.4.20-rmk2-embedix20050228/P14-lowlatency_041221.patch | 1677 |
1 files changed, 0 insertions, 1677 deletions
diff --git a/packages/linux/openzaurus-pxa27x-2.4.20-rmk2-embedix20050228/P14-lowlatency_041221.patch b/packages/linux/openzaurus-pxa27x-2.4.20-rmk2-embedix20050228/P14-lowlatency_041221.patch deleted file mode 100644 index edd63fb13b..0000000000 --- a/packages/linux/openzaurus-pxa27x-2.4.20-rmk2-embedix20050228/P14-lowlatency_041221.patch +++ /dev/null @@ -1,1677 +0,0 @@ -diff -Nur c3000_pre/linux/arch/arm/config.in c3000_test/linux/arch/arm/config.in ---- c3000_pre/linux/arch/arm/config.in 2004-12-16 22:55:34.000000000 +0900 -+++ c3000_test/linux/arch/arm/config.in 2004-12-20 23:23:28.000000000 +0900 -@@ -574,6 +574,8 @@ - fi - fi - dep_bool 'Preemptible Kernel support' CONFIG_PREEMPT $CONFIG_CPU_32 -+bool 'Low latency scheduling' CONFIG_LOLAT -+dep_bool 'Control low latency with sysctl' CONFIG_LOLAT_SYSCTL $CONFIG_LOLAT - - endmenu - -diff -Nur c3000_pre/linux/arch/i386/config.in c3000_test/linux/arch/i386/config.in ---- c3000_pre/linux/arch/i386/config.in 2004-08-21 09:48:09.000000000 +0900 -+++ c3000_test/linux/arch/i386/config.in 2004-12-20 22:56:21.000000000 +0900 -@@ -25,6 +25,9 @@ - - mainmenu_option next_comment - comment 'Processor type and features' -+bool 'Low latency scheduling' CONFIG_LOLAT -+dep_bool 'Control low latency with sysctl' CONFIG_LOLAT_SYSCTL $CONFIG_LOLAT -+ - choice 'Processor family' \ - "386 CONFIG_M386 \ - 486 CONFIG_M486 \ -diff -Nur c3000_pre/linux/drivers/block/ll_rw_blk.c c3000_test/linux/drivers/block/ll_rw_blk.c ---- c3000_pre/linux/drivers/block/ll_rw_blk.c 2004-08-21 09:48:24.000000000 +0900 -+++ c3000_test/linux/drivers/block/ll_rw_blk.c 2004-12-20 22:56:21.000000000 +0900 -@@ -1211,6 +1211,7 @@ - kstat.pgpgin += count; - break; - } -+ conditional_schedule(); - } - - /** -diff -Nur c3000_pre/linux/drivers/char/mem.c c3000_test/linux/drivers/char/mem.c ---- c3000_pre/linux/drivers/char/mem.c 2004-08-21 09:48:25.000000000 +0900 -+++ c3000_test/linux/drivers/char/mem.c 2004-12-20 22:56:21.000000000 +0900 -@@ -422,7 +422,7 @@ - if (count > size) - count = size; - -- zap_page_range(mm, addr, count); -+ zap_page_range(mm, addr, count, 0); - zeromap_page_range(addr, count, PAGE_COPY); - - size -= count; -diff -Nur c3000_pre/linux/drivers/char/random.c c3000_test/linux/drivers/char/random.c ---- c3000_pre/linux/drivers/char/random.c 2004-08-21 09:48:25.000000000 +0900 -+++ c3000_test/linux/drivers/char/random.c 2004-12-20 22:56:21.000000000 +0900 -@@ -1374,6 +1374,11 @@ - buf += i; - ret += i; - add_timer_randomness(&extract_timer_state, nbytes); -+#if LOWLATENCY_NEEDED -+ /* This can happen in softirq's, but that's what we want */ -+ if (conditional_schedule_needed()) -+ break; -+#endif - } - - /* Wipe data just returned from memory */ -diff -Nur c3000_pre/linux/drivers/i2c/i2c-core.c c3000_test/linux/drivers/i2c/i2c-core.c ---- c3000_pre/linux/drivers/i2c/i2c-core.c 2004-08-21 09:48:34.000000000 +0900 -+++ c3000_test/linux/drivers/i2c/i2c-core.c 2004-12-20 22:56:21.000000000 +0900 -@@ -761,6 +761,8 @@ - { - int ret; - -+ conditional_schedule(); -+ - if (adap->algo->master_xfer) { - DEB2(printk("i2c-core.o: master_xfer: %s with %d msgs.\n", - adap->name,num)); -@@ -783,6 +785,8 @@ - struct i2c_adapter *adap=client->adapter; - struct i2c_msg msg; - -+ conditional_schedule(); -+ - if (client->adapter->algo->master_xfer) { - msg.addr = client->addr; - msg.flags = client->flags & I2C_M_TEN; -@@ -812,6 +816,9 @@ - struct i2c_adapter *adap=client->adapter; - struct i2c_msg msg; - int ret; -+ -+ conditional_schedule(); -+ - if (client->adapter->algo->master_xfer) { - msg.addr = client->addr; - msg.flags = client->flags & I2C_M_TEN; -diff -Nur c3000_pre/linux/fs/buffer.c c3000_test/linux/fs/buffer.c ---- c3000_pre/linux/fs/buffer.c 2004-08-21 09:48:58.000000000 +0900 -+++ c3000_test/linux/fs/buffer.c 2004-12-20 22:56:21.000000000 +0900 -@@ -216,8 +216,10 @@ - - if (dev != NODEV && bh->b_dev != dev) - continue; -- if (test_and_set_bit(BH_Lock, &bh->b_state)) -+ if (test_and_set_bit(BH_Lock, &bh->b_state)) { -+ __refile_buffer(bh); - continue; -+ } - if (atomic_set_buffer_clean(bh)) { - __refile_buffer(bh); - get_bh(bh); -@@ -227,6 +229,7 @@ - - spin_unlock(&lru_list_lock); - write_locked_buffers(array, count); -+ conditional_schedule(); - return -EAGAIN; - } - unlock_buffer(bh); -@@ -260,12 +263,19 @@ - struct buffer_head * next; - int nr; - -- next = lru_list[index]; - nr = nr_buffers_type[index]; -+repeat: -+ next = lru_list[index]; - while (next && --nr >= 0) { - struct buffer_head *bh = next; - next = bh->b_next_free; - -+ if (conditional_schedule_needed()) { -+ spin_unlock(&lru_list_lock); -+ unconditional_schedule(); -+ spin_lock(&lru_list_lock); -+ goto repeat; -+ } - if (!buffer_locked(bh)) { - if (refile) - __refile_buffer(bh); -@@ -273,7 +283,6 @@ - } - if (dev != NODEV && bh->b_dev != dev) - continue; -- - get_bh(bh); - spin_unlock(&lru_list_lock); - wait_on_buffer (bh); -@@ -306,6 +315,15 @@ - { - int err = 0; - -+#if LOWLATENCY_NEEDED -+ /* -+ * syncing devA when there are lots of buffers dirty against -+ * devB is expensive. -+ */ -+ if (enable_lowlatency) -+ dev = NODEV; -+#endif -+ - /* One pass for no-wait, three for wait: - * 0) write out all dirty, unlocked buffers; - * 1) wait for all dirty locked buffers; -@@ -697,6 +715,16 @@ - /* Not hashed? */ - if (!bh->b_pprev) - continue; -+ -+ if (conditional_schedule_needed()) { -+ get_bh(bh); -+ spin_unlock(&lru_list_lock); -+ unconditional_schedule(); -+ spin_lock(&lru_list_lock); -+ put_bh(bh); -+ slept = 1; -+ } -+ - if (buffer_locked(bh)) { - get_bh(bh); - spin_unlock(&lru_list_lock); -@@ -848,12 +876,19 @@ - struct buffer_head *bh; - struct inode tmp; - int err = 0, err2; -- -+ DEFINE_RESCHED_COUNT; -+ - INIT_LIST_HEAD(&tmp.i_dirty_buffers); -- -+ -+repeat: - spin_lock(&lru_list_lock); - - while (!list_empty(list)) { -+ if (conditional_schedule_needed()) { -+ spin_unlock(&lru_list_lock); -+ unconditional_schedule(); -+ goto repeat; -+ } - bh = BH_ENTRY(list->next); - list_del(&bh->b_inode_buffers); - if (!buffer_dirty(bh) && !buffer_locked(bh)) -@@ -878,8 +913,18 @@ - spin_lock(&lru_list_lock); - } - } -+ if (TEST_RESCHED_COUNT(32)) { -+ RESET_RESCHED_COUNT(); -+ if (conditional_schedule_needed()) { -+ spin_unlock(&lru_list_lock); -+ unconditional_schedule(); /* Syncing many dirty buffers */ -+ spin_lock(&lru_list_lock); -+ } -+ } - } - -+ RESET_RESCHED_COUNT(); -+ - while (!list_empty(&tmp.i_dirty_buffers)) { - bh = BH_ENTRY(tmp.i_dirty_buffers.prev); - remove_inode_queue(bh); -@@ -889,6 +934,7 @@ - if (!buffer_uptodate(bh)) - err = -EIO; - brelse(bh); -+ conditional_schedule(); - spin_lock(&lru_list_lock); - } - -@@ -916,11 +962,20 @@ - struct buffer_head *bh; - struct list_head *p; - int err = 0; -+ DEFINE_RESCHED_COUNT; - -+repeat: -+ conditional_schedule(); - spin_lock(&lru_list_lock); - -- repeat: - list_for_each_prev(p, list) { -+ if (TEST_RESCHED_COUNT(32)) { -+ RESET_RESCHED_COUNT(); -+ if (conditional_schedule_needed()) { -+ spin_unlock(&lru_list_lock); -+ goto repeat; -+ } -+ } - bh = BH_ENTRY(p); - if (buffer_locked(bh)) { - get_bh(bh); -@@ -929,7 +984,6 @@ - if (!buffer_uptodate(bh)) - err = -EIO; - brelse(bh); -- spin_lock(&lru_list_lock); - goto repeat; - } - } -@@ -946,12 +1000,24 @@ - void invalidate_inode_buffers(struct inode *inode) - { - struct list_head * entry; -- -+ -+repeat: -+ conditional_schedule(); - spin_lock(&lru_list_lock); -- while ((entry = inode->i_dirty_buffers.next) != &inode->i_dirty_buffers) -+ while ((entry = inode->i_dirty_buffers.next) != &inode->i_dirty_buffers) { -+ if (conditional_schedule_needed()) { -+ spin_unlock(&lru_list_lock); -+ goto repeat; -+ } - remove_inode_queue(BH_ENTRY(entry)); -- while ((entry = inode->i_dirty_data_buffers.next) != &inode->i_dirty_data_buffers) -+ } -+ while ((entry = inode->i_dirty_data_buffers.next) != &inode->i_dirty_data_buffers) { -+ if (conditional_schedule_needed()) { -+ spin_unlock(&lru_list_lock); -+ goto repeat; -+ } - remove_inode_queue(BH_ENTRY(entry)); -+ } - spin_unlock(&lru_list_lock); - } - -@@ -974,6 +1040,7 @@ - bh = get_hash_table(dev, block, size); - if (bh) { - touch_buffer(bh); -+ conditional_schedule(); - return bh; - } - -@@ -2831,7 +2898,7 @@ - - DECLARE_WAIT_QUEUE_HEAD(bdflush_wait); - --void wakeup_bdflush(void) -+void wakeup_bdflush(void) - { - wake_up_interruptible(&bdflush_wait); - } -diff -Nur c3000_pre/linux/fs/dcache.c c3000_test/linux/fs/dcache.c ---- c3000_pre/linux/fs/dcache.c 2004-08-21 09:48:58.000000000 +0900 -+++ c3000_test/linux/fs/dcache.c 2004-12-20 22:56:21.000000000 +0900 -@@ -320,11 +320,23 @@ - - void prune_dcache(int count) - { -+ DEFINE_RESCHED_COUNT; -+ -+redo: - spin_lock(&dcache_lock); - for (;;) { - struct dentry *dentry; - struct list_head *tmp; - -+ if (TEST_RESCHED_COUNT(100)) { -+ RESET_RESCHED_COUNT(); -+ if (conditional_schedule_needed()) { -+ spin_unlock(&dcache_lock); -+ unconditional_schedule(); -+ goto redo; -+ } -+ } -+ - tmp = dentry_unused.prev; - - if (tmp == &dentry_unused) -@@ -479,6 +491,7 @@ - struct dentry *this_parent = parent; - struct list_head *next; - int found = 0; -+ DEFINE_RESCHED_COUNT; - - spin_lock(&dcache_lock); - repeat: -@@ -493,6 +506,13 @@ - list_add(&dentry->d_lru, dentry_unused.prev); - found++; - } -+ -+ if (TEST_RESCHED_COUNT(500) && found > 10) { -+ if (conditional_schedule_needed()) /* Typically sys_rmdir() */ -+ goto out; -+ RESET_RESCHED_COUNT(); -+ } -+ - /* - * Descend a level if the d_subdirs list is non-empty. - */ -@@ -517,6 +537,7 @@ - #endif - goto resume; - } -+out: - spin_unlock(&dcache_lock); - return found; - } -@@ -532,8 +553,10 @@ - { - int found; - -- while ((found = select_parent(parent)) != 0) -+ while ((found = select_parent(parent)) != 0) { - prune_dcache(found); -+ conditional_schedule(); /* Typically sys_rmdir() */ -+ } - } - - /* -diff -Nur c3000_pre/linux/fs/exec.c c3000_test/linux/fs/exec.c ---- c3000_pre/linux/fs/exec.c 2004-08-21 09:48:58.000000000 +0900 -+++ c3000_test/linux/fs/exec.c 2004-12-20 22:56:21.000000000 +0900 -@@ -249,7 +249,7 @@ - memset(kaddr+offset+len, 0, - PAGE_SIZE-offset-len); - } -- err = copy_from_user(kaddr+offset, str, bytes_to_copy); -+ err = ll_copy_from_user(kaddr+offset, str, bytes_to_copy); - if (err) { - ret = -EFAULT; - goto out; -diff -Nur c3000_pre/linux/fs/ext2/dir.c c3000_test/linux/fs/ext2/dir.c ---- c3000_pre/linux/fs/ext2/dir.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/ext2/dir.c 2004-12-20 22:56:21.000000000 +0900 -@@ -153,6 +153,7 @@ - struct address_space *mapping = dir->i_mapping; - struct page *page = read_cache_page(mapping, n, - (filler_t*)mapping->a_ops->readpage, NULL); -+ conditional_schedule(); /* Scanning large directories */ - if (!IS_ERR(page)) { - wait_on_page(page); - kmap(page); -diff -Nur c3000_pre/linux/fs/ext2/inode.c c3000_test/linux/fs/ext2/inode.c ---- c3000_pre/linux/fs/ext2/inode.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/ext2/inode.c 2004-12-20 22:56:21.000000000 +0900 -@@ -715,8 +715,13 @@ - { - unsigned long block_to_free = 0, count = 0; - unsigned long nr; -+ DEFINE_RESCHED_COUNT; - - for ( ; p < q ; p++) { -+ if (TEST_RESCHED_COUNT(32)) { -+ RESET_RESCHED_COUNT(); -+ conditional_schedule(); -+ } - nr = le32_to_cpu(*p); - if (nr) { - *p = 0; -@@ -759,6 +764,7 @@ - if (depth--) { - int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - for ( ; p < q ; p++) { -+ conditional_schedule(); /* Deleting large files */ - nr = le32_to_cpu(*p); - if (!nr) - continue; -diff -Nur c3000_pre/linux/fs/ext3/balloc.c c3000_test/linux/fs/ext3/balloc.c ---- c3000_pre/linux/fs/ext3/balloc.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/ext3/balloc.c 2004-12-20 22:56:21.000000000 +0900 -@@ -363,6 +363,9 @@ - } - } - #endif -+ /* superblock lock is held, so this is safe */ -+ conditional_schedule(); -+ - BUFFER_TRACE(bitmap_bh, "clear bit"); - if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) { - ext3_error (sb, __FUNCTION__, -diff -Nur c3000_pre/linux/fs/ext3/inode.c c3000_test/linux/fs/ext3/inode.c ---- c3000_pre/linux/fs/ext3/inode.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/ext3/inode.c 2004-12-20 22:56:21.000000000 +0900 -@@ -902,6 +902,8 @@ - - prev_blocks = inode->i_blocks; - -+ conditional_schedule(); /* Reading large directories */ -+ - bh = ext3_getblk (handle, inode, block, create, err); - if (!bh) - return bh; -@@ -1605,6 +1607,7 @@ - */ - for (p = first; p < last; p++) { - u32 nr = le32_to_cpu(*p); -+ conditional_schedule(); - if (nr) { - struct buffer_head *bh; - -@@ -1659,6 +1662,7 @@ - } - - for (p = first; p < last; p++) { -+ conditional_schedule(); - nr = le32_to_cpu(*p); - if (nr) { - /* accumulate blocks to free if they're contiguous */ -diff -Nur c3000_pre/linux/fs/ext3/namei.c c3000_test/linux/fs/ext3/namei.c ---- c3000_pre/linux/fs/ext3/namei.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/ext3/namei.c 2004-12-20 22:56:21.000000000 +0900 -@@ -157,6 +157,7 @@ - if ((bh = bh_use[ra_ptr++]) == NULL) - goto next; - wait_on_buffer(bh); -+ conditional_schedule(); - if (!buffer_uptodate(bh)) { - /* read error, skip block & hope for the best */ - brelse(bh); -diff -Nur c3000_pre/linux/fs/inode.c c3000_test/linux/fs/inode.c ---- c3000_pre/linux/fs/inode.c 2004-08-21 09:48:58.000000000 +0900 -+++ c3000_test/linux/fs/inode.c 2004-12-20 23:00:06.000000000 +0900 -@@ -251,6 +251,8 @@ - - filemap_fdatawait(inode->i_mapping); - -+ conditional_schedule(); -+ - spin_lock(&inode_lock); - inode->i_state &= ~I_LOCK; - if (!(inode->i_state & I_FREEING)) { -@@ -561,6 +563,7 @@ - - while ((inode_entry = head->next) != head) - { -+ conditional_schedule(); - list_del(inode_entry); - - inode = list_entry(inode_entry, struct inode, i_list); -@@ -589,9 +592,22 @@ - if (tmp == head) - break; - inode = list_entry(tmp, struct inode, i_list); -+ -+ if (conditional_schedule_needed()) { -+ atomic_inc(&inode->i_count); -+ spin_unlock(&inode_lock); -+ unconditional_schedule(); -+ spin_lock(&inode_lock); -+ atomic_dec(&inode->i_count); -+ } -+ - if (inode->i_sb != sb) - continue; -+ atomic_inc(&inode->i_count); -+ spin_unlock(&inode_lock); - invalidate_inode_buffers(inode); -+ spin_lock(&inode_lock); -+ atomic_dec(&inode->i_count); - if (!atomic_read(&inode->i_count)) { - list_del_init(&inode->i_hash); - list_del(&inode->i_list); -@@ -896,6 +912,8 @@ - if (inode) { - struct inode * old; - -+ conditional_schedule(); /* sync_old_buffers */ -+ - spin_lock(&inode_lock); - /* We released the lock, so.. */ - old = find_inode(sb, ino, head, find_actor, opaque); -@@ -1313,18 +1331,32 @@ - int request=goal; - int loop=0; - #endif -+ int nr_to_scan = inodes_stat.nr_unused; - -+resume: - spin_lock(&inode_lock); - - count = 0; - entry = inode_unused.prev; -- while (entry != &inode_unused) -- { -+ while (entry != &inode_unused && nr_to_scan--) { - struct list_head *tmp = entry; - - #ifdef JFFS2_INODE_DEBUG - loop++; - #endif -+ if (conditional_schedule_needed()) { -+ /* -+ * Need to drop the lock. Reposition -+ * the list head so we start here next time. -+ * This can corrupt the LRU nature of the -+ * unused list, but this isn't very important. -+ */ -+ list_del(&inode_unused); -+ list_add(&inode_unused, entry); -+ spin_unlock(&inode_lock); -+ unconditional_schedule(); -+ goto resume; -+ } - entry = entry->prev; - inode = INODE(tmp); - if (inode->i_state & (I_FREEING|I_CLEAR|I_LOCK)) -diff -Nur c3000_pre/linux/fs/jbd/checkpoint.c c3000_test/linux/fs/jbd/checkpoint.c ---- c3000_pre/linux/fs/jbd/checkpoint.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/jbd/checkpoint.c 2004-12-20 22:56:21.000000000 +0900 -@@ -431,7 +431,11 @@ - { - transaction_t *transaction, *last_transaction, *next_transaction; - int ret = 0; -+ int ll_retries = 4; /* lowlatency addition */ - -+restart: -+ if (ll_retries-- == 0) -+ goto out; - transaction = journal->j_checkpoint_transactions; - if (transaction == 0) - goto out; -@@ -451,6 +455,12 @@ - jh = next_jh; - next_jh = jh->b_cpnext; - ret += __try_to_free_cp_buf(jh); -+ if (conditional_schedule_needed()) { -+ spin_unlock(&journal_datalist_lock); -+ unconditional_schedule(); -+ spin_lock(&journal_datalist_lock); -+ goto restart; -+ } - } while (jh != last_jh); - } - } while (transaction != last_transaction); -diff -Nur c3000_pre/linux/fs/jbd/commit.c c3000_test/linux/fs/jbd/commit.c ---- c3000_pre/linux/fs/jbd/commit.c 2004-08-21 09:48:59.000000000 +0900 -+++ c3000_test/linux/fs/jbd/commit.c 2004-12-20 22:56:21.000000000 +0900 -@@ -212,6 +212,16 @@ - __journal_remove_journal_head(bh); - refile_buffer(bh); - __brelse(bh); -+ if (conditional_schedule_needed()) { -+ if (commit_transaction->t_sync_datalist) -+ commit_transaction->t_sync_datalist = -+ next_jh; -+ if (bufs) -+ break; -+ spin_unlock(&journal_datalist_lock); -+ unconditional_schedule(); -+ goto write_out_data; -+ } - } - } - if (bufs == ARRAY_SIZE(wbuf)) { -@@ -235,8 +245,7 @@ - journal_brelse_array(wbuf, bufs); - lock_journal(journal); - spin_lock(&journal_datalist_lock); -- if (bufs) -- goto write_out_data_locked; -+ goto write_out_data_locked; - } - - /* -@@ -272,6 +281,14 @@ - */ - while ((jh = commit_transaction->t_async_datalist)) { - struct buffer_head *bh = jh2bh(jh); -+ if (conditional_schedule_needed()) { -+ spin_unlock(&journal_datalist_lock); -+ unlock_journal(journal); -+ unconditional_schedule(); -+ lock_journal(journal); -+ spin_lock(&journal_datalist_lock); -+ continue; /* List may have changed */ -+ } - if (buffer_locked(bh)) { - spin_unlock(&journal_datalist_lock); - unlock_journal(journal); -@@ -486,6 +503,8 @@ - wait_for_iobuf: - while (commit_transaction->t_iobuf_list != NULL) { - struct buffer_head *bh; -+ -+ conditional_schedule(); - jh = commit_transaction->t_iobuf_list->b_tprev; - bh = jh2bh(jh); - if (buffer_locked(bh)) { -@@ -644,6 +663,8 @@ - transaction_t *cp_transaction; - struct buffer_head *bh; - -+ conditional_schedule(); /* journal is locked */ -+ - jh = commit_transaction->t_forget; - J_ASSERT_JH(jh, jh->b_transaction == commit_transaction || - jh->b_transaction == journal->j_running_transaction); -diff -Nur c3000_pre/linux/fs/proc/array.c c3000_test/linux/fs/proc/array.c ---- c3000_pre/linux/fs/proc/array.c 2004-08-21 09:49:01.000000000 +0900 -+++ c3000_test/linux/fs/proc/array.c 2004-12-20 22:56:21.000000000 +0900 -@@ -498,9 +498,11 @@ - if (end > PMD_SIZE) - end = PMD_SIZE; - do { -- pte_t page = *pte; -+ pte_t page; - struct page *ptpage; - -+ conditional_schedule(); /* For `top' and `ps' */ -+ page = *pte; - address += PAGE_SIZE; - pte++; - if (pte_none(page)) -diff -Nur c3000_pre/linux/fs/proc/generic.c c3000_test/linux/fs/proc/generic.c ---- c3000_pre/linux/fs/proc/generic.c 2004-08-21 09:49:01.000000000 +0900 -+++ c3000_test/linux/fs/proc/generic.c 2004-12-20 22:56:21.000000000 +0900 -@@ -98,6 +98,8 @@ - retval = n; - break; - } -+ -+ conditional_schedule(); /* Some /proc files are large */ - - /* This is a hack to allow mangling of file pos independent - * of actual bytes read. Simply place the data at page, -diff -Nur c3000_pre/linux/fs/reiserfs/buffer2.c c3000_test/linux/fs/reiserfs/buffer2.c ---- c3000_pre/linux/fs/reiserfs/buffer2.c 2004-08-21 09:49:01.000000000 +0900 -+++ c3000_test/linux/fs/reiserfs/buffer2.c 2004-12-20 22:56:21.000000000 +0900 -@@ -54,6 +54,7 @@ - PROC_EXP( unsigned int ctx_switches = kstat.context_swtch ); - - result = bread (super -> s_dev, n_block, n_size); -+ conditional_schedule(); - PROC_INFO_INC( super, breads ); - PROC_EXP( if( kstat.context_swtch != ctx_switches ) - PROC_INFO_INC( super, bread_miss ) ); -diff -Nur c3000_pre/linux/fs/reiserfs/journal.c c3000_test/linux/fs/reiserfs/journal.c ---- c3000_pre/linux/fs/reiserfs/journal.c 2004-08-21 09:49:01.000000000 +0900 -+++ c3000_test/linux/fs/reiserfs/journal.c 2004-12-20 22:56:21.000000000 +0900 -@@ -573,6 +573,7 @@ - /* lock the current transaction */ - inline static void lock_journal(struct super_block *p_s_sb) { - PROC_INFO_INC( p_s_sb, journal.lock_journal ); -+ conditional_schedule(); - while(atomic_read(&(SB_JOURNAL(p_s_sb)->j_wlock)) > 0) { - PROC_INFO_INC( p_s_sb, journal.lock_journal_wait ); - sleep_on(&(SB_JOURNAL(p_s_sb)->j_wait)) ; -@@ -703,6 +704,7 @@ - mark_buffer_dirty(tbh) ; - } - ll_rw_block(WRITE, 1, &tbh) ; -+ conditional_schedule(); - count++ ; - put_bh(tbh) ; /* once for our get_hash */ - } -@@ -832,6 +834,7 @@ - set_bit(BH_Dirty, &(SB_JOURNAL(p_s_sb)->j_header_bh->b_state)) ; - ll_rw_block(WRITE, 1, &(SB_JOURNAL(p_s_sb)->j_header_bh)) ; - wait_on_buffer((SB_JOURNAL(p_s_sb)->j_header_bh)) ; -+ conditional_schedule(); - if (!buffer_uptodate(SB_JOURNAL(p_s_sb)->j_header_bh)) { - printk( "reiserfs: journal-837: IO error during journal replay\n" ); - return -EIO ; -@@ -2125,6 +2128,7 @@ - } - - int journal_begin(struct reiserfs_transaction_handle *th, struct super_block * p_s_sb, unsigned long nblocks) { -+ conditional_schedule(); - return do_journal_begin_r(th, p_s_sb, nblocks, 0) ; - } - -@@ -2265,6 +2269,7 @@ - } - - int journal_end(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) { -+ conditional_schedule(); - return do_journal_end(th, p_s_sb, nblocks, 0) ; - } - -@@ -2716,6 +2721,7 @@ - RFALSE( buffer_locked(bh) && cur_tb != NULL, - "waiting while do_balance was running\n") ; - wait_on_buffer(bh) ; -+ conditional_schedule(); - } - PROC_INFO_INC( p_s_sb, journal.prepare_retry ); - retry_count++ ; -@@ -2888,6 +2894,7 @@ - /* copy all the real blocks into log area. dirty log blocks */ - if (test_bit(BH_JDirty, &cn->bh->b_state)) { - struct buffer_head *tmp_bh ; -+ conditional_schedule(); - tmp_bh = sb_getblk(p_s_sb, reiserfs_get_journal_block(p_s_sb) + - ((cur_write_start + jindex) % JOURNAL_BLOCK_COUNT)) ; - mark_buffer_uptodate(tmp_bh, 1) ; -diff -Nur c3000_pre/linux/fs/reiserfs/stree.c c3000_test/linux/fs/reiserfs/stree.c ---- c3000_pre/linux/fs/reiserfs/stree.c 2004-08-21 09:49:01.000000000 +0900 -+++ c3000_test/linux/fs/reiserfs/stree.c 2004-12-20 22:56:21.000000000 +0900 -@@ -652,9 +652,8 @@ - stop at leaf level - set to - DISK_LEAF_NODE_LEVEL */ - ) { -- int n_block_number = SB_ROOT_BLOCK (p_s_sb), -- expected_level = SB_TREE_HEIGHT (p_s_sb), -- n_block_size = p_s_sb->s_blocksize; -+ int n_block_number, expected_level; -+ int n_block_size = p_s_sb->s_blocksize; - struct buffer_head * p_s_bh; - struct path_element * p_s_last_element; - int n_node_level, n_retval; -@@ -666,7 +665,8 @@ - #endif - - PROC_INFO_INC( p_s_sb, search_by_key ); -- -+ conditional_schedule(); -+ - /* As we add each node to a path we increase its count. This means that - we must be careful to release all nodes in a path before we either - discard the path struct or re-use the path struct, as we do here. */ -@@ -678,6 +678,8 @@ - /* With each iteration of this loop we search through the items in the - current node, and calculate the next current node(next path element) - for the next iteration of this loop.. */ -+ n_block_number = SB_ROOT_BLOCK (p_s_sb); -+ expected_level = SB_TREE_HEIGHT (p_s_sb); - while ( 1 ) { - - #ifdef CONFIG_REISERFS_CHECK -@@ -1104,6 +1106,8 @@ - for (n_counter = *p_n_removed; - n_counter < n_unfm_number; n_counter++, p_n_unfm_pointer-- ) { - -+ conditional_schedule(); -+ - if (item_moved (&s_ih, p_s_path)) { - need_research = 1 ; - break; -diff -Nur c3000_pre/linux/include/linux/low-latency.h c3000_test/linux/include/linux/low-latency.h ---- c3000_pre/linux/include/linux/low-latency.h 1970-01-01 09:00:00.000000000 +0900 -+++ c3000_test/linux/include/linux/low-latency.h 2004-12-20 22:56:21.000000000 +0900 -@@ -0,0 +1,109 @@ -+/* -+ * include/linux/low-latency.h -+ * -+ * Andrew Morton <akpm@zip.com.au> -+ */ -+ -+#ifndef LOW_LATENCY_H_INCLUDED -+#define LOW_LATENCY_H_INCLUDED -+ -+#if defined(CONFIG_LOLAT) -+#define LOWLATENCY_NEEDED 1 -+#else -+#define LOWLATENCY_NEEDED 0 -+#endif -+ -+#if LOWLATENCY_NEEDED -+ -+#include <linux/cache.h> /* For ____cacheline_aligned */ -+ -+#ifdef CONFIG_LOLAT_SYSCTL -+extern struct low_latency_enable_struct { -+ int yep; -+} ____cacheline_aligned __enable_lowlatency; -+#define enable_lowlatency __enable_lowlatency.yep -+ -+#else -+#define enable_lowlatency 1 -+#endif -+ -+/* -+ * Set this non-zero to generate low-latency instrumentation -+ */ -+#define LOWLATENCY_DEBUG 0 -+ -+/* -+ * Set this non-zero for robustness testing -+ */ -+#define LOWLATENCY_ALWAYS_SCHEDULE 0 -+ -+#if LOWLATENCY_DEBUG -+ -+#if LOWLATENCY_ALWAYS_SCHEDULE -+#define conditional_schedule_needed() ((enable_lowlatency == 2) || (enable_lowlatency && current->need_resched)) -+#else -+#define conditional_schedule_needed() (enable_lowlatency && current->need_resched) -+#endif -+ -+struct lolat_stats_t { -+ unsigned long count; -+ int visited; -+ const char *file; -+ int line; -+ struct lolat_stats_t *next; -+}; -+ -+void set_running_and_schedule(struct lolat_stats_t *stats); -+ -+#define unconditional_schedule() \ -+ do { \ -+ static struct lolat_stats_t stats = { \ -+ file: __FILE__, \ -+ line: __LINE__, \ -+ }; \ -+ set_running_and_schedule(&stats); \ -+ } while (0) -+ -+extern void show_lolat_stats(void); -+ -+#else /* LOWLATENCY_DEBUG */ -+ -+#if LOWLATENCY_ALWAYS_SCHEDULE -+#define conditional_schedule_needed() 1 -+#else -+#define conditional_schedule_needed() (current->need_resched) -+#endif -+ -+void set_running_and_schedule(void); -+#define unconditional_schedule() set_running_and_schedule() -+ -+#endif /* LOWLATENCY_DEBUG */ -+ -+#define conditional_schedule() \ -+ do { \ -+ if (conditional_schedule_needed()) \ -+ unconditional_schedule(); \ -+ } while (0) -+ -+#define DEFINE_RESCHED_COUNT int resched_count = 0 -+#define TEST_RESCHED_COUNT(n) (enable_lowlatency && (++resched_count > (n))) -+#define RESET_RESCHED_COUNT() resched_count = 0 -+extern int ll_copy_to_user(void *to_user, const void *from, unsigned long len); -+extern int ll_copy_from_user(void *to, const void *from_user, unsigned long len); -+ -+#else /* LOWLATENCY_NEEDED */ -+ -+#define conditional_schedule_needed() 0 -+#define conditional_schedule() -+#define unconditional_schedule() -+ -+#define DEFINE_RESCHED_COUNT -+#define TEST_RESCHED_COUNT(n) 0 -+#define RESET_RESCHED_COUNT() -+#define ll_copy_to_user(to_user, from, len) copy_to_user((to_user), (from), (len)) -+#define ll_copy_from_user(to, from_user, len) copy_from_user((to), (from_user), (len)) -+ -+#endif /* LOWLATENCY_NEEDED */ -+ -+#endif /* LOW_LATENCY_H_INCLUDED */ -+ -diff -Nur c3000_pre/linux/include/linux/mm.h c3000_test/linux/include/linux/mm.h ---- c3000_pre/linux/include/linux/mm.h 2004-08-21 09:49:13.000000000 +0900 -+++ c3000_test/linux/include/linux/mm.h 2004-12-20 22:56:21.000000000 +0900 -@@ -149,6 +149,8 @@ - */ - extern pgprot_t protection_map[16]; - -+/* Actions for zap_page_range() */ -+#define ZPR_COND_RESCHED 1 /* Do a conditional_schedule() occasionally */ - - /* - * These are the virtual MM functions - opening of an area, closing and -@@ -500,7 +502,7 @@ - extern void shmem_lock(struct file * file, int lock); - extern int shmem_zero_setup(struct vm_area_struct *); - --extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size); -+extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size, int actions); - extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma); - extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot); - extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot); -diff -Nur c3000_pre/linux/include/linux/reiserfs_fs.h c3000_test/linux/include/linux/reiserfs_fs.h ---- c3000_pre/linux/include/linux/reiserfs_fs.h 2004-08-21 09:49:13.000000000 +0900 -+++ c3000_test/linux/include/linux/reiserfs_fs.h 2004-12-20 22:56:21.000000000 +0900 -@@ -1197,8 +1197,8 @@ - #define fs_generation(s) ((s)->u.reiserfs_sb.s_generation_counter) - #define get_generation(s) atomic_read (&fs_generation(s)) - #define FILESYSTEM_CHANGED_TB(tb) (get_generation((tb)->tb_sb) != (tb)->fs_gen) --#define fs_changed(gen,s) (gen != get_generation (s)) -- -+#define __fs_changed(gen,s) (gen != get_generation (s)) -+#define fs_changed(gen,s) ({conditional_schedule(); __fs_changed(gen,s);}) - - /***************************************************************************/ - /* FIXATE NODES */ -diff -Nur c3000_pre/linux/include/linux/sched.h c3000_test/linux/include/linux/sched.h ---- c3000_pre/linux/include/linux/sched.h 2004-08-21 09:49:13.000000000 +0900 -+++ c3000_test/linux/include/linux/sched.h 2004-12-20 22:56:21.000000000 +0900 -@@ -1092,6 +1092,7 @@ - #include <linux/dcache.h> - #include <linux/tqueue.h> - #include <linux/fs_struct.h> -+#include <linux/low-latency.h> - - #endif /* __KERNEL__ */ - #endif -diff -Nur c3000_pre/linux/include/linux/sysctl.h c3000_test/linux/include/linux/sysctl.h ---- c3000_pre/linux/include/linux/sysctl.h 2004-08-21 09:49:13.000000000 +0900 -+++ c3000_test/linux/include/linux/sysctl.h 2004-12-20 22:56:21.000000000 +0900 -@@ -131,6 +131,7 @@ - KERN_CORE_USES_PID=52, /* int: use core or core.%pid */ - KERN_TAINTED=53, /* int: various kernel tainted flags */ - KERN_CADPID=54, /* int: PID of the process to notify on CAD */ -+ KERN_LOWLATENCY=55, /* int: enable low latency scheduling */ - }; - - -diff -Nur c3000_pre/linux/kernel/exit.c c3000_test/linux/kernel/exit.c ---- c3000_pre/linux/kernel/exit.c 2004-08-21 09:49:14.000000000 +0900 -+++ c3000_test/linux/kernel/exit.c 2004-12-20 22:56:21.000000000 +0900 -@@ -196,6 +196,7 @@ - } - i++; - set >>= 1; -+ conditional_schedule(); /* sys_exit, many files open */ - } - } - } -diff -Nur c3000_pre/linux/kernel/ksyms.c c3000_test/linux/kernel/ksyms.c ---- c3000_pre/linux/kernel/ksyms.c 2004-12-19 00:35:59.000000000 +0900 -+++ c3000_test/linux/kernel/ksyms.c 2004-12-20 23:07:26.000000000 +0900 -@@ -481,6 +481,13 @@ - EXPORT_SYMBOL(do_gettimeofday); - EXPORT_SYMBOL(do_settimeofday); - -+#if LOWLATENCY_NEEDED -+EXPORT_SYMBOL(set_running_and_schedule); -+#ifdef CONFIG_LOLAT_SYSCTL -+EXPORT_SYMBOL(__enable_lowlatency); -+#endif -+#endif -+ - #if !defined(__ia64__) - EXPORT_SYMBOL(loops_per_jiffy); - #endif -diff -Nur c3000_pre/linux/kernel/module.c c3000_test/linux/kernel/module.c ---- c3000_pre/linux/kernel/module.c 2004-08-21 09:49:14.000000000 +0900 -+++ c3000_test/linux/kernel/module.c 2004-12-20 22:56:21.000000000 +0900 -@@ -1174,6 +1174,11 @@ - return ERR_PTR(-ENOMEM); - lock_kernel(); - for (v = module_list, n = *pos; v; n -= v->nsyms, v = v->next) { -+#if 0 -+ /* We can't actually do this, because we'd create a -+ * race against module unload. Need a semaphore. */ -+ conditional_schedule(); -+#endif - if (n < v->nsyms) { - p->mod = v; - p->index = n; -diff -Nur c3000_pre/linux/kernel/sched.c c3000_test/linux/kernel/sched.c ---- c3000_pre/linux/kernel/sched.c 2004-08-21 09:49:14.000000000 +0900 -+++ c3000_test/linux/kernel/sched.c 2004-12-20 22:56:21.000000000 +0900 -@@ -302,6 +302,17 @@ - if (tsk->processor != this_cpu) - smp_send_reschedule(tsk->processor); - } -+#if LOWLATENCY_NEEDED -+ if (enable_lowlatency && (p->policy != SCHED_OTHER)) { -+ struct task_struct *t; -+ for (i = 0; i < smp_num_cpus; i++) { -+ cpu = cpu_logical_map(i); -+ t = cpu_curr(cpu); -+ if (t != tsk) -+ t->need_resched = 1; -+ } -+ } -+#endif - return; - - -@@ -1429,3 +1440,93 @@ - atomic_inc(&init_mm.mm_count); - enter_lazy_tlb(&init_mm, current, cpu); - } -+ -+#if LOWLATENCY_NEEDED -+#if LOWLATENCY_DEBUG -+ -+static struct lolat_stats_t *lolat_stats_head; -+static spinlock_t lolat_stats_lock = SPIN_LOCK_UNLOCKED; -+ -+void set_running_and_schedule(struct lolat_stats_t *stats) -+{ -+ spin_lock(&lolat_stats_lock); -+ if (stats->visited == 0) { -+ stats->visited = 1; -+ stats->next = lolat_stats_head; -+ lolat_stats_head = stats; -+ } -+ stats->count++; -+ spin_unlock(&lolat_stats_lock); -+ -+ if (current->state != TASK_RUNNING) -+ set_current_state(TASK_RUNNING); -+ schedule(); -+} -+ -+void show_lolat_stats(void) -+{ -+ struct lolat_stats_t *stats = lolat_stats_head; -+ -+ printk("Low latency scheduling stats:\n"); -+ while (stats) { -+ printk("%s:%d: %lu\n", stats->file, stats->line, stats->count); -+ stats->count = 0; -+ stats = stats->next; -+ } -+} -+ -+#else /* LOWLATENCY_DEBUG */ -+ -+void set_running_and_schedule() -+{ -+ if (current->state != TASK_RUNNING) -+ __set_current_state(TASK_RUNNING); -+ schedule(); -+} -+ -+#endif /* LOWLATENCY_DEBUG */ -+ -+int ll_copy_to_user(void *to_user, const void *from, unsigned long len) -+{ -+ while (len) { -+ unsigned long n_to_copy = len; -+ unsigned long remainder; -+ -+ if (n_to_copy > 4096) -+ n_to_copy = 4096; -+ remainder = copy_to_user(to_user, from, n_to_copy); -+ if (remainder) -+ return remainder + len; -+ to_user = ((char *)to_user) + n_to_copy; -+ from = ((char *)from) + n_to_copy; -+ len -= n_to_copy; -+ conditional_schedule(); -+ } -+ return 0; -+} -+ -+int ll_copy_from_user(void *to, const void *from_user, unsigned long len) -+{ -+ while (len) { -+ unsigned long n_to_copy = len; -+ unsigned long remainder; -+ -+ if (n_to_copy > 4096) -+ n_to_copy = 4096; -+ remainder = copy_from_user(to, from_user, n_to_copy); -+ if (remainder) -+ return remainder + len; -+ to = ((char *)to) + n_to_copy; -+ from_user = ((char *)from_user) + n_to_copy; -+ len -= n_to_copy; -+ conditional_schedule(); -+ } -+ return 0; -+} -+ -+#ifdef CONFIG_LOLAT_SYSCTL -+struct low_latency_enable_struct __enable_lowlatency = { 0, }; -+#endif -+ -+#endif /* LOWLATENCY_NEEDED */ -+ -diff -Nur c3000_pre/linux/kernel/sysctl.c c3000_test/linux/kernel/sysctl.c ---- c3000_pre/linux/kernel/sysctl.c 2004-08-21 09:49:14.000000000 +0900 -+++ c3000_test/linux/kernel/sysctl.c 2004-12-20 22:56:21.000000000 +0900 -@@ -271,6 +271,10 @@ - {KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug", - &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec}, - #endif -+#ifdef CONFIG_LOLAT_SYSCTL -+ {KERN_LOWLATENCY, "lowlatency", &enable_lowlatency, sizeof (int), -+ 0644, NULL, &proc_dointvec}, -+#endif - {0} - }; - -diff -Nur c3000_pre/linux/mm/filemap.c c3000_test/linux/mm/filemap.c ---- c3000_pre/linux/mm/filemap.c 2004-08-21 09:49:15.000000000 +0900 -+++ c3000_test/linux/mm/filemap.c 2004-12-20 22:56:21.000000000 +0900 -@@ -179,7 +179,9 @@ - { - struct list_head *head, *curr; - struct page * page; -+ int ll_count = 100; - -+restart: - head = &inode->i_mapping->clean_pages; - - spin_lock(&pagemap_lru_lock); -@@ -190,6 +192,14 @@ - page = list_entry(curr, struct page, list); - curr = curr->next; - -+ if (conditional_schedule_needed() && ll_count) { -+ spin_unlock(&pagecache_lock); -+ spin_unlock(&pagemap_lru_lock); -+ unconditional_schedule(); -+ ll_count--; -+ goto restart; -+ } -+ - /* We cannot invalidate something in dirty.. */ - if (PageDirty(page)) - continue; -@@ -253,8 +263,7 @@ - page_cache_release(page); - } - --static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *)); --static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial) -+static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial, int *restart_count) - { - struct list_head *curr; - struct page * page; -@@ -265,6 +274,17 @@ - while (curr != head) { - unsigned long offset; - -+ if (conditional_schedule_needed() && *restart_count) { -+ (*restart_count)--; -+ list_del(head); -+ list_add(head, curr); /* Restart on this page */ -+ spin_unlock(&pagecache_lock); -+ unconditional_schedule(); -+ spin_lock(&pagecache_lock); -+ unlocked = 1; -+ goto restart; -+ } -+ - page = list_entry(curr, struct page, list); - offset = page->index; - -@@ -297,13 +317,11 @@ - } else - wait_on_page(page); - -- page_cache_release(page); -- -- if (current->need_resched) { -- __set_current_state(TASK_RUNNING); -- schedule(); -+ if (LOWLATENCY_NEEDED) { -+ *restart_count = 4; /* We made progress */ - } - -+ page_cache_release(page); - spin_lock(&pagecache_lock); - goto restart; - } -@@ -326,13 +344,14 @@ - { - unsigned long start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); -+ int restart_count = 4; - int unlocked; - - spin_lock(&pagecache_lock); - do { -- unlocked = truncate_list_pages(&mapping->clean_pages, start, &partial); -- unlocked |= truncate_list_pages(&mapping->dirty_pages, start, &partial); -- unlocked |= truncate_list_pages(&mapping->locked_pages, start, &partial); -+ unlocked = truncate_list_pages(&mapping->clean_pages, start, &partial, &restart_count); -+ unlocked |= truncate_list_pages(&mapping->dirty_pages, start, &partial, &restart_count); -+ unlocked |= truncate_list_pages(&mapping->locked_pages, start, &partial, &restart_count); - } while (unlocked); - /* Traversed all three lists without dropping the lock */ - spin_unlock(&pagecache_lock); -@@ -477,6 +496,7 @@ - - page_cache_get(page); - spin_unlock(&pagecache_lock); -+ conditional_schedule(); /* sys_msync() (only used by minixfs, udf) */ - lock_page(page); - - /* The buffers could have been free'd while we waited for the page lock */ -@@ -563,12 +583,14 @@ - list_del(&page->list); - list_add(&page->list, &mapping->locked_pages); - -- if (!PageDirty(page)) -- continue; -- - page_cache_get(page); - spin_unlock(&pagecache_lock); - -+ conditional_schedule(); /* sys_msync() */ -+ -+ if (!PageDirty(page)) -+ goto clean; -+ - lock_page(page); - - if (PageDirty(page)) { -@@ -579,7 +601,7 @@ - ret = err; - } else - UnlockPage(page); -- -+clean: - page_cache_release(page); - spin_lock(&pagecache_lock); - } -@@ -597,7 +619,8 @@ - int filemap_fdatawait(struct address_space * mapping) - { - int ret = 0; -- -+ DEFINE_RESCHED_COUNT; -+restart: - spin_lock(&pagecache_lock); - - while (!list_empty(&mapping->locked_pages)) { -@@ -606,6 +629,17 @@ - list_del(&page->list); - list_add(&page->list, &mapping->clean_pages); - -+ if (TEST_RESCHED_COUNT(32)) { -+ RESET_RESCHED_COUNT(); -+ if (conditional_schedule_needed()) { -+ page_cache_get(page); -+ spin_unlock(&pagecache_lock); -+ unconditional_schedule(); -+ page_cache_release(page); -+ goto restart; -+ } -+ } -+ - if (!PageLocked(page)) - continue; - -@@ -706,8 +740,10 @@ - spin_lock(&pagecache_lock); - page = __find_page_nolock(mapping, offset, *hash); - spin_unlock(&pagecache_lock); -- if (page) -+ if (page) { -+ conditional_schedule(); - return 0; -+ } - - page = page_cache_alloc(mapping); - if (!page) -@@ -963,6 +999,11 @@ - * the hash-list needs a held write-lock. - */ - repeat: -+ if (conditional_schedule_needed()) { -+ spin_unlock(&pagecache_lock); -+ unconditional_schedule(); -+ spin_lock(&pagecache_lock); -+ } - page = __find_page_nolock(mapping, offset, hash); - if (page) { - page_cache_get(page); -@@ -1413,6 +1454,8 @@ - page_cache_get(page); - spin_unlock(&pagecache_lock); - -+ conditional_schedule(); /* sys_read() */ -+ - if (!Page_Uptodate(page)) - goto page_not_up_to_date; - generic_file_readahead(reada_ok, filp, inode, page); -@@ -2114,6 +2157,12 @@ - address += PAGE_SIZE; - pte++; - } while (address && (address < end)); -+ -+ if (conditional_schedule_needed()) { -+ spin_unlock(&vma->vm_mm->page_table_lock); -+ unconditional_schedule(); /* syncing large mapped files */ -+ spin_lock(&vma->vm_mm->page_table_lock); -+ } - return error; - } - -@@ -2530,7 +2579,9 @@ - if (vma->vm_flags & VM_LOCKED) - return -EINVAL; - -- zap_page_range(vma->vm_mm, start, end - start); -+ zap_page_range(vma->vm_mm, start, end - start, -+ ZPR_COND_RESCHED); /* sys_madvise(MADV_DONTNEED) */ -+ - return 0; - } - -@@ -3095,6 +3146,9 @@ - goto sync_failure; - page_fault = __copy_from_user(kaddr+offset, buf, bytes); - flush_dcache_page(page); -+ -+ conditional_schedule(); -+ - status = mapping->a_ops->commit_write(file, page, offset, offset+bytes); - if (page_fault) - goto fail_write; -diff -Nur c3000_pre/linux/mm/memory.c c3000_test/linux/mm/memory.c ---- c3000_pre/linux/mm/memory.c 2004-08-21 09:49:15.000000000 +0900 -+++ c3000_test/linux/mm/memory.c 2004-12-20 22:56:21.000000000 +0900 -@@ -370,7 +370,7 @@ - /* - * remove user pages in a given range. - */ --void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size) -+static void do_zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size) - { - mmu_gather_t *tlb; - pgd_t * dir; -@@ -494,6 +494,10 @@ - struct page *map; - while (!(map = follow_page(mm, start, write))) { - spin_unlock(&mm->page_table_lock); -+ -+ /* Pinning down many physical pages (kiobufs, mlockall) */ -+ conditional_schedule(); -+ - switch (handle_mm_fault(mm, vma, start, write)) { - case 1: - tsk->min_flt++; -@@ -655,6 +659,21 @@ - iobuf->locked = 0; - } - -+#define MAX_ZAP_BYTES 256*PAGE_SIZE -+ -+void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size, int actions) -+{ -+ while (size) { -+ unsigned long chunk = size; -+ if (actions & ZPR_COND_RESCHED && chunk > MAX_ZAP_BYTES) -+ chunk = MAX_ZAP_BYTES; -+ do_zap_page_range(mm, address, chunk); -+ if (actions & ZPR_COND_RESCHED) -+ conditional_schedule(); -+ address += chunk; -+ size -= chunk; -+ } -+} - - /* - * Lock down all of the pages of a kiovec for IO. -@@ -764,11 +783,18 @@ - return 0; - } - --static inline void zeromap_pte_range(pte_t * pte, unsigned long address, -- unsigned long size, pgprot_t prot) -+static inline void zeromap_pte_range(struct mm_struct *mm, pte_t * pte, -+ unsigned long address, unsigned long size, -+ pgprot_t prot) - { - unsigned long end; - -+ if (conditional_schedule_needed()) { -+ spin_unlock(&mm->page_table_lock); -+ unconditional_schedule(); /* mmap(/dev/zero) */ -+ spin_lock(&mm->page_table_lock); -+ } -+ - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) -@@ -796,7 +822,7 @@ - pte_t * pte = pte_alloc(mm, pmd, address); - if (!pte) - return -ENOMEM; -- zeromap_pte_range(pte, address, end - address, prot); -+ zeromap_pte_range(mm, pte, address, end - address, prot); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); -@@ -1044,7 +1070,7 @@ - - /* mapping wholly truncated? */ - if (mpnt->vm_pgoff >= pgoff) { -- zap_page_range(mm, start, len); -+ zap_page_range(mm, start, len, 0); - continue; - } - -@@ -1057,7 +1083,7 @@ - /* Ok, partially affected.. */ - start += diff << PAGE_SHIFT; - len = (len - diff) << PAGE_SHIFT; -- zap_page_range(mm, start, len); -+ zap_page_range(mm, start, len, 0); - } while ((mpnt = mpnt->vm_next_share) != NULL); - } - -diff -Nur c3000_pre/linux/mm/mmap.c c3000_test/linux/mm/mmap.c ---- c3000_pre/linux/mm/mmap.c 2004-12-16 22:55:54.000000000 +0900 -+++ c3000_test/linux/mm/mmap.c 2004-12-20 23:07:25.000000000 +0900 -@@ -598,7 +598,7 @@ - fput(file); - - /* Undo any partial mapping done by a device driver. */ -- zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start); -+ zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start, 0); - free_vma: - kmem_cache_free(vm_area_cachep, vma); - return error; -@@ -998,7 +998,7 @@ - remove_shared_vm_struct(mpnt); - mm->map_count--; - -- zap_page_range(mm, st, size); -+ zap_page_range(mm, st, size, ZPR_COND_RESCHED); /* sys_munmap() */ - - /* - * Fix the mapping, and free the old area if it wasn't reused. -@@ -1158,7 +1158,7 @@ - } - mm->map_count--; - remove_shared_vm_struct(mpnt); -- zap_page_range(mm, start, size); -+ zap_page_range(mm, start, size, ZPR_COND_RESCHED); /* sys_exit() */ - if (mpnt->vm_file) - fput(mpnt->vm_file); - kmem_cache_free(vm_area_cachep, mpnt); -diff -Nur c3000_pre/linux/mm/mremap.c c3000_test/linux/mm/mremap.c ---- c3000_pre/linux/mm/mremap.c 2004-12-16 22:55:54.000000000 +0900 -+++ c3000_test/linux/mm/mremap.c 2004-12-20 23:07:25.000000000 +0900 -@@ -121,7 +121,7 @@ - flush_cache_range(mm, new_addr, new_addr + len); - while ((offset += PAGE_SIZE) < len) - move_one_page(mm, new_addr + offset, old_addr + offset); -- zap_page_range(mm, new_addr, len); -+ zap_page_range(mm, new_addr, len, 0); - #ifdef __arm__ - memc_update_mm(mm); - #endif -diff -Nur c3000_pre/linux/mm/slab.c c3000_test/linux/mm/slab.c ---- c3000_pre/linux/mm/slab.c 2004-11-16 15:31:09.000000000 +0900 -+++ c3000_test/linux/mm/slab.c 2004-12-20 22:56:21.000000000 +0900 -@@ -940,6 +940,7 @@ - list_del(&slabp->list); - - spin_unlock_irq(&cachep->spinlock); -+ conditional_schedule(); - kmem_slab_destroy(cachep, slabp); - ret++; - spin_lock_irq(&cachep->spinlock); -@@ -1853,6 +1854,7 @@ - */ - spin_unlock_irq(&best_cachep->spinlock); - kmem_slab_destroy(best_cachep, slabp); -+ conditional_schedule(); /* try_to_free_pages() */ - spin_lock_irq(&best_cachep->spinlock); - } - spin_unlock_irq(&best_cachep->spinlock); -diff -Nur c3000_pre/linux/mm/swapfile.c c3000_test/linux/mm/swapfile.c ---- c3000_pre/linux/mm/swapfile.c 2004-08-21 09:49:16.000000000 +0900 -+++ c3000_test/linux/mm/swapfile.c 2004-12-20 22:56:21.000000000 +0900 -@@ -819,7 +819,7 @@ - len += sprintf(buf + len, "partition\t"); - - usedswap = 0; -- for (j = 0; j < ptr->max; ++j) -+ for (j = 0; j < ptr->max; ++j) { - switch (ptr->swap_map[j]) { - case SWAP_MAP_BAD: - case 0: -@@ -827,6 +827,8 @@ - default: - usedswap++; - } -+ conditional_schedule(); -+ } - len += sprintf(buf + len, "%d\t%d\t%d\n", ptr->pages << (PAGE_SHIFT - 10), - usedswap << (PAGE_SHIFT - 10), ptr->prio); - } -@@ -1120,6 +1122,11 @@ - if (swap_info[i].flags != SWP_USED) - continue; - for (j = 0; j < swap_info[i].max; ++j) { -+ if (conditional_schedule_needed()) { -+ swap_list_unlock(); -+ conditional_schedule(); -+ swap_list_lock(); -+ } - switch (swap_info[i].swap_map[j]) { - case 0: - case SWAP_MAP_BAD: -diff -Nur c3000_pre/linux/mm/vmscan.c c3000_test/linux/mm/vmscan.c ---- c3000_pre/linux/mm/vmscan.c 2004-08-21 09:49:16.000000000 +0900 -+++ c3000_test/linux/mm/vmscan.c 2004-12-20 22:56:21.000000000 +0900 -@@ -173,6 +173,7 @@ - { - pte_t * pte; - unsigned long pmd_end; -+ DEFINE_RESCHED_COUNT; - - if (pmd_none(*dir)) - return count; -@@ -198,11 +199,17 @@ - address += PAGE_SIZE; - break; - } -+ if (TEST_RESCHED_COUNT(4)) { -+ if (conditional_schedule_needed()) -+ goto out; -+ RESET_RESCHED_COUNT(); -+ } - } - } - address += PAGE_SIZE; - pte++; - } while (address && (address < end)); -+out: - mm->swap_address = address; - return count; - } -@@ -231,6 +238,8 @@ - count = swap_out_pmd(mm, vma, pmd, address, end, count, classzone); - if (!count) - break; -+ if (conditional_schedule_needed()) -+ return count; - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); -@@ -255,6 +264,8 @@ - count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone); - if (!count) - break; -+ if (conditional_schedule_needed()) -+ return count; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - pgdir++; - } while (address && (address < end)); -@@ -276,6 +287,7 @@ - * Find the proper vm-area after freezing the vma chain - * and ptes. - */ -+continue_scan: - spin_lock(&mm->page_table_lock); - address = mm->swap_address; - if (address == TASK_SIZE || swap_mm != mm) { -@@ -293,6 +305,12 @@ - vma = vma->vm_next; - if (!vma) - break; -+ if (conditional_schedule_needed()) { /* Scanning a large vma */ -+ spin_unlock(&mm->page_table_lock); -+ unconditional_schedule(); -+ /* Continue from where we left off */ -+ goto continue_scan; -+ } - if (!count) - goto out_unlock; - address = vma->vm_start; -diff -Nur c3000_pre/linux/net/core/iovec.c c3000_test/linux/net/core/iovec.c ---- c3000_pre/linux/net/core/iovec.c 2004-08-21 11:23:13.000000000 +0900 -+++ c3000_test/linux/net/core/iovec.c 2004-12-20 22:56:21.000000000 +0900 -@@ -88,7 +88,7 @@ - if(iov->iov_len) - { - int copy = min_t(unsigned int, iov->iov_len, len); -- if (copy_to_user(iov->iov_base, kdata, copy)) -+ if (ll_copy_to_user(iov->iov_base, kdata, copy)) - goto out; - kdata+=copy; - len-=copy; -diff -Nur c3000_pre/linux/net/ipv4/tcp_minisocks.c c3000_test/linux/net/ipv4/tcp_minisocks.c ---- c3000_pre/linux/net/ipv4/tcp_minisocks.c 2004-08-21 09:49:22.000000000 +0900 -+++ c3000_test/linux/net/ipv4/tcp_minisocks.c 2004-12-20 22:56:21.000000000 +0900 -@@ -440,6 +440,9 @@ - { - struct tcp_tw_bucket *tw; - int killed = 0; -+#if LOWLATENCY_NEEDED -+ int max_killed = 0; -+#endif - - /* NOTE: compare this to previous version where lock - * was released after detaching chain. It was racy, -@@ -453,6 +456,13 @@ - goto out; - - while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) { -+#if LOWLATENCY_NEEDED -+ /* This loop takes ~6 usecs per iteration. */ -+ if (killed > 100) { -+ max_killed = 1; -+ break; -+ } -+#endif - tcp_tw_death_row[tcp_tw_death_row_slot] = tw->next_death; - tw->pprev_death = NULL; - spin_unlock(&tw_death_lock); -@@ -463,12 +473,24 @@ - killed++; - - spin_lock(&tw_death_lock); -+ -+ } -+ -+#if LOWLATENCY_NEEDED -+ if (max_killed) { /* More to do: do it soon */ -+ mod_timer(&tcp_tw_timer, jiffies+2); -+ tcp_tw_count -= killed; -+ } -+ else -+#endif -+ { -+ tcp_tw_death_row_slot = -+ ((tcp_tw_death_row_slot + 1) & (TCP_TWKILL_SLOTS - 1)); -+ -+ if ((tcp_tw_count -= killed) != 0) -+ mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD); - } -- tcp_tw_death_row_slot = -- ((tcp_tw_death_row_slot + 1) & (TCP_TWKILL_SLOTS - 1)); - -- if ((tcp_tw_count -= killed) != 0) -- mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD); - net_statistics[smp_processor_id()*2].TimeWaited += killed; - out: - spin_unlock(&tw_death_lock); |