summaryrefslogtreecommitdiff
path: root/debian/patches
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches')
-rw-r--r--debian/patches/libpager-make-the-request-queue-more-memory-efficien.patch163
1 files changed, 163 insertions, 0 deletions
diff --git a/debian/patches/libpager-make-the-request-queue-more-memory-efficien.patch b/debian/patches/libpager-make-the-request-queue-more-memory-efficien.patch
new file mode 100644
index 00000000..57023592
--- /dev/null
+++ b/debian/patches/libpager-make-the-request-queue-more-memory-efficien.patch
@@ -0,0 +1,163 @@
+From b3fcdc50024b3837a76cd854d02a940dac2e5dc3 Mon Sep 17 00:00:00 2001
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Sun, 23 Nov 2014 18:11:30 +0100
+Subject: [PATCH hurd] libpager: make the request queue more memory-efficient
+
+Previously, `pager_demuxer' allocated a chunk of memory for the
+response message. But if memory gets scarce, the kernel will issue a
+large number of paging requests to free up memory. In such a
+situation, allocating memory is dangerous.
+
+Fix this by not allocating space for the response message, rather, use
+a chunk of the workers stack space. Also, we only handle the `notify'
+and `memory_object' protocol, which both only contain simple routines,
+we only need a `mig_response_header_t'.
+
+* libpager/demuxer.c (struct request): Remove `inp' and `outp'.
+(request_inp): New function.
+(pager_demuxer): Do not allocate memory for the response.
+(mig_reply_setup): New function.
+(worker_func): Adjust accordingly.
+---
+ libpager/demuxer.c | 66 ++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 49 insertions(+), 17 deletions(-)
+
+diff --git a/libpager/demuxer.c b/libpager/demuxer.c
+index efdf285..a06c4bf 100644
+--- a/libpager/demuxer.c
++++ b/libpager/demuxer.c
+@@ -47,10 +47,16 @@ struct request
+ {
+ struct item item;
+ mig_routine_t routine;
+- mach_msg_header_t *inp;
+- mach_msg_header_t *outp;
+ };
+
++/* A struct request object is immediately followed by the received
++ message. */
++static inline mach_msg_header_t *
++request_inp (const struct request *r)
++{
++ return (mach_msg_header_t *) ((char *) r + sizeof *r);
++}
++
+ /* A worker. */
+ struct worker
+ {
+@@ -81,10 +87,6 @@ pager_demuxer (struct requests *requests,
+ {
+ 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))))
+@@ -94,7 +96,7 @@ pager_demuxer (struct requests *requests,
+ mach_msg_size_t padded_size = (inp->msgh_size + MASK) & ~MASK;
+ #undef MASK
+
+- struct request *r = malloc (sizeof *r + padded_size + max_size);
++ struct request *r = malloc (sizeof *r + padded_size);
+ if (r == NULL)
+ {
+ err = ENOMEM;
+@@ -102,11 +104,7 @@ pager_demuxer (struct requests *requests,
+ }
+
+ 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);
++ memcpy (request_inp (r), inp, inp->msgh_size);
+
+ pthread_mutex_lock (&requests->lock);
+
+@@ -126,6 +124,37 @@ pager_demuxer (struct requests *requests,
+ return TRUE;
+ }
+
++/* XXX: The libc should provide this function. */
++static void
++mig_reply_setup (
++ const mach_msg_header_t *in,
++ mach_msg_header_t *out)
++{
++ static const mach_msg_type_t RetCodeType = {
++ /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
++ /* msgt_size = */ 32,
++ /* msgt_number = */ 1,
++ /* msgt_inline = */ TRUE,
++ /* msgt_longform = */ FALSE,
++ /* msgt_deallocate = */ FALSE,
++ /* msgt_unused = */ 0
++ };
++
++#define InP (in)
++#define OutP ((mig_reply_header_t *) out)
++ OutP->Head.msgh_bits =
++ MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InP->msgh_bits), 0);
++ OutP->Head.msgh_size = sizeof *OutP;
++ OutP->Head.msgh_remote_port = InP->msgh_remote_port;
++ OutP->Head.msgh_local_port = MACH_PORT_NULL;
++ OutP->Head.msgh_seqno = 0;
++ OutP->Head.msgh_id = InP->msgh_id + 100;
++ OutP->RetCodeType = RetCodeType;
++ OutP->RetCode = MIG_BAD_ID;
++#undef InP
++#undef OutP
++}
++
+ /* Consumes requests from the queue. */
+ static void *
+ worker_func (void *arg)
+@@ -133,6 +162,7 @@ worker_func (void *arg)
+ struct worker *self = (struct worker *) arg;
+ struct requests *requests = self->requests;
+ struct request *r = NULL;
++ mig_reply_header_t reply_msg;
+
+ while (1)
+ {
+@@ -165,7 +195,7 @@ worker_func (void *arg)
+
+ for (i = 0; i < WORKER_COUNT; i++)
+ if (requests->workers[i].tag
+- == (unsigned long) r->inp->msgh_local_port)
++ == (unsigned long) request_inp (r)->msgh_local_port)
+ {
+ /* Some other thread is working on that object. Delegate
+ the request to that worker. */
+@@ -174,18 +204,20 @@ worker_func (void *arg)
+ }
+
+ /* Claim responsibility for this object by setting our tag. */
+- self->tag = (unsigned long) r->inp->msgh_local_port;
++ self->tag = (unsigned long) request_inp (r)->msgh_local_port;
+
+ got_one:
+ pthread_mutex_unlock (&requests->lock);
+
++ mig_reply_setup (request_inp (r), (mach_msg_header_t *) &reply_msg);
++
+ /* Call the server routine. */
+- (*r->routine) (r->inp, r->outp);
++ (*r->routine) (request_inp (r), (mach_msg_header_t *) &reply_msg);
+
+ /* 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;
++ mig_reply_header_t *request = (mig_reply_header_t *) request_inp (r);
++ mig_reply_header_t *reply = &reply_msg;
+
+ switch (reply->RetCode)
+ {
+--
+2.1.3
+