bug-hurd
[Top][All Lists]
Advanced

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

[PATCH 8/9] libpager: make libpager single-threaded


From: Justus Winter
Subject: [PATCH 8/9] libpager: make libpager single-threaded
Date: Mon, 28 Apr 2014 12:20:03 +0200

Previously, libpager used multiple threads to service requests to
memory objects.  This has proven to be problematic, as paging requests
often arrive in batches, resulting in the creation of many hundred
threads.

Furthermore, the semantic of paging requests requires that the
requests to an object processed in the order the messages were
delivered.  This was implemented using sequence barriers in
_pager_wait_for_seqno, _pager_release_seqno, and
_pager_update_seqno{,_p}.

Unfortunately, this means that not only do we create too many threads,
but worse, all but one thread processing requests to an object are
asleep most of the time.

Previous attempts to introduce a fixed upper bound on the number of
threads failed because ext2fs uses two kinds of pagers.  This has been
fixed in db078e596ee586cd9a77a3a625cea75c79935faf.

Use a single thread to service paging requests.  This removes the need
for the sequence barriers, remove that code.

This prevents paging-related thread-storms.  It also seems to actually
increase the performance of the whole system, as indicated by slightly
faster Hurd package builds.

* console/pager.c (service_paging_requests): Use a single thread.
* ext2fs/pager.c (service_paging_requests): Likewise.
* libdiskfs/disk-pager.c (service_paging_requests): Likewise.
* storeio/pager.c (service_paging_requests): Likewise.
* libpager/chg-compl.c: Remove calls to _pager_wait_for_seqno,
_pager_release_seqno, _pager_update_seqno, and _pager_update_seqno_p.
* libpager/data-request.c: Likewise.
* libpager/data-return.c: Likewise.
* libpager/data-unlock.c: Likewise.
* libpager/demuxer.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/pager-create.c: Likewise.
* libpager/stubs.c: Likewise.
* libpager/priv.h (struct pager): Drop fields seqno and waitingforseqno.
* libpager/seqnos.c: Remove unused file.
* libpager/Makefile (SRCS): Drop seqnos.c.
---
 console/pager.c             |  9 +++---
 ext2fs/pager.c              |  8 ++---
 libdiskfs/disk-pager.c      |  9 +++---
 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          |  3 --
 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-create.c     |  2 --
 libpager/priv.h             |  7 ----
 libpager/seqnos.c           | 79 ---------------------------------------------
 libpager/stubs.c            |  9 ------
 storeio/pager.c             | 10 +++---
 19 files changed, 18 insertions(+), 155 deletions(-)
 delete mode 100644 libpager/seqnos.c

diff --git a/console/pager.c b/console/pager.c
index 87c36f0..e40ae45 100644
--- a/console/pager.c
+++ b/console/pager.c
@@ -127,11 +127,10 @@ 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);
+  ports_manage_port_operations_one_thread (pager_bucket,
+                                          pager_demuxer,
+                                          0);
+  /* Not reached.  */
   return NULL;
 }    
 
diff --git a/ext2fs/pager.c b/ext2fs/pager.c
index 017efcc..92e9178 100644
--- a/ext2fs/pager.c
+++ b/ext2fs/pager.c
@@ -1198,11 +1198,9 @@ 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);
+  ports_manage_port_operations_one_thread (pager_bucket,
+                                          pager_demuxer,
+                                          0);
   /* Not reached.  */
   return NULL;
 }
diff --git a/libdiskfs/disk-pager.c b/libdiskfs/disk-pager.c
index 9a0d9d8..6746d4c 100644
--- a/libdiskfs/disk-pager.c
+++ b/libdiskfs/disk-pager.c
@@ -39,11 +39,10 @@ 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);
+  ports_manage_port_operations_one_thread (pager_bucket,
+                                          pager_demuxer,
+                                          0);
+  /* Not reached.  */
   return NULL;
 }
 
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..90edf1d 100644
--- a/libpager/demuxer.c
+++ b/libpager/demuxer.c
@@ -33,8 +33,5 @@ pager_demuxer (mach_msg_header_t *inp,
       return TRUE;
     }
 
-  /* 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;
 }
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 365ba27..3f0482f 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");
@@ -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-create.c b/libpager/pager-create.c
index 1fc15b8..b583f02 100644
--- a/libpager/pager-create.c
+++ b/libpager/pager-create.c
@@ -42,10 +42,8 @@ pager_create (struct user_pager_info *upi,
   p->notify_on_evict = notify_on_evict;
   p->memobjcntl = MACH_PORT_NULL;
   p->memobjname = MACH_PORT_NULL;
-  p->seqno = -1;
   p->noterm = 0;
   p->termwaiting = 0;
-  p->waitingforseqno = 0;
   p->pagemap = 0;
   p->pagemapsize = 0;
 
diff --git a/libpager/priv.h b/libpager/priv.h
index d49cbb9..dc2f908 100644
--- a/libpager/priv.h
+++ b/libpager/priv.h
@@ -55,14 +55,11 @@ struct pager
   memory_object_control_t memobjcntl;
   memory_object_name_t memobjname;
 
-  mach_port_seqno_t seqno;
-
   int noterm;                  /* number of threads blocking termination */
 
   struct pager *next, **pprev;
 
   int termwaiting:1;
-  int waitingforseqno:1;
 
 #ifdef KERNEL_INIT_RACE
   /* Out of sequence object_init calls waiting for
@@ -136,10 +133,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/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..4f86407 100644
--- a/storeio/pager.c
+++ b/storeio/pager.c
@@ -148,12 +148,10 @@ 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);
-
+  ports_manage_port_operations_one_thread (pager_port_bucket,
+                                          pager_demuxer,
+                                          0);
+  /* Not reached.  */
   return NULL;
 }
 
-- 
1.9.2




reply via email to

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