summaryrefslogtreecommitdiff
path: root/devio/devpager.c
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1995-07-08 23:26:54 +0000
committerMiles Bader <miles@gnu.org>1995-07-08 23:26:54 +0000
commitdbe8a4ba45fddb5086ed0393ed16656a390d5e1c (patch)
tree04e88f4449ee193173bb7bd7501b749b09b21f5c /devio/devpager.c
parenta064ef82e289f6ca6ba19b13f276fbd31524c899 (diff)
(dev_stop_paging): New function.
(pager_dropweak): New function. (pager_port_type): Deleted var. (pager_port_bucket, pager_port_class): New vars. (dev_get_memory_object): Moved here from dev.c. Also, call init_dev_pager if necessary. (service_paging_requests): New function. (init_dev_pager): New function.
Diffstat (limited to 'devio/devpager.c')
-rw-r--r--devio/devpager.c132
1 files changed, 127 insertions, 5 deletions
diff --git a/devio/devpager.c b/devio/devpager.c
index ab3da34a..9d6e4abb 100644
--- a/devio/devpager.c
+++ b/devio/devpager.c
@@ -24,15 +24,10 @@
#include <assert.h>
#include "dev.h"
-#include "ptypes.h"
/* ---------------------------------------------------------------- */
/* Pager library callbacks; see <hurd/pager.h> for more info. */
-/* This will be the type used in calls to allocate_port by the pager system.
- */
-int pager_port_type = PT_MEMOBJ;
-
/* For pager PAGER, read one page from offset PAGE. Set *BUF to be the
address of the page, and set *WRITE_LOCK if the page must be provided
read-only. The only permissable error returns are EIO, EDQUOT, and
@@ -150,3 +145,130 @@ void
pager_clear_user_data(struct user_pager_info *upi)
{
}
+
+/* ---------------------------------------------------------------- */
+
+/* A top-level function for the paging thread that just services paging
+ requests. */
+static void
+service_paging_requests (any_t arg)
+{
+ struct dev *dev = (struct dev *)arg;
+ for (;;)
+ ports_manage_port_operations_multithread (dev->pager_port_bucket,
+ pager_demuxer,
+ 1000 * 30, 1000 * 60 * 5,
+ 1, MACH_PORT_NULL);
+}
+
+/* Initialize paging for this device. */
+static void
+init_dev_paging (struct dev *dev)
+{
+ dev->pager_port_bucket = ports_create_bucket ();
+
+ /* Make a thread to service paging requests. */
+ cthread_detach (cthread_fork ((cthread_fn_t)service_paging_requests,
+ (any_t)dev));
+}
+
+void
+pager_dropweak (struct user_pager_info *upi __attribute__ ((unused)))
+{
+}
+
+/* ---------------------------------------------------------------- */
+
+/* Try to stop all paging activity on DEV, returning true if we were
+ successful. If NOSYNC is true, then we won't write back any (kernel)
+ cached pages to the device. */
+int
+dev_stop_paging (struct dev *dev, int nosync)
+{
+ int success = 1; /* Initially assume success. */
+
+ io_state_lock(&dev->io_state);
+
+ if (dev->pager != NULL)
+ {
+ int num_pagers = ports_count_bucket (dev->pager_port_bucket);
+ if (num_pagers > 0 && !nosync)
+ {
+ error_t block_cache (void *arg)
+ {
+ struct pager *p = arg;
+ pager_change_attributes (p, 0, MEMORY_OBJECT_COPY_DELAY, 1);
+ return 0;
+ }
+ error_t enable_cache (void *arg)
+ {
+ struct pager *p = arg;
+ pager_change_attributes (p, 1, MEMORY_OBJECT_COPY_DELAY, 0);
+ return 0;
+ }
+
+ /* Loop through the pagers and turn off caching one by one,
+ synchronously. That should cause termination of each pager. */
+ ports_bucket_iterate (dev->pager_port_bucket, block_cache);
+
+ /* Give it a second; the kernel doesn't actually shutdown
+ immediately. XXX */
+ sleep (1);
+
+ num_pagers = ports_count_bucket (dev->pager_port_bucket);
+ if (num_pagers > 0)
+ /* Darn, there are actual honest users. Turn caching back on,
+ and return failure. */
+ {
+ ports_bucket_iterate (dev->pager_port_bucket, enable_cache);
+ success = 0;
+ }
+ }
+
+ if (success && !nosync)
+ /* shutdown the pager on DEV. If NOSYNC is set, we don't bother, for
+ fear that this may result in I/O. In this case we've disabled
+ rpcs on the pager's ports, so this will result in hanging... What
+ do we do??? XXXX */
+ pager_shutdown (dev->pager);
+ }
+
+ if (success)
+ dev->pager = NULL;
+
+ io_state_lock(&dev->io_state);
+
+ return success;
+}
+
+/* ---------------------------------------------------------------- */
+
+/* Returns in MEMOBJ the port for a memory object backed by the storage on
+ DEV. Returns 0 or the error code if an error occurred. */
+error_t
+dev_get_memory_object(struct dev *dev, memory_object_t *memobj)
+{
+ if (dev_is(dev, DEV_SERIAL))
+ return ENODEV;
+
+ io_state_lock(&dev->io_state);
+ if (dev->pager_port_bucket == NULL)
+ init_dev_paging (dev);
+ if (dev->pager == NULL)
+ dev->pager =
+ pager_create((struct user_pager_info *)dev, dev->pager_port_bucket,
+ 1, MEMORY_OBJECT_COPY_DELAY);
+ io_state_unlock(&dev->io_state);
+
+ if (dev->pager == NULL)
+ return ENODEV; /* XXX ??? */
+
+ *memobj = pager_get_port(dev->pager);
+ if (*memobj != MACH_PORT_NULL)
+ return
+ mach_port_insert_right(mach_task_self(),
+ *memobj, *memobj,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ return 0;
+}