summaryrefslogtreecommitdiff
path: root/debian
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-03 04:04:45 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-03 04:04:45 +0200
commit157e44e4f5befe8ba70be069bc8ded43e7c9ed72 (patch)
tree14ef2a9b5a968ed19e6acc841ba1aac425f6b7d9 /debian
parent1ee1f37b0ec4de8fe4429a2bf981f3f3c4b8ad7c (diff)
add libports-per-bucket-hashtable.patch
Diffstat (limited to 'debian')
-rw-r--r--debian/patches/libports-per-bucket-hashtable.patch1058
-rw-r--r--debian/patches/series1
2 files changed, 1059 insertions, 0 deletions
diff --git a/debian/patches/libports-per-bucket-hashtable.patch b/debian/patches/libports-per-bucket-hashtable.patch
new file mode 100644
index 00000000..e1406f02
--- /dev/null
+++ b/debian/patches/libports-per-bucket-hashtable.patch
@@ -0,0 +1,1058 @@
+commit 74ecfb7e8b9249f60deaaf1f516d35a4f825b9dc
+Author: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Sat May 3 03:53:41 2014 +0200
+
+ libports: per-bucket lock for the hash tables
+
+diff --git a/libports/begin-rpc.c b/libports/begin-rpc.c
+index 142af98..de58b06 100644
+--- a/libports/begin-rpc.c
++++ b/libports/begin-rpc.c
+@@ -29,14 +29,14 @@ ports_begin_rpc (void *portstruct, mach_msg_id_t msg_id, struct rpc_info *info)
+
+ struct port_info *pi = portstruct;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ do
+ {
+ /* If our receive right is gone, then abandon the RPC. */
+ if (pi->port_right == MACH_PORT_NULL)
+ {
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return EOPNOTSUPP;
+ }
+
+@@ -75,13 +75,13 @@ ports_begin_rpc (void *portstruct, mach_msg_id_t msg_id, struct rpc_info *info)
+ if (block_flags)
+ {
+ *block_flags |= PORTS_BLOCKED;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ /* We've been cancelled, just return EINTR. If we were the
+ only one blocking, PORTS_BLOCKED will still be turned on,
+ but that's ok, it will just cause a (harmless) extra
+ pthread_cond_broadcast(). */
+ {
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return EINTR;
+ }
+ }
+@@ -102,7 +102,7 @@ ports_begin_rpc (void *portstruct, mach_msg_id_t msg_id, struct rpc_info *info)
+ pi->bucket->rpcs++;
+ _ports_total_rpcs++;
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return 0;
+ }
+diff --git a/libports/bucket-iterate.c b/libports/bucket-iterate.c
+index 38a9f7a..8a306f0 100644
+--- a/libports/bucket-iterate.c
++++ b/libports/bucket-iterate.c
+@@ -35,11 +35,11 @@ _ports_bucket_class_iterate (struct port_bucket *bucket,
+ size_t i, n, nr_items;
+ error_t err;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&bucket->lock);
+
+ if (bucket->htable.nr_items == 0)
+ {
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&bucket->lock);
+ return 0;
+ }
+
+@@ -60,7 +60,7 @@ _ports_bucket_class_iterate (struct port_bucket *bucket,
+ n++;
+ }
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&bucket->lock);
+
+ if (n != nr_items)
+ {
+diff --git a/libports/claim-right.c b/libports/claim-right.c
+index 4851ea3..73e383a 100644
+--- a/libports/claim-right.c
++++ b/libports/claim-right.c
+@@ -34,19 +34,21 @@ ports_claim_right (void *portstruct)
+ if (ret == MACH_PORT_NULL)
+ return ret;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&pi->bucket->lock);
+ hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry);
++ pthread_mutex_unlock (&pi->bucket->lock);
+ err = mach_port_move_member (mach_task_self (), ret, MACH_PORT_NULL);
+ assert_perror (err);
++ pthread_mutex_lock (&_ports_global_lock);
+ pi->port_right = MACH_PORT_NULL;
+ if (pi->flags & PORT_HAS_SENDRIGHTS)
+ {
+ pi->flags &= ~PORT_HAS_SENDRIGHTS;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ ports_port_deref (pi);
+ }
+ else
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return ret;
+ }
+diff --git a/libports/class-iterate.c b/libports/class-iterate.c
+index 1f8878a..638dd45 100644
+--- a/libports/class-iterate.c
++++ b/libports/class-iterate.c
+@@ -23,13 +23,13 @@ error_t
+ ports_class_iterate (struct port_class *class,
+ error_t (*fun)(void *))
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ if (class->ports != 0)
+ {
+ struct port_bucket *bucket = class->ports->bucket;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return _ports_bucket_class_iterate (bucket, class, fun);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return 0;
+ }
+diff --git a/libports/complete-deallocate.c b/libports/complete-deallocate.c
+index 7e7d467..c08d0ce 100644
+--- a/libports/complete-deallocate.c
++++ b/libports/complete-deallocate.c
+@@ -29,13 +29,15 @@ _ports_complete_deallocate (struct port_info *pi)
+
+ if (pi->port_right)
+ {
++ pthread_mutex_lock (&pi->bucket->lock);
+ hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry);
++ pthread_mutex_unlock (&pi->bucket->lock);
+ mach_port_mod_refs (mach_task_self (), pi->port_right,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ pi->port_right = MACH_PORT_NULL;
+ }
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ *pi->prevp = pi->next;
+ if (pi->next)
+@@ -44,7 +46,7 @@ _ports_complete_deallocate (struct port_info *pi)
+ pi->bucket->count--;
+ pi->class->count--;
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ if (pi->class->clean_routine)
+ (*pi->class->clean_routine)(pi);
+diff --git a/libports/count-bucket.c b/libports/count-bucket.c
+index 63feb6b..8e6eadb 100644
+--- a/libports/count-bucket.c
++++ b/libports/count-bucket.c
+@@ -25,10 +25,10 @@ ports_count_bucket (struct port_bucket *bucket)
+ {
+ int ret;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ ret = bucket->count;
+ bucket->flags |= PORT_BUCKET_NO_ALLOC;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return ret;
+ }
+diff --git a/libports/count-class.c b/libports/count-class.c
+index 0c48b46..5f5dc73 100644
+--- a/libports/count-class.c
++++ b/libports/count-class.c
+@@ -25,9 +25,9 @@ ports_count_class (struct port_class *class)
+ {
+ int ret;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ ret = class->count;
+ class->flags |= PORT_CLASS_NO_ALLOC;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return ret;
+ }
+diff --git a/libports/create-bucket.c b/libports/create-bucket.c
+index 52d50c3..f8a0996 100644
+--- a/libports/create-bucket.c
++++ b/libports/create-bucket.c
+@@ -46,13 +46,14 @@ ports_create_bucket ()
+ return NULL;
+ }
+
++ pthread_mutex_init (&ret->lock, NULL);
+ hurd_ihash_init (&ret->htable, offsetof (struct port_info, hentry));
+ ret->rpcs = ret->flags = ret->count = 0;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ ret->next = _ports_all_buckets;
+ _ports_all_buckets = ret;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return ret;
+ }
+diff --git a/libports/create-internal.c b/libports/create-internal.c
+index d56637c..33ee1e1 100644
+--- a/libports/create-internal.c
++++ b/libports/create-internal.c
+@@ -62,25 +62,27 @@ _ports_create_port_internal (struct port_class *class,
+ pi->current_rpcs = 0;
+ pi->bucket = bucket;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ loop:
+ if (class->flags & PORT_CLASS_NO_ALLOC)
+ {
+ class->flags |= PORT_CLASS_ALLOC_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ goto cancelled;
+ goto loop;
+ }
+ if (bucket->flags & PORT_BUCKET_NO_ALLOC)
+ {
+ bucket->flags |= PORT_BUCKET_ALLOC_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ goto cancelled;
+ goto loop;
+ }
+
++ pthread_mutex_lock (&bucket->lock);
+ err = hurd_ihash_add (&bucket->htable, port, pi);
++ pthread_mutex_unlock (&bucket->lock);
+ if (err)
+ goto lose;
+
+@@ -91,7 +93,7 @@ _ports_create_port_internal (struct port_class *class,
+ class->ports = pi;
+ bucket->count++;
+ class->count++;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ if (install)
+ {
+@@ -107,7 +109,7 @@ _ports_create_port_internal (struct port_class *class,
+ cancelled:
+ err = EINTR;
+ lose:
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ lose_unlocked:;
+ error_t e;
+ e = mach_port_mod_refs (mach_task_self (), port,
+diff --git a/libports/destroy-right.c b/libports/destroy-right.c
+index 65e19c7..b12dec9 100644
+--- a/libports/destroy-right.c
++++ b/libports/destroy-right.c
+@@ -30,12 +30,12 @@ ports_destroy_right (void *portstruct)
+
+ if (pi->port_right != MACH_PORT_NULL)
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&pi->bucket->lock);
+ hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry);
+ err = mach_port_mod_refs (mach_task_self (), pi->port_right,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ assert_perror (err);
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&pi->bucket->lock);
+
+ pi->port_right = MACH_PORT_NULL;
+
+diff --git a/libports/enable-bucket.c b/libports/enable-bucket.c
+index f9c7b85..bf33cf8 100644
+--- a/libports/enable-bucket.c
++++ b/libports/enable-bucket.c
+@@ -23,12 +23,12 @@
+ void
+ ports_enable_bucket (struct port_bucket *bucket)
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ bucket->flags &= ~PORT_BUCKET_NO_ALLOC;
+ if (bucket->flags & PORT_BUCKET_ALLOC_WAIT)
+ {
+ bucket->flags &= ~PORT_BUCKET_ALLOC_WAIT;
+ pthread_cond_broadcast (&_ports_block);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/enable-class.c b/libports/enable-class.c
+index b3894eb..cbddc1a 100644
+--- a/libports/enable-class.c
++++ b/libports/enable-class.c
+@@ -23,12 +23,12 @@
+ void
+ ports_enable_class (struct port_class *class)
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ class->flags &= ~PORT_CLASS_NO_ALLOC;
+ if (class->flags & PORT_CLASS_ALLOC_WAIT)
+ {
+ class->flags &= ~PORT_CLASS_ALLOC_WAIT;
+ pthread_cond_broadcast (&_ports_block);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/end-rpc.c b/libports/end-rpc.c
+index b5dcb3a..9134822 100644
+--- a/libports/end-rpc.c
++++ b/libports/end-rpc.c
+@@ -25,7 +25,7 @@ ports_end_rpc (void *port, struct rpc_info *info)
+ {
+ struct port_info *pi = port;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ if (info->notifies)
+ _ports_remove_notified_rpc (info);
+@@ -51,5 +51,5 @@ ports_end_rpc (void *port, struct rpc_info *info)
+ RPC is now finished anwhow. */
+ hurd_check_cancel ();
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/get-right.c b/libports/get-right.c
+index 42bfa2b..e0c7853 100644
+--- a/libports/get-right.c
++++ b/libports/get-right.c
+@@ -29,11 +29,11 @@ ports_get_right (void *port)
+ mach_port_t foo;
+ error_t err;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&pi->bucket->lock);
+
+ if (pi->port_right == MACH_PORT_NULL)
+ {
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&pi->bucket->lock);
+ return MACH_PORT_NULL;
+ }
+
+@@ -53,6 +53,6 @@ ports_get_right (void *port)
+ if (foo != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), foo);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&pi->bucket->lock);
+ return pi->port_right;
+ }
+diff --git a/libports/import-port.c b/libports/import-port.c
+index 5c66685..1aa422a 100644
+--- a/libports/import-port.c
++++ b/libports/import-port.c
+@@ -56,25 +56,27 @@ ports_import_port (struct port_class *class, struct port_bucket *bucket,
+ pi->current_rpcs = 0;
+ pi->bucket = bucket;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ loop:
+ if (class->flags & PORT_CLASS_NO_ALLOC)
+ {
+ class->flags |= PORT_CLASS_ALLOC_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ goto cancelled;
+ goto loop;
+ }
+ if (bucket->flags & PORT_BUCKET_NO_ALLOC)
+ {
+ bucket->flags |= PORT_BUCKET_ALLOC_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ goto cancelled;
+ goto loop;
+ }
+
++ pthread_mutex_lock (&bucket->lock);
+ err = hurd_ihash_add (&bucket->htable, port, pi);
++ pthread_mutex_unlock (&bucket->lock);
+ if (err)
+ goto lose;
+
+@@ -85,7 +87,7 @@ ports_import_port (struct port_class *class, struct port_bucket *bucket,
+ class->ports = pi;
+ bucket->count++;
+ class->count++;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ mach_port_move_member (mach_task_self (), port, bucket->portset);
+
+@@ -107,7 +109,7 @@ ports_import_port (struct port_class *class, struct port_bucket *bucket,
+ cancelled:
+ err = EINTR;
+ lose:
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ free (pi);
+
+ return err;
+diff --git a/libports/inhibit-all-rpcs.c b/libports/inhibit-all-rpcs.c
+index d4a54ba..337d068 100644
+--- a/libports/inhibit-all-rpcs.c
++++ b/libports/inhibit-all-rpcs.c
+@@ -27,7 +27,7 @@ ports_inhibit_all_rpcs ()
+ {
+ error_t err = 0;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ if (_ports_flags & (_PORTS_INHIBITED | _PORTS_INHIBIT_WAIT))
+ err = EBUSY;
+@@ -38,6 +38,7 @@ ports_inhibit_all_rpcs ()
+
+ for (bucket = _ports_all_buckets; bucket; bucket = bucket->next)
+ {
++ pthread_mutex_lock (&bucket->lock);
+ HURD_IHASH_ITERATE (&bucket->htable, portstruct)
+ {
+ struct rpc_info *rpc;
+@@ -53,12 +54,13 @@ ports_inhibit_all_rpcs ()
+ hurd_thread_cancel (rpc->thread);
+ }
+ }
++ pthread_mutex_unlock (&bucket->lock);
+ }
+
+ while (_ports_total_rpcs > this_one)
+ {
+ _ports_flags |= _PORTS_INHIBIT_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ /* We got cancelled. */
+ {
+ err = EINTR;
+@@ -71,7 +73,7 @@ ports_inhibit_all_rpcs ()
+ _ports_flags |= _PORTS_INHIBITED;
+ }
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return err;
+ }
+diff --git a/libports/inhibit-bucket-rpcs.c b/libports/inhibit-bucket-rpcs.c
+index 965aa03..d55798e 100644
+--- a/libports/inhibit-bucket-rpcs.c
++++ b/libports/inhibit-bucket-rpcs.c
+@@ -27,7 +27,7 @@ ports_inhibit_bucket_rpcs (struct port_bucket *bucket)
+ {
+ error_t err = 0;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ if (bucket->flags & (PORT_BUCKET_INHIBITED | PORT_BUCKET_INHIBIT_WAIT))
+ err = EBUSY;
+@@ -35,6 +35,7 @@ ports_inhibit_bucket_rpcs (struct port_bucket *bucket)
+ {
+ int this_one = 0;
+
++ pthread_mutex_lock (&bucket->lock);
+ HURD_IHASH_ITERATE (&bucket->htable, portstruct)
+ {
+ struct rpc_info *rpc;
+@@ -49,12 +50,12 @@ ports_inhibit_bucket_rpcs (struct port_bucket *bucket)
+ hurd_thread_cancel (rpc->thread);
+ }
+ }
+-
++ pthread_mutex_unlock (&bucket->lock);
+
+ while (bucket->rpcs > this_one)
+ {
+ bucket->flags |= PORT_BUCKET_INHIBIT_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ /* We got cancelled. */
+ {
+ err = EINTR;
+@@ -67,7 +68,7 @@ ports_inhibit_bucket_rpcs (struct port_bucket *bucket)
+ bucket->flags |= PORT_BUCKET_INHIBITED;
+ }
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return err;
+ }
+diff --git a/libports/inhibit-class-rpcs.c b/libports/inhibit-class-rpcs.c
+index 7ee8653..fe26f27 100644
+--- a/libports/inhibit-class-rpcs.c
++++ b/libports/inhibit-class-rpcs.c
+@@ -26,7 +26,7 @@ ports_inhibit_class_rpcs (struct port_class *class)
+ {
+ error_t err = 0;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ if (class->flags & (PORT_CLASS_INHIBITED | PORT_CLASS_INHIBIT_WAIT))
+ err = EBUSY;
+@@ -49,7 +49,7 @@ ports_inhibit_class_rpcs (struct port_class *class)
+ while (class->rpcs > this_one)
+ {
+ class->flags |= PORT_CLASS_INHIBIT_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ /* We got cancelled. */
+ {
+ err = EINTR;
+@@ -62,7 +62,7 @@ ports_inhibit_class_rpcs (struct port_class *class)
+ class->flags |= PORT_CLASS_INHIBITED;
+ }
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return err;
+ }
+diff --git a/libports/inhibit-port-rpcs.c b/libports/inhibit-port-rpcs.c
+index b741eeb..f712ca9 100644
+--- a/libports/inhibit-port-rpcs.c
++++ b/libports/inhibit-port-rpcs.c
+@@ -27,7 +27,7 @@ ports_inhibit_port_rpcs (void *portstruct)
+ error_t err = 0;
+ struct port_info *pi = portstruct;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ if (pi->flags & (PORT_INHIBITED | PORT_INHIBIT_WAIT))
+ err = EBUSY;
+@@ -50,7 +50,7 @@ ports_inhibit_port_rpcs (void *portstruct)
+ && !(pi->current_rpcs == this_rpc && ! this_rpc->next))
+ {
+ pi->flags |= PORT_INHIBIT_WAIT;
+- if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_lock))
++ if (pthread_hurd_cond_wait_np (&_ports_block, &_ports_global_lock))
+ /* We got cancelled. */
+ {
+ err = EINTR;
+@@ -63,7 +63,7 @@ ports_inhibit_port_rpcs (void *portstruct)
+ pi->flags |= PORT_INHIBITED;
+ }
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ return err;
+ }
+diff --git a/libports/init.c b/libports/init.c
+index 3ef5388..36e42a0 100644
+--- a/libports/init.c
++++ b/libports/init.c
+@@ -20,7 +20,7 @@
+
+ #include "ports.h"
+
+-pthread_mutex_t _ports_lock = PTHREAD_MUTEX_INITIALIZER;
++pthread_mutex_t _ports_global_lock = PTHREAD_MUTEX_INITIALIZER;
+ pthread_cond_t _ports_block = PTHREAD_COND_INITIALIZER;
+ struct port_bucket *_ports_all_buckets;
+ int _ports_total_rpcs;
+diff --git a/libports/interrupt-notified-rpcs.c b/libports/interrupt-notified-rpcs.c
+index 49a15d0..06f1c1f 100644
+--- a/libports/interrupt-notified-rpcs.c
++++ b/libports/interrupt-notified-rpcs.c
+@@ -36,7 +36,7 @@ ports_interrupt_notified_rpcs (void *object,
+ {
+ struct ports_notify *np;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ for (np = _ports_notifications; np; np = np->next)
+ if (np->port == port && np->what == what)
+ {
+@@ -49,7 +49,7 @@ ports_interrupt_notified_rpcs (void *object,
+ }
+ break;
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+ }
+
+diff --git a/libports/interrupt-on-notify.c b/libports/interrupt-on-notify.c
+index b358e84..7b93429 100644
+--- a/libports/interrupt-on-notify.c
++++ b/libports/interrupt-on-notify.c
+@@ -34,13 +34,13 @@ ports_interrupt_rpc_on_notification (void *object,
+ struct rpc_notify *new_req, *req;
+ struct port_info *pi = object;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ if (! MACH_PORT_VALID (port))
+ /* PORT is already dead or bogus, so interrupt the rpc immediately. */
+ {
+ hurd_thread_cancel (rpc->thread);
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return 0;
+ }
+
+@@ -53,11 +53,11 @@ ports_interrupt_rpc_on_notification (void *object,
+ time we'll add a new structure, so we malloc while we don't have the
+ lock, and free it if we're wrong. */
+ {
+- pthread_mutex_unlock (&_ports_lock); /* Don't hold the lock during malloc. */
++ pthread_mutex_unlock (&_ports_global_lock); /* Don't hold the lock during malloc. */
+ new_req = malloc (sizeof (struct rpc_notify));
+ if (! new_req)
+ return ENOMEM;
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ }
+
+ /* Find any existing entry for PORT/WHAT. */
+@@ -80,7 +80,7 @@ ports_interrupt_rpc_on_notification (void *object,
+ {
+ new_req->next = _ports_free_rpc_notifies;
+ _ports_free_rpc_notifies = new_req;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return ENOMEM;
+ }
+ }
+@@ -138,7 +138,7 @@ ports_interrupt_rpc_on_notification (void *object,
+ if (req_notify)
+ pthread_mutex_lock (&pn->lock);
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ if (req_notify)
+ {
+@@ -170,11 +170,11 @@ ports_interrupt_self_on_notification (void *object,
+ struct port_info *pi = object;
+ thread_t thread = hurd_thread_self ();
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ for (rpc = pi->current_rpcs; rpc; rpc = rpc->next)
+ if (rpc->thread == thread)
+ break;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+
+ assert (rpc);
+
+diff --git a/libports/interrupt-operation.c b/libports/interrupt-operation.c
+index 943bd4f..940ae27 100644
+--- a/libports/interrupt-operation.c
++++ b/libports/interrupt-operation.c
+@@ -29,10 +29,10 @@ ports_S_interrupt_operation (struct port_info *pi,
+ {
+ if (!pi)
+ return EOPNOTSUPP;
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ if (pi->cancel_threshold < seqno)
+ pi->cancel_threshold = seqno;
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ ports_interrupt_rpcs (pi);
+ return 0;
+ }
+diff --git a/libports/interrupt-rpcs.c b/libports/interrupt-rpcs.c
+index 42f51a5..3dc3777 100644
+--- a/libports/interrupt-rpcs.c
++++ b/libports/interrupt-rpcs.c
+@@ -27,7 +27,7 @@ ports_interrupt_rpcs (void *portstruct)
+ struct port_info *pi = portstruct;
+ struct rpc_info *rpc;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ for (rpc = pi->current_rpcs; rpc; rpc = rpc->next)
+ {
+@@ -35,5 +35,5 @@ ports_interrupt_rpcs (void *portstruct)
+ _ports_record_interruption (rpc);
+ }
+
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/lookup-port.c b/libports/lookup-port.c
+index 289369f..c919266 100644
+--- a/libports/lookup-port.c
++++ b/libports/lookup-port.c
+@@ -27,26 +27,32 @@ ports_lookup_port (struct port_bucket *bucket,
+ struct port_class *class)
+ {
+ struct port_info *pi = 0;
+-
+- pthread_mutex_lock (&_ports_lock);
+
+ if (bucket)
+- pi = hurd_ihash_find (&bucket->htable, port);
++ {
++ pthread_mutex_lock (&bucket->lock);
++ pi = hurd_ihash_find (&bucket->htable, port);
++ pthread_mutex_unlock (&bucket->lock);
++ }
+ else
+- for (bucket = _ports_all_buckets; bucket; bucket = bucket->next)
+- {
+- pi = hurd_ihash_find (&bucket->htable, port);
+- if (pi)
+- break;
+- }
+-
++ {
++ pthread_mutex_lock (&_ports_global_lock);
++ for (bucket = _ports_all_buckets; bucket; bucket = bucket->next)
++ {
++ pthread_mutex_lock (&bucket->lock);
++ pi = hurd_ihash_find (&bucket->htable, port);
++ pthread_mutex_unlock (&bucket->lock);
++ if (pi)
++ break;
++ }
++ pthread_mutex_unlock (&_ports_global_lock);
++ }
++
+ if (pi && class && pi->class != class)
+ pi = 0;
+
+ if (pi)
+ ports_port_ref (pi);
+
+- pthread_mutex_unlock (&_ports_lock);
+-
+ return pi;
+ }
+diff --git a/libports/manage-multithread.c b/libports/manage-multithread.c
+index 2067cba..3ef4f4e 100644
+--- a/libports/manage-multithread.c
++++ b/libports/manage-multithread.c
+@@ -173,10 +173,10 @@ ports_manage_port_operations_multithread (struct port_bucket *bucket,
+ }
+ else
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ if (inp->msgh_seqno < pi->cancel_threshold)
+ hurd_thread_cancel (link.thread);
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ status = demuxer (inp, outheadp);
+ ports_end_rpc (pi, &link);
+ }
+diff --git a/libports/no-senders.c b/libports/no-senders.c
+index 1a6084b..77d033f 100644
+--- a/libports/no-senders.c
++++ b/libports/no-senders.c
+@@ -29,10 +29,10 @@ ports_no_senders (void *portstruct,
+ int dealloc;
+ mach_port_t old;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ if ((pi->flags & PORT_HAS_SENDRIGHTS) == 0)
+ {
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ return;
+ }
+ if (mscount >= pi->mscount)
+@@ -53,8 +53,8 @@ ports_no_senders (void *portstruct,
+ mach_port_deallocate (mach_task_self (), old);
+ dealloc = 0;
+ }
+- pthread_mutex_unlock (&_ports_lock);
+-
++ pthread_mutex_unlock (&_ports_global_lock);
++
+ if (dealloc)
+ {
+ ports_interrupt_notified_rpcs (portstruct, pi->port_right,
+diff --git a/libports/ports.h b/libports/ports.h
+index 7088b2d..c5bf8eb 100644
+--- a/libports/ports.h
++++ b/libports/ports.h
+@@ -67,6 +67,8 @@ struct port_bucket
+ int rpcs;
+ int flags;
+ int count;
++ pthread_mutex_t lock;
++
+ struct port_bucket *next;
+ };
+ /* FLAGS above are the following: */
+@@ -402,7 +404,7 @@ extern kern_return_t
+ ports_do_mach_notify_send_once (struct port_info *pi);
+
+ /* Private data */
+-extern pthread_mutex_t _ports_lock;
++extern pthread_mutex_t _ports_global_lock;
+ extern pthread_cond_t _ports_block;
+ extern struct port_bucket *_ports_all_buckets;
+ extern int _ports_total_rpcs;
+diff --git a/libports/reallocate-from-external.c b/libports/reallocate-from-external.c
+index 4dfc59c..84fecc9 100644
+--- a/libports/reallocate-from-external.c
++++ b/libports/reallocate-from-external.c
+@@ -34,17 +34,19 @@ ports_reallocate_from_external (void *portstruct, mach_port_t receive)
+
+ err = mach_port_get_receive_status (mach_task_self (), receive, &stat);
+ assert_perror (err);
+-
+- pthread_mutex_lock (&_ports_lock);
+-
++
++ pthread_mutex_lock (&_ports_global_lock);
++
+ assert (pi->port_right);
+
+ err = mach_port_mod_refs (mach_task_self (), pi->port_right,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ assert_perror (err);
+
++ pthread_mutex_lock (&pi->bucket->lock);
+ hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry);
+-
++ pthread_mutex_unlock (&pi->bucket->lock);
++
+ if ((pi->flags & PORT_HAS_SENDRIGHTS) && !stat.mps_srights)
+ {
+ dropref = 1;
+@@ -55,15 +57,17 @@ ports_reallocate_from_external (void *portstruct, mach_port_t receive)
+ pi->flags |= PORT_HAS_SENDRIGHTS;
+ ports_port_ref (pi);
+ }
+-
++ pthread_mutex_unlock (&_ports_global_lock);
++
+ pi->port_right = receive;
+ pi->cancel_threshold = 0;
+ pi->mscount = stat.mps_mscount;
+-
++
++ pthread_mutex_lock (&pi->bucket->lock);
+ err = hurd_ihash_add (&pi->bucket->htable, receive, pi);
++ pthread_mutex_unlock (&pi->bucket->lock);
+ assert_perror (err);
+- pthread_mutex_unlock (&_ports_lock);
+-
++
+ mach_port_move_member (mach_task_self (), receive, pi->bucket->portset);
+
+ if (stat.mps_srights)
+diff --git a/libports/reallocate-port.c b/libports/reallocate-port.c
+index d2adaeb..f68865e 100644
+--- a/libports/reallocate-port.c
++++ b/libports/reallocate-port.c
+@@ -29,14 +29,16 @@ ports_reallocate_port (void *portstruct)
+ error_t err;
+ int dropref = 0;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ assert (pi->port_right);
+
+ err = mach_port_mod_refs (mach_task_self (), pi->port_right,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ assert_perror (err);
+
++ pthread_mutex_lock (&pi->bucket->lock);
+ hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry);
++ pthread_mutex_unlock (&pi->bucket->lock);
+
+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &pi->port_right);
+@@ -46,11 +48,14 @@ ports_reallocate_port (void *portstruct)
+ pi->flags &= ~PORT_HAS_SENDRIGHTS;
+ dropref = 1;
+ }
++ pthread_mutex_unlock (&_ports_global_lock);
++
+ pi->cancel_threshold = 0;
+ pi->mscount = 0;
++ pthread_mutex_lock (&pi->bucket->lock);
+ err = hurd_ihash_add (&pi->bucket->htable, pi->port_right, pi);
++ pthread_mutex_unlock (&pi->bucket->lock);
+ assert_perror (err);
+- pthread_mutex_unlock (&_ports_lock);
+
+ err = mach_port_move_member (mach_task_self (), pi->port_right,
+ pi->bucket->portset);
+diff --git a/libports/resume-all-rpcs.c b/libports/resume-all-rpcs.c
+index e4befff..e7766a1 100644
+--- a/libports/resume-all-rpcs.c
++++ b/libports/resume-all-rpcs.c
+@@ -24,7 +24,7 @@
+ void
+ ports_resume_all_rpcs ()
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ assert (_ports_flags & _PORTS_INHIBITED);
+ _ports_flags &= ~_PORTS_INHIBITED;
+ if (_ports_flags & _PORTS_BLOCKED)
+@@ -32,5 +32,5 @@ ports_resume_all_rpcs ()
+ _ports_flags &= ~_PORTS_BLOCKED;
+ pthread_cond_broadcast (&_ports_block);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/resume-bucket-rpcs.c b/libports/resume-bucket-rpcs.c
+index cf4db91..1078dac 100644
+--- a/libports/resume-bucket-rpcs.c
++++ b/libports/resume-bucket-rpcs.c
+@@ -24,7 +24,7 @@
+ void
+ ports_resume_bucket_rpcs (struct port_bucket *bucket)
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ assert (bucket->flags & PORT_BUCKET_INHIBITED);
+ bucket->flags &= ~PORT_BUCKET_INHIBITED;
+ if (bucket->flags & PORT_BUCKET_BLOCKED)
+@@ -32,5 +32,5 @@ ports_resume_bucket_rpcs (struct port_bucket *bucket)
+ bucket->flags &= ~PORT_BUCKET_BLOCKED;
+ pthread_cond_broadcast (&_ports_block);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/resume-class-rpcs.c b/libports/resume-class-rpcs.c
+index 60a2b12..00ec7de 100644
+--- a/libports/resume-class-rpcs.c
++++ b/libports/resume-class-rpcs.c
+@@ -24,7 +24,7 @@
+ void
+ ports_resume_class_rpcs (struct port_class *class)
+ {
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+ assert (class->flags & PORT_CLASS_INHIBITED);
+ class->flags &= ~PORT_CLASS_INHIBITED;
+ if (class->flags & PORT_CLASS_BLOCKED)
+@@ -32,5 +32,5 @@ ports_resume_class_rpcs (struct port_class *class)
+ class->flags &= ~PORT_CLASS_BLOCKED;
+ pthread_cond_broadcast (&_ports_block);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/resume-port-rpcs.c b/libports/resume-port-rpcs.c
+index 6d71ab5..845c6f1 100644
+--- a/libports/resume-port-rpcs.c
++++ b/libports/resume-port-rpcs.c
+@@ -25,9 +25,9 @@ void
+ ports_resume_port_rpcs (void *portstruct)
+ {
+ struct port_info *pi = portstruct;
+-
+- pthread_mutex_lock (&_ports_lock);
+-
++
++ pthread_mutex_lock (&_ports_global_lock);
++
+ assert (pi->flags & PORT_INHIBITED);
+ pi->flags &= ~PORT_INHIBITED;
+ if (pi->flags & PORT_BLOCKED)
+@@ -35,5 +35,5 @@ ports_resume_port_rpcs (void *portstruct)
+ pi->flags &= ~PORT_BLOCKED;
+ pthread_cond_broadcast (&_ports_block);
+ }
+- pthread_mutex_unlock (&_ports_lock);
++ pthread_mutex_unlock (&_ports_global_lock);
+ }
+diff --git a/libports/transfer-right.c b/libports/transfer-right.c
+index f4e0c86..01c08e9 100644
+--- a/libports/transfer-right.c
++++ b/libports/transfer-right.c
+@@ -35,13 +35,15 @@ ports_transfer_right (void *tostruct,
+ int hassendrights = 0;
+ error_t err;
+
+- pthread_mutex_lock (&_ports_lock);
++ pthread_mutex_lock (&_ports_global_lock);
+
+ /* Fetch the port in FROMPI and clear its use */
+ port = frompi->port_right;
+ if (port != MACH_PORT_NULL)
+ {
++ pthread_mutex_lock (&frompi->bucket->lock);
+ hurd_ihash_locp_remove (&frompi->bucket->htable, frompi->hentry);
++ pthread_mutex_unlock (&frompi->bucket->lock);
+ frompi->port_right = MACH_PORT_NULL;
+ if (frompi->flags & PORT_HAS_SENDRIGHTS)
+ {
+@@ -54,7 +56,9 @@ ports_transfer_right (void *tostruct,
+ /* Destroy the existing right in TOPI. */
+ if (topi->port_right != MACH_PORT_NULL)
+ {
++ pthread_mutex_lock (&topi->bucket->lock);
+ hurd_ihash_locp_remove (&topi->bucket->htable, topi->hentry);
++ pthread_mutex_unlock (&topi->bucket->lock);
+ err = mach_port_mod_refs (mach_task_self (), topi->port_right,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ assert_perror (err);
+@@ -74,10 +78,14 @@ ports_transfer_right (void *tostruct,
+ topi->port_right = port;
+ topi->cancel_threshold = frompi->cancel_threshold;
+ topi->mscount = frompi->mscount;
+-
++
++ pthread_mutex_unlock (&_ports_global_lock);
++
+ if (port)
+ {
++ pthread_mutex_lock (&topi->bucket->lock);
+ err = hurd_ihash_add (&topi->bucket->htable, port, topi);
++ pthread_mutex_unlock (&topi->bucket->lock);
+ assert_perror (err);
+ if (topi->bucket != frompi->bucket)
+ {
+@@ -86,9 +94,7 @@ ports_transfer_right (void *tostruct,
+ assert_perror (err);
+ }
+ }
+-
+- pthread_mutex_unlock (&_ports_lock);
+-
++
+ /* Take care of any lowered reference counts. */
+ if (dereffrompi)
+ ports_port_deref (frompi);
diff --git a/debian/patches/series b/debian/patches/series
index bc5c48b1..14ca54d7 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -47,3 +47,4 @@ fatfs-two-pagers.patch
libpager-singlethreaded.patch
libpager-drop-seqnos.patch
libports-lockless-refcounting.patch
+libports-per-bucket-hashtable.patch