diff options
-rw-r--r-- | fatfs/pager.c | 87 |
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; } |