[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Allocating buffers in ext2fs
From: |
Neal H Walfield |
Subject: |
Allocating buffers in ext2fs |
Date: |
Sun, 18 Nov 2001 17:50:52 +0100 |
User-agent: |
Gnus/5.090004 (Oort Gnus v0.04) Emacs/21.1 |
I have the modified the allocation and deallocation scheme in the
ext2fs pager code to be a bit smarter. Now, when we need to allocate
a single page, we preallocate several more at the same time. This
code also reduces the lock contention by waiting until as late as
possible to take a lock.
I also included two small side fixes: two zero initializers were
removed and a comment was fixed.
ext2fs/ChangeLog:
2001-11-17 Neal H Walfield <neal@cs.uml.edu>
* pager.c (MIN_FREE_PAGE_BUFS): New macro. Minimum number of
page buffers to allocate at a time.
(get_page_bufs): free_page_bufs_lock does not need to held to
see if there are any free pages. Only if we think that there
are free pages do we need the lock to: first, confirm the
suspicion and then allocate a page.
In the case where there are no free pages (or we suspect that
there are none), allocate MIN_FREE_PAGE_BUFS and connect all
of the unused pages to the free_page_bufs list.
(free_page_buf): Only lock free_page_bufs_lock if a page is to
be connected to the free_page_bufs list.
(free_page_bufs): No need to zero initialize a global static.
(num_free_page_bufs): Likewise.
(find_block): Correct comment.
Index: pager.c
===================================================================
RCS file: /cvsroot/hurd/hurd/ext2fs/pager.c,v
retrieving revision 1.68
diff -u -p -r1.68 pager.c
--- pager.c 2001/01/07 17:03:55 1.68
+++ pager.c 2001/11/18 15:41:02
@@ -70,10 +70,11 @@ do { spin_lock (&ext2s_pager_stats.lock)
#endif /* STATS */
#define MAX_FREE_PAGE_BUFS 32
+#define MIN_FREE_PAGE_BUFS 4
static spin_lock_t free_page_bufs_lock = SPIN_LOCK_INITIALIZER;
-static void *free_page_bufs = 0;
-static int num_free_page_bufs = 0;
+static void *free_page_bufs;
+static int num_free_page_bufs;
/* Returns a single page page-aligned buffer. */
static void *
@@ -81,20 +82,41 @@ get_page_buf ()
{
void *buf;
- spin_lock (&free_page_bufs_lock);
-
buf = free_page_bufs;
- if (buf == 0)
+ if (buf)
{
- spin_unlock (&free_page_bufs_lock);
- buf = mmap (0, vm_page_size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- if (buf == (void *) -1)
- buf = 0;
+ spin_lock (&free_page_bufs_lock);
+ buf = free_page_bufs;
+ if (buf)
+ {
+ assert (num_free_page_bufs > 0);
+ free_page_bufs = *(void **)buf;
+ num_free_page_bufs--;
+ spin_unlock (&free_page_bufs_lock);
+ return buf;
+ }
+ else
+ spin_unlock (&free_page_bufs_lock);
}
+
+ buf = mmap (0, vm_page_size * MIN_FREE_PAGE_BUFS,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (buf == MAP_FAILED)
+ return 0;
else
{
- free_page_bufs = *(void **)buf;
- num_free_page_bufs--;
+ int i;
+ void *p;
+
+ for (i = 1, p = buf + vm_page_size;
+ i < MIN_FREE_PAGE_BUFS - 1;
+ i++, p += vm_page_size)
+ *(void **)p = p + vm_page_size;
+
+ spin_lock (&free_page_bufs_lock);
+ *(void **)p = free_page_bufs;
+ free_page_bufs = buf + vm_page_size;
+ num_free_page_bufs += MIN_FREE_PAGE_BUFS - 1;
spin_unlock (&free_page_bufs_lock);
}
@@ -105,26 +127,25 @@ get_page_buf ()
static void
free_page_buf (void *buf)
{
- spin_lock (&free_page_bufs_lock);
if (num_free_page_bufs < MAX_FREE_PAGE_BUFS)
+ /* This test is not locked, however, if we have an extra page in
+ the free list, it makes no real difference. */
{
+ spin_lock (&free_page_bufs_lock);
*(void **)buf = free_page_bufs;
free_page_bufs = buf;
num_free_page_bufs++;
spin_unlock (&free_page_bufs_lock);
}
else
- {
- spin_unlock (&free_page_bufs_lock);
- munmap (buf, vm_page_size);
- }
+ munmap (buf, vm_page_size);
}
/* Find the location on disk of page OFFSET in NODE. Return the disk block
- in BLOCK (if unallocated, then return 0). If *LOCK is 0, then it a reader
+ in BLOCK (if unallocated, then return 0). If *LOCK is 0, then a reader
lock is aquired on NODE's ALLOC_LOCK before doing anything, and left
- locked after return -- even if an error is returned. 0 on success or an
- error code otherwise is returned. */
+ locked after the return -- even if an error is returned. 0 is returned
+ on success otherwise an error code. */
static error_t
find_block (struct node *node, vm_offset_t offset,
block_t *block, struct rwlock **lock)
- Allocating buffers in ext2fs,
Neal H Walfield <=
- Re: Allocating buffers in ext2fs, Roland McGrath, 2001/11/18
- Re: Allocating buffers in ext2fs, Neal H Walfield, 2001/11/20
- Re: Allocating buffers in ext2fs, Neal H Walfield, 2001/11/21
- Re: Allocating buffers in ext2fs, Roland McGrath, 2001/11/22
- Re: Allocating buffers in ext2fs, Neal H Walfield, 2001/11/22
- Re: Allocating buffers in ext2fs, Roland McGrath, 2001/11/22
- Re: Allocating buffers in ext2fs, Roland McGrath, 2001/11/22
- Re: Allocating buffers in ext2fs, Neal H Walfield, 2001/11/24