bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH hurd 1/2] libpager: make the request queue more memory-effici


From: Samuel Thibault
Subject: Re: [PATCH hurd 1/2] libpager: make the request queue more memory-efficient
Date: Sun, 23 Nov 2014 23:53:23 +0100
User-agent: Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30)

Justus Winter, le Sun 23 Nov 2014 23:06:58 +0100, a écrit :
> 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'.

Ack, thanks!

> * 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
> 

-- 
Samuel
I am the "ILOVEGNU" signature virus. Just copy me to your signature.
This email was infected under the terms of the GNU General Public License.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]