summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fatfs/pager.c87
1 files changed, 62 insertions, 25 deletions
diff --git a/fatfs/pager.c b/fatfs/pager.c
index 6180aacf..f855ecfc 100644
--- a/fatfs/pager.c
+++ b/fatfs/pager.c
@@ -18,12 +18,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+#include <error.h>
#include <string.h>
#include <hurd/store.h>
#include "fatfs.h"
-/* A ports bucket to hold pager ports. */
-struct port_bucket *pager_bucket;
+/* A ports bucket to hold disk pager ports. */
+struct port_bucket *disk_pager_bucket;
+
+/* A ports bucket to hold file pager ports. */
+struct port_bucket *file_pager_bucket;
/* Mapped image of the FAT. */
void *fat_image;
@@ -752,16 +756,51 @@ pager_dropweak (struct user_pager_info *p __attribute__ ((unused)))
{
}
+/* A top-level function for the paging thread that just services paging
+ requests. */
+static void *
+service_paging_requests (void *arg)
+{
+ struct port_bucket *pager_bucket = arg;
+ ports_manage_port_operations_multithread (pager_bucket,
+ pager_demuxer,
+ 1000,
+ 0,
+ NULL);
+ /* Not reached. */
+ return NULL;
+}
+
/* Create the disk pager. */
void
create_fat_pager (void)
{
+ pthread_t thread;
+ pthread_attr_t attr;
+ error_t err;
+
+ /* The disk pager. */
struct user_pager_info *upi = malloc (sizeof (struct user_pager_info));
upi->type = FAT;
- pager_bucket = ports_create_bucket ();
- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0,
+ disk_pager_bucket = ports_create_bucket ();
+ diskfs_start_disk_pager (upi, disk_pager_bucket, MAY_CACHE, 0,
bytes_per_sector * sectors_per_fat,
&fat_image);
+
+ /* The file pager. */
+ file_pager_bucket = ports_create_bucket ();
+
+#define STACK_SIZE (64 * 1024)
+ pthread_attr_init (&attr);
+ pthread_attr_setstacksize (&attr, STACK_SIZE);
+#undef STACK_SIZE
+
+ /* Make a thread to service file paging requests. */
+ err = pthread_create (&thread, &attr,
+ service_paging_requests, file_pager_bucket);
+ if (err)
+ error (2, err, "pthread_create");
+ pthread_detach (thread);
}
/* Call this to create a FILE_DATA pager and return a send right.
@@ -800,7 +839,7 @@ diskfs_get_filemap (struct node *node, vm_prot_t prot)
upi->max_prot = prot;
diskfs_nref_light (node);
node->dn->pager =
- pager_create (upi, pager_bucket, MAY_CACHE,
+ pager_create (upi, file_pager_bucket, MAY_CACHE,
MEMORY_OBJECT_COPY_DELAY, 0);
if (node->dn->pager == 0)
{
@@ -881,14 +920,13 @@ diskfs_shutdown_pager ()
error_t shutdown_one (void *v_p)
{
struct pager *p = v_p;
- if (p != diskfs_disk_pager)
- pager_shutdown (p);
+ pager_shutdown (p);
return 0;
}
write_all_disknodes ();
- ports_bucket_iterate (pager_bucket, shutdown_one);
+ ports_bucket_iterate (file_pager_bucket, shutdown_one);
pager_sync (diskfs_disk_pager, 1);
@@ -903,13 +941,12 @@ diskfs_sync_everything (int wait)
error_t sync_one (void *v_p)
{
struct pager *p = v_p;
- if (p != diskfs_disk_pager)
- pager_sync (p, wait);
+ pager_sync (p, wait);
return 0;
}
write_all_disknodes ();
- ports_bucket_iterate (pager_bucket, sync_one);
+ ports_bucket_iterate (file_pager_bucket, sync_one);
pager_sync (diskfs_disk_pager, wait);
}
@@ -926,7 +963,8 @@ disable_caching ()
/* Loop through the pagers and turn off caching one by one,
synchronously. That should cause termination of each pager. */
- ports_bucket_iterate (pager_bucket, block_cache);
+ ports_bucket_iterate (disk_pager_bucket, block_cache);
+ ports_bucket_iterate (file_pager_bucket, block_cache);
}
static void
@@ -954,7 +992,8 @@ enable_caching ()
return 0;
}
- ports_bucket_iterate (pager_bucket, enable_cache);
+ ports_bucket_iterate (disk_pager_bucket, enable_cache);
+ ports_bucket_iterate (file_pager_bucket, enable_cache);
}
/* Tell diskfs if there are pagers exported, and if none, then
@@ -962,9 +1001,9 @@ enable_caching ()
int
diskfs_pager_users ()
{
- int npagers = ports_count_bucket (pager_bucket);
+ int npagers = ports_count_bucket (file_pager_bucket);
- if (npagers <= 1)
+ if (npagers == 0)
return 0;
if (MAY_CACHE)
@@ -975,8 +1014,8 @@ diskfs_pager_users ()
immediately. XXX */
sleep (1);
- npagers = ports_count_bucket (pager_bucket);
- if (npagers <= 1)
+ npagers = ports_count_bucket (file_pager_bucket);
+ if (npagers == 0)
return 0;
/* Darn, there are actual honest users. Turn caching back on,
@@ -984,7 +1023,7 @@ diskfs_pager_users ()
enable_caching ();
}
- ports_enable_bucket (pager_bucket);
+ ports_enable_bucket (file_pager_bucket);
return 1;
}
@@ -995,17 +1034,15 @@ vm_prot_t
diskfs_max_user_pager_prot ()
{
vm_prot_t max_prot = 0;
- int npagers = ports_count_bucket (pager_bucket);
+ int npagers = ports_count_bucket (file_pager_bucket);
- if (npagers > 1)
- /* More than just the disk pager. */
+ if (npagers > 0)
{
error_t add_pager_max_prot (void *v_p)
{
struct pager *p = v_p;
struct user_pager_info *upi = pager_get_upi (p);
- if (upi->type == FILE_DATA)
- max_prot |= upi->max_prot;
+ max_prot |= upi->max_prot;
/* Stop iterating if MAX_PROT is as filled as it is going to
get. */
return max_prot == (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
@@ -1017,12 +1054,12 @@ diskfs_max_user_pager_prot ()
immediately. XXX */
sleep (1);
- ports_bucket_iterate (pager_bucket, add_pager_max_prot);
+ ports_bucket_iterate (file_pager_bucket, add_pager_max_prot);
enable_caching ();
}
- ports_enable_bucket (pager_bucket);
+ ports_enable_bucket (file_pager_bucket);
return max_prot;
}