summaryrefslogtreecommitdiff
path: root/debian
diff options
context:
space:
mode:
Diffstat (limited to 'debian')
-rw-r--r--debian/patches/libpager-fixthreads.patch1133
-rw-r--r--debian/patches/series1
2 files changed, 0 insertions, 1134 deletions
diff --git a/debian/patches/libpager-fixthreads.patch b/debian/patches/libpager-fixthreads.patch
deleted file mode 100644
index 11cbf092..00000000
--- a/debian/patches/libpager-fixthreads.patch
+++ /dev/null
@@ -1,1133 +0,0 @@
-From c7fbe4eff191fd543f2ae1b46ae7caddf9559af6 Mon Sep 17 00:00:00 2001
-From: Justus Winter <4winter@informatik.uni-hamburg.de>
-Date: Thu, 17 Apr 2014 15:44:12 +0200
-Subject: [PATCH hurd] libpager: use a fixed number of threads
-
-Previously, libpager used an unbounded number of threads to receive
-messages from the pager bucket. It used sequence barriers to execute
-the requests to order requests to each object.
-
-The sequence barriers are implemented in seqnos.c. A server function
-uses _pager_wait_for_seqno to wait for its sequence number and
-_pager_release_seqno to release it, or it uses _pager_update_seqno to
-do both operations in one step.
-
-These sequence barriers divide each server function in three parts: A,
-B, and C. A_i happens "before" the sequence barrier i, B_i happens
-"in order", C_i happens "after" the sequence barrier. This partial
-order < has the following properties:
-
-* This order is *per object*. Requests to different objects are not
- ordered.
-
-* A_i < B_i, B_i < C_i (due to the structure of the code)
-
-* B_i < B_{i+1} (this is due to the sequence barriers)
-
-* Note that only the B parts are ordered by the sequence numbers, we
- are free to execute C_i and C_{i+1} in any possible order. The same
- argument applies to the A parts.
-
-The sequence barriers are implemented using a very simple ticket
-algorithm. Every request, even the invalid ones, is processed by a
-thread, and waits until the ticket count reaches its seqno, does some
-work in-order, then increments the ticket and awakes all threads that
-have piled up up to this moment. All of them except one will then
-discover that it's not their turn yet and go to sleep again.
-
-Creating one thread per request has proven to be problematic as
-memory_object requests often arrive in large batches.
-
-This patch does two things:
-
-* Use a single thread to receive messages from the port bucket. All
- incoming request are put into a queue.
-
-* Use a fixed-number of threads (though even one is actually enough)
- to execute the the server functions. If multiple threads are used,
- a work-delegation mechanism ensures that the per object order < is
- preserved.
-
-For reference, I used the following command to create workloads that
-highlight the problem this patch is addressing:
-
-% settrans t .../ext2fs --sync=30 /dev/sd2s1
-...
-% /usr/bin/time zsh -c 'for ((i=0; i < 1500; i++)); do
- dd if=/dev/zero of=t/src/$i bs=4k count=290 2>/dev/null
- echo -n .
- if ((i % 100 == 0)) ; then echo -n $i; fi
-done'
-
-* libpager/queue.h: New file.
-* libpager/demuxer.c: Manage a queue of requests received from the
-port bucket.
-(pager_demuxer): Just decode the server function and enqueue the
-request.
-(worker_func): New function that consumes and executes the requests
-from the queue.
-(service_paging_requests): New function.
-(pager_start_workers): Likewise.
-* libpager/data-request.c: Remove the seqno barriers.
-* libpager/data-return.c: Likewise.
-* libpager/data-unlock.c: Likewise.
-* libpager/chg-compl.c: Likewise.
-* libpager/lock-completed.c: Likewise.
-* libpager/no-senders.c: Likewise.
-* libpager/notify-stubs.c: Likewise.
-* libpager/object-init.c: Likewise.
-* libpager/object-terminate.c: Likewise.
-* libpager/seqnos.c: Remove file.
-* libpager/stubs.c: Likewise.
-* libpager/pager.h (pager_demuxer): Drop declaration.
-(pager_start_workers): New declaration.
-* libpager/priv.h: Remove the _pager_seqno declarations.
-* libpager/Makefile (SRCS): Drop seqnos.c.
-* console/pager.c (user_pager_init): Call pager_start_workers.
-* libdiskfs/disk-pager.c: Likewise.
-* storeio/pager.c: Likewise.
-* ext2fs/pager.c (service_paging_requests): Remove function.
-(create_disk_pager): Start separate file pager using
-`pager_start_workers'.
-* fatfs/pager.c (service_paging_requests): Remove function.
-(create_fat_pager): Start separate file pager using
-`pager_start_workers'.
----
- console/pager.c | 29 +----
- ext2fs/pager.c | 28 +----
- fatfs/pager.c | 28 +----
- libdiskfs/disk-pager.c | 28 +----
- libpager/Makefile | 2 +-
- libpager/chg-compl.c | 4 +-
- libpager/data-request.c | 3 -
- libpager/data-return.c | 4 -
- libpager/data-unlock.c | 5 -
- libpager/demuxer.c | 287 ++++++++++++++++++++++++++++++++++++++++++--
- libpager/lock-completed.c | 2 -
- libpager/no-senders.c | 1 -
- libpager/notify-stubs.c | 10 --
- libpager/object-init.c | 2 -
- libpager/object-terminate.c | 4 +-
- libpager/pager.h | 7 +-
- libpager/priv.h | 4 -
- libpager/queue.h | 61 ++++++++++
- libpager/seqnos.c | 79 ------------
- libpager/stubs.c | 9 --
- storeio/pager.c | 26 +---
- 21 files changed, 361 insertions(+), 262 deletions(-)
- create mode 100644 libpager/queue.h
- delete mode 100644 libpager/seqnos.c
-
-diff --git a/console/pager.c b/console/pager.c
-index 87c36f0..3568211 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 39cf1c7..298dae7 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 f855ecf..0c59084 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 9a0d9d8..4083ef2 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 b622295..a15a899 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 d77c46c..89ccfc8 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 82ce904..18f3de6 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 ee6c6e8..f16f323 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 599237c..8c7c776 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 b4d4054..efdf285 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 a3f3f16..30b1dd3 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 c21dfc2..d0bbe27 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 ba13882..a826420 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 6683e24..eb62c44 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 332bcab..e8c6f38 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 d0572af..29ec833 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 1f8405a..4576e12 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 0000000..d3cf738
---- /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 cab2f33..0000000
---- 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 411f483..c7f1a5a 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 7d78711..c260d73 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);
---
-2.1.1
-
diff --git a/debian/patches/series b/debian/patches/series
index 5df1a067..76ad8769 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -55,7 +55,6 @@ xkb-compat.patch
#procfs-0007-procfs-provide-magic-retry-response-for-proc-self.patch
startup-avoid-broken-puts.patch
-libpager-fixthreads.patch
0001-libshouldbeinlibc-add-assert.h-variant-that-prints-b.patch
0002-include-use-assert-backtrace.h-in-refcount.h.patch