aboutsummaryrefslogtreecommitdiff
path: root/libports/transfer-right.c
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-03 03:53:41 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-09-29 17:03:57 +0200
commitb2ae574d39adfe283c61a3ec0c766e8780f345af (patch)
tree994d77346507f28b621a4a573f87f1f1e890e097 /libports/transfer-right.c
parent02c47da17b716bfff20bfafe2d5958b2b720ff49 (diff)
downloadhurd-b2ae574d39adfe283c61a3ec0c766e8780f345af.tar.gz
hurd-b2ae574d39adfe283c61a3ec0c766e8780f345af.tar.bz2
hurd-b2ae574d39adfe283c61a3ec0c766e8780f345af.zip
libports: use a global hash table for the lookups
Previously, libports used a hash table per port bucket. This makes looking up a port difficult if one does not know the port bucket, as one has to iterate over all buckets and do a hash table lookup each. Having to iterate over the buckets makes it necessary to keep a list of all buckets, which has to be updated and protected by a lock as well. Also, the current code in _ports_bucket_class_iterate iterates over the hash table associated with the bucket given. When ports_class_iterate calls this common function, it obtains a reference to the bucket from one of the ports in the given class. This will not work if a class contains ports in different port buckets. This limitation is not documented as far as I can see. Again, having to maintain this list has its cost and requires serialization. Use a global hash table for lookups instead. Keep the per-bucket hash tables for efficient iteration over buckets. Furthermore, serialize access to all hash tables using a separate lock. Remove the linked lists of all buckets and all ports in a class. * libports/bucket-iterate.c (ports_bucket_iterate): Acquire _ports_htable_lock. Also, generalize ports_bucket_iterate so that it takes a pointer to a hash table as first argument. (ports_bucket_iterate): Ajust call to former function accordingly. * libports/class-iterate.c (ports_class_iterate): Just call the generalized _ports_bucket_class_iterate with the global hash table as argument. * libports/ports.h (struct port_info): Remove the port class links. (struct port_bucket): Remove the hash table, and the all buckets link. (_ports_all_buckets): Remove declaration. (_ports_htable): New global hash table. (_ports_htable_lock): Protected by this lock. * libports/claim-right.c: Adjust accordingly. * libports/complete-deallocate.c: Likewise. * libports/create-bucket.c: Likewise. * libports/create-class.c: Likewise. * libports/create-internal.c: Likewise. * libports/destroy-right.c: Likewise. * libports/import-port.c: Likewise. * libports/lookup-port.c: Likewise. * libports/reallocate-from-external.c: Likewise. * libports/reallocate-port.c: Likewise. * libports/transfer-right.c: Likewise. * libports/inhibit-all-rpcs.c: Iterate over the hash table. * libports/inhibit-bucket-rpcs.c: Likewise, but filter using bucket. * libports/inhibit-class-rpcs.c: Likewise, but filter using class. * libports/init.c (_ports_htable): Initialize. (_ports_htable_lock): Likewise.
Diffstat (limited to 'libports/transfer-right.c')
-rw-r--r--libports/transfer-right.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/libports/transfer-right.c b/libports/transfer-right.c
index 72488a99..3f482905 100644
--- a/libports/transfer-right.c
+++ b/libports/transfer-right.c
@@ -41,7 +41,10 @@ ports_transfer_right (void *tostruct,
port = frompi->port_right;
if (port != MACH_PORT_NULL)
{
+ pthread_rwlock_wrlock (&_ports_htable_lock);
+ hurd_ihash_locp_remove (&_ports_htable, frompi->ports_htable_entry);
hurd_ihash_locp_remove (&frompi->bucket->htable, frompi->hentry);
+ pthread_rwlock_unlock (&_ports_htable_lock);
frompi->port_right = MACH_PORT_NULL;
if (frompi->flags & PORT_HAS_SENDRIGHTS)
{
@@ -54,7 +57,10 @@ ports_transfer_right (void *tostruct,
/* Destroy the existing right in TOPI. */
if (topi->port_right != MACH_PORT_NULL)
{
+ pthread_rwlock_wrlock (&_ports_htable_lock);
+ hurd_ihash_locp_remove (&_ports_htable, topi->ports_htable_entry);
hurd_ihash_locp_remove (&topi->bucket->htable, topi->hentry);
+ pthread_rwlock_unlock (&_ports_htable_lock);
err = mach_port_mod_refs (mach_task_self (), topi->port_right,
MACH_PORT_RIGHT_RECEIVE, -1);
assert_perror (err);
@@ -74,10 +80,16 @@ ports_transfer_right (void *tostruct,
topi->port_right = port;
topi->cancel_threshold = frompi->cancel_threshold;
topi->mscount = frompi->mscount;
-
+
+ pthread_mutex_unlock (&_ports_lock);
+
if (port)
{
+ pthread_rwlock_wrlock (&_ports_htable_lock);
+ err = hurd_ihash_add (&_ports_htable, port, topi);
+ assert_perror (err);
err = hurd_ihash_add (&topi->bucket->htable, port, topi);
+ pthread_rwlock_unlock (&_ports_htable_lock);
assert_perror (err);
if (topi->bucket != frompi->bucket)
{
@@ -86,9 +98,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);