summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-11-23 18:11:30 +0100
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-11-23 18:11:30 +0100
commitb3fcdc50024b3837a76cd854d02a940dac2e5dc3 (patch)
treecd19784b3e8eda7fde8601f0fb2c15d60fb3aae1
parent25fe9cb62331d609b87b9d0b1db06d06ab825d16 (diff)
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.
-rw-r--r--libpager/demuxer.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/libpager/demuxer.c b/libpager/demuxer.c
index efdf2853..a06c4bfa 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)
{