From b2ae574d39adfe283c61a3ec0c766e8780f345af Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Sat, 3 May 2014 03:53:41 +0200 Subject: 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. --- libports/bucket-iterate.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'libports/bucket-iterate.c') diff --git a/libports/bucket-iterate.c b/libports/bucket-iterate.c index 2d1b00d8..b9ef0eb7 100644 --- a/libports/bucket-iterate.c +++ b/libports/bucket-iterate.c @@ -25,7 +25,7 @@ /* Internal entrypoint for both ports_bucket_iterate and ports_class_iterate. If CLASS is non-null, call FUN only for ports in that class. */ error_t -_ports_bucket_class_iterate (struct port_bucket *bucket, +_ports_bucket_class_iterate (struct hurd_ihash *ht, struct port_class *class, error_t (*fun)(void *)) { @@ -36,23 +36,26 @@ _ports_bucket_class_iterate (struct port_bucket *bucket, error_t err; pthread_mutex_lock (&_ports_lock); + pthread_rwlock_rdlock (&_ports_htable_lock); - if (bucket->htable.nr_items == 0) + if (ht->nr_items == 0) { + pthread_rwlock_unlock (&_ports_htable_lock); pthread_mutex_unlock (&_ports_lock); return 0; } - nr_items = bucket->htable.nr_items; + nr_items = ht->nr_items; p = malloc (nr_items * sizeof *p); if (p == NULL) { + pthread_rwlock_unlock (&_ports_htable_lock); pthread_mutex_unlock (&_ports_lock); return ENOMEM; } n = 0; - HURD_IHASH_ITERATE (&bucket->htable, arg) + HURD_IHASH_ITERATE (ht, arg) { struct port_info *const pi = arg; @@ -63,6 +66,7 @@ _ports_bucket_class_iterate (struct port_bucket *bucket, n++; } } + pthread_rwlock_unlock (&_ports_htable_lock); pthread_mutex_unlock (&_ports_lock); if (n != 0 && n != nr_items) @@ -89,5 +93,5 @@ error_t ports_bucket_iterate (struct port_bucket *bucket, error_t (*fun)(void *)) { - return _ports_bucket_class_iterate (bucket, 0, fun); + return _ports_bucket_class_iterate (&bucket->htable, NULL, fun); } -- cgit v1.2.3