diff options
-rw-r--r-- | console/pager.c | 29 | ||||
-rw-r--r-- | ext2fs/pager.c | 28 | ||||
-rw-r--r-- | fatfs/pager.c | 28 | ||||
-rw-r--r-- | libdiskfs/disk-pager.c | 28 | ||||
-rw-r--r-- | libpager/Makefile | 2 | ||||
-rw-r--r-- | libpager/chg-compl.c | 4 | ||||
-rw-r--r-- | libpager/data-request.c | 3 | ||||
-rw-r--r-- | libpager/data-return.c | 4 | ||||
-rw-r--r-- | libpager/data-unlock.c | 5 | ||||
-rw-r--r-- | libpager/demuxer.c | 287 | ||||
-rw-r--r-- | libpager/lock-completed.c | 2 | ||||
-rw-r--r-- | libpager/no-senders.c | 1 | ||||
-rw-r--r-- | libpager/notify-stubs.c | 10 | ||||
-rw-r--r-- | libpager/object-init.c | 2 | ||||
-rw-r--r-- | libpager/object-terminate.c | 4 | ||||
-rw-r--r-- | libpager/pager.h | 7 | ||||
-rw-r--r-- | libpager/priv.h | 4 | ||||
-rw-r--r-- | libpager/queue.h | 61 | ||||
-rw-r--r-- | libpager/seqnos.c | 79 | ||||
-rw-r--r-- | libpager/stubs.c | 9 | ||||
-rw-r--r-- | storeio/pager.c | 26 |
21 files changed, 361 insertions, 262 deletions
diff --git a/console/pager.c b/console/pager.c index 87c36f07..3568211e 100644 --- a/console/pager.c +++ b/console/pager.c @@ -119,22 +119,6 @@ void pager_dropweak (struct user_pager_info *upi) { } - - -/* 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; - for (;;) - ports_manage_port_operations_multithread (pager_bucket, - pager_demuxer, - 1000 * 60 * 2, - 1000 * 60 * 10, 0); - return NULL; -} - /* Initialize the pager for the display component. */ void @@ -148,15 +132,10 @@ user_pager_init (void) if (! pager_bucket) error (5, errno, "Cannot create pager bucket"); - /* Make a thread to service paging requests. */ - err = pthread_create (&thread, NULL, service_paging_requests, pager_bucket); - if (!err) - pthread_detach (thread); - else - { - errno = err; - perror ("pthread_create"); - } + /* Start libpagers worker threads. */ + err = pager_start_workers (pager_bucket); + if (err) + error (5, err, "Cannot start pager worker threads"); } diff --git a/ext2fs/pager.c b/ext2fs/pager.c index 39cf1c73..298dae7a 100644 --- a/ext2fs/pager.c +++ b/ext2fs/pager.c @@ -1192,21 +1192,6 @@ disk_cache_block_is_ref (block_t block) return ref; } -/* 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, and the file pager. */ void create_disk_pager (void) @@ -1231,17 +1216,10 @@ create_disk_pager (void) /* 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); + /* Start libpagers worker threads. */ + err = pager_start_workers (file_pager_bucket); if (err) - error (2, err, "pthread_create"); - pthread_detach (thread); + ext2_panic ("can't create libpager worker threads: %s", strerror (err)); } /* Call this to create a FILE_DATA pager and return a send right. diff --git a/fatfs/pager.c b/fatfs/pager.c index f855ecfc..0c590841 100644 --- a/fatfs/pager.c +++ b/fatfs/pager.c @@ -756,21 +756,6 @@ 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) @@ -790,17 +775,10 @@ create_fat_pager (void) /* 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); + /* Start libpagers worker threads. */ + err = pager_start_workers (file_pager_bucket); if (err) - error (2, err, "pthread_create"); - pthread_detach (thread); + error (2, err, "can't create libpager worker threads"); } /* Call this to create a FILE_DATA pager and return a send right. diff --git a/libdiskfs/disk-pager.c b/libdiskfs/disk-pager.c index 9a0d9d88..4083ef27 100644 --- a/libdiskfs/disk-pager.c +++ b/libdiskfs/disk-pager.c @@ -33,39 +33,19 @@ static struct hurd_signal_preemptor preemptor = handler: (sighandler_t) &fault_handler, }; -/* 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; - for (;;) - ports_manage_port_operations_multithread (pager_bucket, - pager_demuxer, - 1000 * 60 * 2, - 1000 * 60 * 10, 0); - return NULL; -} - void diskfs_start_disk_pager (struct user_pager_info *upi, struct port_bucket *pager_bucket, int may_cache, int notify_on_evict, size_t size, void **image) { - pthread_t thread; error_t err; mach_port_t disk_pager_port; - /* Make a thread to service paging requests. */ - err = pthread_create (&thread, NULL, service_paging_requests, pager_bucket); - if (!err) - pthread_detach (thread); - else - { - errno = err; - perror ("pthread_create"); - } + /* Start libpagers worker threads. */ + err = pager_start_workers (pager_bucket); + if (err) + error (2, err, "creating pager worker threads failed"); /* Create the pager. */ diskfs_disk_pager = pager_create (upi, pager_bucket, diff --git a/libpager/Makefile b/libpager/Makefile index b6222950..a15a899b 100644 --- a/libpager/Makefile +++ b/libpager/Makefile @@ -22,7 +22,7 @@ SRCS = data-request.c data-return.c data-unlock.c pager-port.c \ inhibit-term.c lock-completed.c lock-object.c mark-error.c \ no-senders.c object-init.c object-terminate.c pagemap.c \ pager-create.c pager-flush.c pager-shutdown.c pager-sync.c \ - stubs.c seqnos.c demuxer.c chg-compl.c pager-attr.c clean.c \ + stubs.c demuxer.c chg-compl.c pager-attr.c clean.c \ dropweak.c notify-stubs.c get-upi.c pager-memcpy.c pager-return.c \ offer-page.c installhdrs = pager.h diff --git a/libpager/chg-compl.c b/libpager/chg-compl.c index d77c46cf..89ccfc8b 100644 --- a/libpager/chg-compl.c +++ b/libpager/chg-compl.c @@ -37,7 +37,6 @@ _pager_seqnos_memory_object_change_completed (struct pager *p, } pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seq); for (ar = p->attribute_requests; ar; ar = ar->next) if (ar->may_cache == maycache && ar->copy_strategy == strat) @@ -46,8 +45,7 @@ _pager_seqnos_memory_object_change_completed (struct pager *p, pthread_cond_broadcast (&p->wakeup); break; } - - _pager_release_seqno (p, seq); + pthread_mutex_unlock (&p->interlock); return 0; } diff --git a/libpager/data-request.c b/libpager/data-request.c index 82ce9041..18f3de66 100644 --- a/libpager/data-request.c +++ b/libpager/data-request.c @@ -41,7 +41,6 @@ _pager_seqnos_memory_object_data_request (struct pager *p, /* Acquire the right to meddle with the pagemap */ pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); /* sanity checks -- we don't do multi-page requests yet. */ if (control != p->memobjcntl) @@ -105,7 +104,6 @@ _pager_seqnos_memory_object_data_request (struct pager *p, } /* Let someone else in. */ - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); if (!doread) @@ -139,7 +137,6 @@ _pager_seqnos_memory_object_data_request (struct pager *p, allow_release_out: _pager_allow_termination (p); release_out: - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); return 0; } diff --git a/libpager/data-return.c b/libpager/data-return.c index ee6c6e83..f16f3238 100644 --- a/libpager/data-return.c +++ b/libpager/data-return.c @@ -52,7 +52,6 @@ _pager_do_write_request (struct pager *p, /* Acquire the right to meddle with the pagemap */ pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); /* sanity checks -- we don't do multi-page requests yet. */ if (control != p->memobjcntl) @@ -101,7 +100,6 @@ _pager_do_write_request (struct pager *p, notified[i] = (p->notify_on_evict && ! (pm_entries[i] & PM_PAGEINWAIT)); - _pager_release_seqno (p, seqno); goto notify; } else { @@ -158,7 +156,6 @@ _pager_do_write_request (struct pager *p, } /* Let someone else in. */ - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); /* This is inefficient; we should send all the pages to the device at once @@ -251,7 +248,6 @@ _pager_do_write_request (struct pager *p, return 0; release_out: - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); return 0; } diff --git a/libpager/data-unlock.c b/libpager/data-unlock.c index 599237c1..8c7c776d 100644 --- a/libpager/data-unlock.c +++ b/libpager/data-unlock.c @@ -35,11 +35,6 @@ _pager_seqnos_memory_object_data_unlock (struct pager *p, || p->port.class != _pager_class) return EOPNOTSUPP; - pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); - _pager_release_seqno (p, seqno); - pthread_mutex_unlock (&p->interlock); - if (p->pager_state != NORMAL) { printf ("pager in wrong state for unlock\n"); diff --git a/libpager/demuxer.c b/libpager/demuxer.c index b4d40541..efdf2853 100644 --- a/libpager/demuxer.c +++ b/libpager/demuxer.c @@ -1,5 +1,5 @@ /* Demuxer for pager library - Copyright (C) 1994, 1995, 2002, 2011 Free Software Foundation + Copyright (C) 1993-2014 Free Software Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -15,26 +15,291 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <error.h> +#include <mach/mig_errors.h> +#include <pthread.h> +#include <string.h> + #include "priv.h" #include "memory_object_S.h" #include "notify_S.h" +#include "queue.h" + +/* + Worker pool for the server functions. + + A single thread receives messages from the port bucket and puts them + into a queue. A fixed number of consumers actually execute the + server functions and send the reply. + + The requests to an object O have to be processed in the order they + were received. To this end, each worker has a local queue and a + tag. If a thread processes a request to O, it sets its tag to a + unique identifier representing O. If another thread now dequeues a + second request to O, it enqueues it to the first workers queue. + + At least one worker thread is necessary. +*/ +#define WORKER_COUNT 1 + +/* An request contains the message received from the port set. */ +struct request +{ + struct item item; + mig_routine_t routine; + mach_msg_header_t *inp; + mach_msg_header_t *outp; +}; + +/* A worker. */ +struct worker +{ + struct requests *requests; /* our pagers request queue */ + struct queue queue; /* other workers may delegate requests to us */ + unsigned long tag; /* tag of the object we are working on */ +}; + +/* This is the queue for incoming requests. A single thread receives + messages from the port set, looks the service routine up, and + enqueues the request here. */ +struct requests +{ + struct port_bucket *bucket; + struct queue queue; + int asleep; + pthread_cond_t wakeup; + pthread_mutex_t lock; + struct worker workers[WORKER_COUNT]; +}; /* Demultiplex a single message directed at a pager port; INP is the message received; fill OUTP with the reply. */ -int -pager_demuxer (mach_msg_header_t *inp, +static int +pager_demuxer (struct requests *requests, + mach_msg_header_t *inp, mach_msg_header_t *outp) { + error_t err = MIG_NO_REPLY; + + /* The maximum size of the reply is 2048 bytes. See the MIG source + for details. */ + const mach_msg_size_t max_size = 2048; + mig_routine_t routine; - if ((routine = _pager_seqnos_memory_object_server_routine (inp)) || - (routine = _pager_seqnos_notify_server_routine (inp))) + if (! ((routine = _pager_seqnos_memory_object_server_routine (inp)) || + (routine = _pager_seqnos_notify_server_routine (inp)))) + return FALSE; + +#define MASK (8u - 1u) + mach_msg_size_t padded_size = (inp->msgh_size + MASK) & ~MASK; +#undef MASK + + struct request *r = malloc (sizeof *r + padded_size + max_size); + if (r == NULL) + { + err = ENOMEM; + goto out; + } + + r->routine = routine; + r->inp = (mach_msg_header_t *) ((char *) r + sizeof *r); + memcpy (r->inp, inp, inp->msgh_size); + + r->outp = (mach_msg_header_t *) ((char *) r + sizeof *r + padded_size); + memcpy (r->outp, outp, sizeof *outp); + + pthread_mutex_lock (&requests->lock); + + queue_enqueue (&requests->queue, &r->item); + + /* Awake worker. */ + if (requests->asleep > 0) + pthread_cond_signal (&requests->wakeup); + + pthread_mutex_unlock (&requests->lock); + + /* A worker thread will reply. */ + err = MIG_NO_REPLY; + + out: + ((mig_reply_header_t *) outp)->RetCode = err; + return TRUE; +} + +/* Consumes requests from the queue. */ +static void * +worker_func (void *arg) +{ + struct worker *self = (struct worker *) arg; + struct requests *requests = self->requests; + struct request *r = NULL; + + while (1) + { + int i; + mach_msg_return_t mr; + + /* Free previous message. */ + free (r); + + pthread_mutex_lock (&requests->lock); + + /* First, look in our queue for more requests to the object we + have been working on lately. Some other thread might have + delegated them to us. */ + r = queue_dequeue (&self->queue); + if (r != NULL) + goto got_one; + + /* Nope. Clear our tag and... */ + self->tag = 0; + + get_request_locked: + /* ... get a request from the global queue instead. */ + while ((r = queue_dequeue (&requests->queue)) == NULL) + { + requests->asleep += 1; + pthread_cond_wait (&requests->wakeup, &requests->lock); + requests->asleep -= 1; + } + + for (i = 0; i < WORKER_COUNT; i++) + if (requests->workers[i].tag + == (unsigned long) r->inp->msgh_local_port) + { + /* Some other thread is working on that object. Delegate + the request to that worker. */ + queue_enqueue (&requests->workers[i].queue, &r->item); + goto get_request_locked; + } + + /* Claim responsibility for this object by setting our tag. */ + self->tag = (unsigned long) r->inp->msgh_local_port; + + got_one: + pthread_mutex_unlock (&requests->lock); + + /* Call the server routine. */ + (*r->routine) (r->inp, r->outp); + + /* What follows is basically the second part of + mach_msg_server_timeout. */ + mig_reply_header_t *request = (mig_reply_header_t *) r->inp; + mig_reply_header_t *reply = (mig_reply_header_t *) r->outp; + + switch (reply->RetCode) + { + case KERN_SUCCESS: + /* Hunky dory. */ + break; + + case MIG_NO_REPLY: + /* The server function wanted no reply sent. + Loop for another request. */ + continue; + + default: + /* Some error; destroy the request message to release any + port rights or VM it holds. Don't destroy the reply port + right, so we can send an error message. */ + request->Head.msgh_remote_port = MACH_PORT_NULL; + mach_msg_destroy (&request->Head); + break; + } + + if (reply->Head.msgh_remote_port == MACH_PORT_NULL) + { + /* No reply port, so destroy the reply. */ + if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) + mach_msg_destroy (&reply->Head); + continue; + } + + /* Send the reply. */ + mr = mach_msg (&reply->Head, + MACH_SEND_MSG, + reply->Head.msgh_size, + 0, + MACH_PORT_NULL, + 0, + MACH_PORT_NULL); + + switch (mr) + { + case MACH_SEND_INVALID_DEST: + /* The reply can't be delivered, so destroy it. This error + indicates only that the requester went away, so we + continue and get the next request. */ + mach_msg_destroy (&reply->Head); + break; + + default: + /* Some other form of lossage; there is not much we can + do here. */ + error (0, mr, "mach_msg"); + } + } + + /* Not reached. */ + return NULL; +} + +/* A top-level function for the paging thread that just services paging + requests. */ +static void * +service_paging_requests (void *arg) +{ + struct requests *requests = arg; + + int demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outp) + { + return pager_demuxer (requests, inp, outp); + } + + ports_manage_port_operations_one_thread (requests->bucket, + demuxer, + 0); + /* Not reached. */ + return NULL; +} + +/* Start the worker threads libpager uses to service requests. */ +error_t +pager_start_workers (struct port_bucket *pager_bucket) +{ + error_t err; + int i; + pthread_t t; + struct requests *requests; + + requests = malloc (sizeof *requests); + if (requests == NULL) + return ENOMEM; + + requests->bucket = pager_bucket; + requests->asleep = 0; + queue_init (&requests->queue); + pthread_cond_init (&requests->wakeup, NULL); + pthread_mutex_init (&requests->lock, NULL); + + /* Make a thread to service paging requests. */ + err = pthread_create (&t, NULL, service_paging_requests, requests); + if (err) + return err; + pthread_detach (t); + + for (i = 0; i < WORKER_COUNT; i++) { - (*routine) (inp, outp); - return TRUE; + requests->workers[i].requests = requests; + requests->workers[i].tag = 0; + queue_init (&requests->workers[i].queue); + + err = pthread_create (&t, NULL, &worker_func, &requests->workers[i]); + if (err) + return err; + pthread_detach (t); } - /* Synchronize our bookkeeping of the port's seqno with the one - consumed by this bogus message. */ - _pager_update_seqno (inp->msgh_local_port, inp->msgh_seqno); - return FALSE; + return err; } diff --git a/libpager/lock-completed.c b/libpager/lock-completed.c index a3f3f168..30b1dd3d 100644 --- a/libpager/lock-completed.c +++ b/libpager/lock-completed.c @@ -37,7 +37,6 @@ _pager_seqnos_memory_object_lock_completed (struct pager *p, return EOPNOTSUPP; pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); if (control != p->memobjcntl) { @@ -59,7 +58,6 @@ _pager_seqnos_memory_object_lock_completed (struct pager *p, } out: - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); return err; diff --git a/libpager/no-senders.c b/libpager/no-senders.c index c21dfc2f..d0bbe27b 100644 --- a/libpager/no-senders.c +++ b/libpager/no-senders.c @@ -29,7 +29,6 @@ _pager_do_seqnos_mach_notify_no_senders (struct port_info *pi, pi->class != _pager_class) return EOPNOTSUPP; - _pager_update_seqno_p ((struct pager *) pi, seqno); ports_no_senders (pi, mscount); return 0; diff --git a/libpager/notify-stubs.c b/libpager/notify-stubs.c index ba138824..a8264203 100644 --- a/libpager/notify-stubs.c +++ b/libpager/notify-stubs.c @@ -28,8 +28,6 @@ _pager_do_seqnos_mach_notify_port_deleted (struct port_info *pi, mach_port_t name __attribute__ ((unused))) { - _pager_update_seqno_p ((struct pager *) pi, seqno); - return 0; } @@ -39,8 +37,6 @@ _pager_do_seqnos_mach_notify_msg_accepted (struct port_info *pi, mach_port_t name __attribute__ ((unused))) { - _pager_update_seqno_p ((struct pager *) pi, seqno); - return 0; } @@ -50,8 +46,6 @@ _pager_do_seqnos_mach_notify_port_destroyed (struct port_info *pi, mach_port_t name __attribute__ ((unused))) { - _pager_update_seqno_p ((struct pager *) pi, seqno); - return 0; } @@ -59,8 +53,6 @@ error_t _pager_do_seqnos_mach_notify_send_once (struct port_info *pi, mach_port_seqno_t seqno) { - _pager_update_seqno_p ((struct pager *) pi, seqno); - return 0; } @@ -70,7 +62,5 @@ _pager_do_seqnos_mach_notify_dead_name (struct port_info *pi, mach_port_t name __attribute__ ((unused))) { - _pager_update_seqno_p ((struct pager *) pi, seqno); - return 0; } diff --git a/libpager/object-init.c b/libpager/object-init.c index 6683e24d..eb62c443 100644 --- a/libpager/object-init.c +++ b/libpager/object-init.c @@ -33,7 +33,6 @@ _pager_seqnos_memory_object_init (struct pager *p, return EOPNOTSUPP; pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); if (pagesize != __vm_page_size) { @@ -69,7 +68,6 @@ _pager_seqnos_memory_object_init (struct pager *p, p->pager_state = NORMAL; out: - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); return 0; diff --git a/libpager/object-terminate.c b/libpager/object-terminate.c index 332bcab8..e8c6f381 100644 --- a/libpager/object-terminate.c +++ b/libpager/object-terminate.c @@ -32,8 +32,7 @@ _pager_seqnos_memory_object_terminate (struct pager *p, return EOPNOTSUPP; pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); - + if (control != p->memobjcntl) { printf ("incg terminate: wrong control port\n"); @@ -75,7 +74,6 @@ _pager_seqnos_memory_object_terminate (struct pager *p, #endif out: - _pager_release_seqno (p, seqno); pthread_mutex_unlock (&p->interlock); return 0; diff --git a/libpager/pager.h b/libpager/pager.h index d0572af1..29ec833a 100644 --- a/libpager/pager.h +++ b/libpager/pager.h @@ -25,11 +25,8 @@ scope. */ struct user_pager_info; -/* This de-muxer function is for use within libports_demuxer. */ -/* INP is a message we've received; OUTP will be filled in with - a reply message. */ -int pager_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp); +/* Start the worker threads libpager uses to service requests. */ +error_t pager_start_workers (struct port_bucket *pager_bucket); /* Create a new pager. The pager will have a port created for it (using libports, in BUCKET) and will be immediately ready diff --git a/libpager/priv.h b/libpager/priv.h index 1f8405af..4576e127 100644 --- a/libpager/priv.h +++ b/libpager/priv.h @@ -134,10 +134,6 @@ extern int _pager_page_errors[]; struct port_class *_pager_class; -void _pager_wait_for_seqno (struct pager *, mach_port_seqno_t); -void _pager_release_seqno (struct pager *, mach_port_seqno_t); -void _pager_update_seqno (mach_port_t, mach_port_seqno_t); -void _pager_update_seqno_p (struct pager *, mach_port_seqno_t); void _pager_block_termination (struct pager *); void _pager_allow_termination (struct pager *); error_t _pager_pagemap_resize (struct pager *, vm_address_t); diff --git a/libpager/queue.h b/libpager/queue.h new file mode 100644 index 00000000..d3cf738e --- /dev/null +++ b/libpager/queue.h @@ -0,0 +1,61 @@ +/* A FIFO queue with constant-time enqueue and dequeue operations. + + Copyright (C) 2014 Free Software Foundation, Inc. + + Written by Justus Winter <4winter@informatik.uni-hamburg.de> + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ + +/* A FIFO queue with constant-time enqueue and dequeue operations. */ +struct item { + struct item *next; +}; + +struct queue { + struct item *head; + struct item **tail; +}; + +static inline void +queue_init (struct queue *q) +{ + q->head = NULL; + q->tail = &q->head; +} + +static inline void +queue_enqueue (struct queue *q, struct item *r) +{ + *q->tail = r; + q->tail = &r->next; + r->next = NULL; +} + +static inline void * +queue_dequeue (struct queue *q) +{ + struct item *r = q->head; + if (r == NULL) + return NULL; + + /* Pop the first item off. */ + if ((q->head = q->head->next) == NULL) + /* The queue is empty, fix tail pointer. */ + q->tail = &q->head; + + r->next = NULL; + return r; +} diff --git a/libpager/seqnos.c b/libpager/seqnos.c deleted file mode 100644 index cab2f33d..00000000 --- a/libpager/seqnos.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Sequence number synchronization routines for pager library - Copyright (C) 1994, 2011 Free Software Foundation - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "priv.h" -#include <assert.h> - -/* The message with seqno SEQNO has just been dequeued for pager P; - wait until all preceding messages have had a chance and then - return. */ -void -_pager_wait_for_seqno (struct pager *p, - mach_port_seqno_t seqno) -{ - while (seqno != p->seqno + 1) - { - p->waitingforseqno = 1; - pthread_cond_wait (&p->wakeup, &p->interlock); - } -} - - -/* Allow the next message for pager P (potentially blocked in - _pager_wait_for_seqno) to be handled. */ -void -_pager_release_seqno (struct pager *p, - mach_port_seqno_t seqno) -{ - assert (seqno == p->seqno + 1); - p->seqno = seqno; - if (p->waitingforseqno) - { - p->waitingforseqno = 0; - pthread_cond_broadcast (&p->wakeup); - } -} - - -/* Just update the seqno. */ -void -_pager_update_seqno (mach_port_t object, - mach_port_seqno_t seqno) -{ - struct pager *p; - - p = ports_lookup_port (0, object, _pager_class); - _pager_update_seqno_p (p, seqno); - if (p) - ports_port_deref (p); -} - - -/* Just update the seqno, pointer version. */ -void -_pager_update_seqno_p (struct pager *p, - mach_port_seqno_t seqno) -{ - if (p - && p->port.class == _pager_class) - { - pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); - _pager_release_seqno (p, seqno); - pthread_mutex_unlock (&p->interlock); - } -} diff --git a/libpager/stubs.c b/libpager/stubs.c index 411f4839..c7f1a5a1 100644 --- a/libpager/stubs.c +++ b/libpager/stubs.c @@ -29,9 +29,6 @@ _pager_seqnos_memory_object_copy (struct pager *p, mach_port_t new) { printf ("m_o_copy called\n"); - - _pager_update_seqno_p (p, seq); - return EOPNOTSUPP; } @@ -44,9 +41,6 @@ _pager_seqnos_memory_object_data_write (struct pager *p, vm_size_t data_cnt) { printf ("m_o_data_write called\n"); - - _pager_update_seqno_p (p, seq); - return EOPNOTSUPP; } @@ -60,8 +54,5 @@ _pager_seqnos_memory_object_supply_completed (struct pager *p, vm_offset_t err_off) { printf ("m_o_supply_completed called\n"); - - _pager_update_seqno_p (p, seq); - return EOPNOTSUPP; } diff --git a/storeio/pager.c b/storeio/pager.c index 7d787110..c260d732 100644 --- a/storeio/pager.c +++ b/storeio/pager.c @@ -24,6 +24,7 @@ #include <strings.h> #include <unistd.h> #include <errno.h> +#include <error.h> #include <sys/mman.h> #include <stdio.h> @@ -142,21 +143,6 @@ pager_clear_user_data (struct user_pager_info *upi) static struct port_bucket *pager_port_bucket = 0; -/* A top-level function for the paging thread that just services paging - requests. */ -static void * -service_paging_requests (void *arg) -{ - (void) arg; - - for (;;) - ports_manage_port_operations_multithread (pager_port_bucket, - pager_demuxer, - 1000 * 30, 1000 * 60 * 5, 0); - - return NULL; -} - /* Initialize paging for this device. */ static void init_dev_paging () @@ -173,14 +159,12 @@ init_dev_paging () pager_port_bucket = ports_create_bucket (); - /* Make a thread to service paging requests. */ - err = pthread_create (&thread, NULL, service_paging_requests, NULL); - if (!err) - pthread_detach (thread); - else + /* Start libpagers worker threads. */ + err = pager_start_workers (pager_port_bucket); + if (err) { errno = err; - perror ("pthread_create"); + error (0, err, "pager_start_workers"); } } pthread_mutex_unlock (&pager_global_lock); |