commit 60e4ccf4cfd4e67fa7b0a51d95d87a1791e34788 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 9230b1f..5a6a56b 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; } @@ -47,7 +47,7 @@ _ports_bucket_class_iterate (struct port_bucket *bucket, p = malloc (nr_items * sizeof *p); if (p == NULL) { - pthread_mutex_unlock (&_ports_lock); + pthread_mutex_unlock (&bucket->lock); return ENOMEM; } @@ -63,7 +63,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..6fe68f5 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 (&_ports_global_lock); if (pi->port_right == MACH_PORT_NULL) { - pthread_mutex_unlock (&_ports_lock); + pthread_mutex_unlock (&_ports_global_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 (&_ports_global_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);