diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-16 13:25:36 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-16 13:25:36 +0200 |
commit | b39a4dca84393407806cb8a8b0630db1993bc38e (patch) | |
tree | 45ccb3ad2877d05d7f28bef9a31827dd2b11d78f | |
parent | 1302c1f89d1c4b0980e445c06102b38971eca3a7 (diff) |
drop old patch series
17 files changed, 0 insertions, 3479 deletions
diff --git a/debian/patches/0001-libihash-fix-typo.patch b/debian/patches/0001-libihash-fix-typo.patch deleted file mode 100644 index 0ce59408..00000000 --- a/debian/patches/0001-libihash-fix-typo.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6748c1a767337587a723695f294edf8c567aff79 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Thu, 15 May 2014 17:57:10 +0200 -Subject: [PATCH 01/16] libihash: fix typo - -* libihash/ihash.c (hurd_ihash_add): Fix typo. ---- - libihash/ihash.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libihash/ihash.c b/libihash/ihash.c -index 151c1a7..f20ba61 100644 ---- a/libihash/ihash.c -+++ b/libihash/ihash.c -@@ -302,7 +302,7 @@ hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t item) - else - ht->size <<= 1; - -- /* calloc() will initialize all values to _HURD_IHASH_EMPTY implicitely. */ -+ /* calloc() will initialize all values to _HURD_IHASH_EMPTY implicitly. */ - ht->items = calloc (ht->size, sizeof (struct _hurd_ihash_item)); - - if (ht->items == NULL) --- -2.0.0.rc0 - diff --git a/debian/patches/0002-libihash-add-hurd_ihash_get_load.patch b/debian/patches/0002-libihash-add-hurd_ihash_get_load.patch deleted file mode 100644 index d6b17098..00000000 --- a/debian/patches/0002-libihash-add-hurd_ihash_get_load.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 27dcb999977533fadd4c8c370c472bf9e31fd4c7 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Thu, 15 May 2014 13:53:16 +0200 -Subject: [PATCH 02/16] libihash: add hurd_ihash_get_load - -* libihash/ihash.c (hurd_ihash_add): Move the code computing the load -factor of the hash table... -* libihash/ihash.h (hurd_ihash_get_load): ... here, together with the -comment describing the method and the rationale for chosing binary -percent. ---- - libihash/ihash.c | 20 ++------------------ - libihash/ihash.h | 24 ++++++++++++++++++++++++ - 2 files changed, 26 insertions(+), 18 deletions(-) - -diff --git a/libihash/ihash.c b/libihash/ihash.c -index f20ba61..4d9cc18 100644 ---- a/libihash/ihash.c -+++ b/libihash/ihash.c -@@ -273,24 +273,8 @@ hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t item) - - if (ht->size) - { -- /* Only fill the hash table up to its maximum load factor given -- as "binary percent", where 128b% corresponds to 100%. As the -- size is always a power of two, and 128 is also, the quotient -- of both is also a power of two. Therefore, we can use bit -- shifts to scale the number of items. -- -- load = nr_items * 128 / size -- = nr_items * 2^{log2 (128) - log2 (size)} -- = nr_items >> (log2 (size) - log2 (128)) -- -- if size >= 128 -- = nr_items << (log2 (128) - log2 (size)) -- -- otherwise -- */ -- int d = __builtin_ctzl (ht->size) - 7; -- unsigned int load = d >= 0 -- ? ht->nr_items >> d -- : ht->nr_items << -d; -- if (load <= ht->max_load) -+ /* Only fill the hash table up to its maximum load factor. */ -+ if (hurd_ihash_get_load (ht) <= ht->max_load) - if (add_one (ht, key, item)) - return 0; - } -diff --git a/libihash/ihash.h b/libihash/ihash.h -index 809166f..345630d 100644 ---- a/libihash/ihash.h -+++ b/libihash/ihash.h -@@ -160,6 +160,30 @@ void hurd_ihash_set_cleanup (hurd_ihash_t ht, hurd_ihash_cleanup_t cleanup, - void hurd_ihash_set_max_load (hurd_ihash_t ht, unsigned int max_load); - - -+/* Get the current load factor of HT in binary percent, where 128b% -+ corresponds to 100%. The reason we do this is that it is so -+ efficient to compute: -+ -+ As the size is always a power of two, and 128 is also, the quotient -+ of both is also a power of two. Therefore, we can use bit shifts -+ to scale the number of items. -+ -+ load = nr_items * 128 / size -+ = nr_items * 2^{log2 (128) - log2 (size)} -+ = nr_items >> (log2 (size) - log2 (128)) -+ -- if size >= 128 -+ = nr_items << (log2 (128) - log2 (size)) -+ -- otherwise -+ -+ If you want to convert this to percent, just divide by 1.28. */ -+static inline unsigned int -+hurd_ihash_get_load (hurd_ihash_t ht) -+{ -+ int d = __builtin_ctzl (ht->size) - 7; -+ return d >= 0 ? ht->nr_items >> d : ht->nr_items << -d; -+} -+ -+ - /* Add ITEM to the hash table HT under the key KEY. If there already - is an item under this key, call the cleanup function (if any) for - it before overriding the value. If a memory allocation error --- -2.0.0.rc0 - diff --git a/debian/patches/0003-libihash-add-hurd_ihash_value_valid.patch b/debian/patches/0003-libihash-add-hurd_ihash_value_valid.patch deleted file mode 100644 index b289435f..00000000 --- a/debian/patches/0003-libihash-add-hurd_ihash_value_valid.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 4fd74e766ae0992f08b525cd935fb7c5bbf6e24c Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Thu, 15 May 2014 17:55:45 +0200 -Subject: [PATCH 03/16] libihash: add hurd_ihash_value_valid - -* libihash/ihash.h (hurd_ihash_value_valid): New function. -* libihash/ihash.c (index_empty): Use hurd_ihash_value_valid. ---- - libihash/ihash.c | 3 +-- - libihash/ihash.h | 7 +++++++ - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/libihash/ihash.c b/libihash/ihash.c -index 4d9cc18..5b7b542 100644 ---- a/libihash/ihash.c -+++ b/libihash/ihash.c -@@ -50,8 +50,7 @@ murmur3_mix32 (uint32_t h, unsigned int bits) - static inline int - index_empty (hurd_ihash_t ht, unsigned int idx) - { -- return ht->items[idx].value == _HURD_IHASH_EMPTY -- || ht->items[idx].value == _HURD_IHASH_DELETED; -+ return ! hurd_ihash_value_valid (ht->items[idx].value); - } - - -diff --git a/libihash/ihash.h b/libihash/ihash.h -index 345630d..394bcf9 100644 ---- a/libihash/ihash.h -+++ b/libihash/ihash.h -@@ -41,6 +41,13 @@ typedef void *hurd_ihash_value_t; - #define _HURD_IHASH_EMPTY ((hurd_ihash_value_t) 0) - #define _HURD_IHASH_DELETED ((hurd_ihash_value_t) -1) - -+/* Test if VALUE is valid. */ -+static inline int -+hurd_ihash_value_valid (hurd_ihash_value_t value) -+{ -+ return value != _HURD_IHASH_EMPTY && value != _HURD_IHASH_DELETED; -+} -+ - /* The type of integer we want to use for the keys. */ - typedef uintptr_t hurd_ihash_key_t; - --- -2.0.0.rc0 - diff --git a/debian/patches/0004-libihash-optimize-lookup-or-insert-operations.patch b/debian/patches/0004-libihash-optimize-lookup-or-insert-operations.patch deleted file mode 100644 index 2b537469..00000000 --- a/debian/patches/0004-libihash-optimize-lookup-or-insert-operations.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 64b064dacb5fb06bd0901a53dd6d9402c4c9195a Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Wed, 14 May 2014 16:24:21 +0200 -Subject: [PATCH 04/16] libihash: optimize lookup-or-insert operations - -If libihash is used to implement a cache, a insertion is always -preceeded by a lookup. hurd_ihash_add has to do the lookup again. - -Provide a new pair of functions, hurd_ihash_locp_add and -hurd_ihash_locp_find, that can be used in combination to avoid the -second lookup. - -* libihash/ihash.c (hurd_ihash_locp_add): New function using a -location pointer... -(hurd_ihash_locp_find): ... that has been returned by this function if -the lookup failed. -* libihash/ihash.h (hurd_ihash_locp_add): New declaration. -(hurd_ihash_locp_find): Likewise. -(hurd_ihash_locp_value): New function. - -fixup_ihash_locp_add ---- - libihash/ihash.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- - libihash/ihash.h | 52 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 129 insertions(+), 1 deletion(-) - -diff --git a/libihash/ihash.c b/libihash/ihash.c -index 5b7b542..167c872 100644 ---- a/libihash/ihash.c -+++ b/libihash/ihash.c -@@ -258,7 +258,54 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value) - return 0; - } - -- -+ -+/* Add VALUE to the hash table HT under the key KEY at LOCP. If there -+ already is an item under this key, call the cleanup function (if -+ any) for it before overriding the value. This function is faster -+ than hurd_ihash_add. -+ -+ If LOCP is NULL, fall back to hurd_ihash_add. Otherwise, LOCP must -+ be valid and may either be obtained from hurd_ihash_locp_find, or -+ from an item that is currently in the hash table. If an item is -+ replaced, KEY must match the key of the previous item. -+ -+ If a memory allocation error occurs, ENOMEM is returned, otherwise -+ 0. */ -+error_t -+hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp, -+ hurd_ihash_key_t key, hurd_ihash_value_t value) -+{ -+ struct _hurd_ihash_item *item = (struct _hurd_ihash_item *) locp; -+ -+ /* In case of complications, fall back to hurd_ihash_add. */ -+ if (ht->size == 0 -+ || item == NULL -+ || item->value == _HURD_IHASH_DELETED -+ || hurd_ihash_get_load (ht) > ht->max_load) -+ return hurd_ihash_add (ht, key, value); -+ -+ if (item->value == _HURD_IHASH_EMPTY) -+ { -+ item->key = key; -+ ht->nr_items += 1; -+ } -+ else -+ { -+ assert (item->key == key); -+ if (ht->cleanup) -+ (*ht->cleanup) (locp, ht->cleanup_data); -+ } -+ -+ item->value = value; -+ -+ if (ht->locp_offset != HURD_IHASH_NO_LOCP) -+ *((hurd_ihash_locp_t *) (((char *) value) + ht->locp_offset)) -+ = locp; -+ -+ return 0; -+} -+ -+ - /* Add ITEM to the hash table HT under the key KEY. If there already - is an item under this key, call the cleanup function (if any) for - it before overriding the value. If a memory allocation error -@@ -327,6 +374,35 @@ hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key) - } - } - -+/* Find the item in the hash table HT with key KEY. If it is found, -+ return the location of its slot in the hash table. If it is not -+ found, this function may still return a location. -+ -+ This location pointer can always be safely accessed using -+ hurd_ihash_locp_value. If the lookup is successful, -+ hurd_ihash_locp_value will return the value related to KEY. -+ -+ If the lookup is successful, the returned location can be used with -+ hurd_ihash_locp_add to update the item, and with -+ hurd_ihash_locp_remove to remove it. -+ -+ If the lookup is not successful, the returned location can be used -+ with hurd_ihash_locp_add to add the item. -+ -+ Note that returned location is only valid until the next insertion -+ or deletion. */ -+hurd_ihash_locp_t -+hurd_ihash_locp_find (hurd_ihash_t ht, hurd_ihash_key_t key) -+{ -+ int idx; -+ -+ if (ht->size == 0) -+ return NULL; -+ -+ idx = find_index (ht, key); -+ return &ht->items[idx].value; -+} -+ - - /* Remove the entry with the key KEY from the hash table HT. If such - an entry was found and removed, 1 is returned, otherwise 0. */ -diff --git a/libihash/ihash.h b/libihash/ihash.h -index 394bcf9..847d596 100644 ---- a/libihash/ihash.h -+++ b/libihash/ihash.h -@@ -26,6 +26,7 @@ - #include <sys/types.h> - #include <limits.h> - #include <stdint.h> -+#include <stddef.h> - - - /* The type of the values corresponding to the keys. Must be a -@@ -198,10 +199,61 @@ hurd_ihash_get_load (hurd_ihash_t ht) - error_t hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key_t key, - hurd_ihash_value_t item); - -+/* Add VALUE to the hash table HT under the key KEY at LOCP. If there -+ already is an item under this key, call the cleanup function (if -+ any) for it before overriding the value. This function is faster -+ than hurd_ihash_add. -+ -+ If LOCP is NULL, fall back to hurd_ihash_add. Otherwise, LOCP must -+ be valid and may either be obtained from hurd_ihash_locp_find, or -+ from an item that is currently in the hash table. If an item is -+ replaced, KEY must match the key of the previous item. -+ -+ If a memory allocation error occurs, ENOMEM is returned, otherwise -+ 0. */ -+error_t hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp, -+ hurd_ihash_key_t key, hurd_ihash_value_t value); -+ - /* Find and return the item in the hash table HT with key KEY, or NULL - if it doesn't exist. */ - hurd_ihash_value_t hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key); - -+/* Find the item in the hash table HT with key KEY. If it is found, -+ return the location of its slot in the hash table. If it is not -+ found, this function may still return a location. -+ -+ This location pointer can always be safely accessed using -+ hurd_ihash_locp_value. If the lookup is successful, -+ hurd_ihash_locp_value will return the value related to KEY. -+ -+ If the lookup is successful, the returned location can be used with -+ hurd_ihash_locp_add to update the item, and with -+ hurd_ihash_locp_remove to remove it. -+ -+ If the lookup is not successful, the returned location can be used -+ with hurd_ihash_locp_add to add the item. -+ -+ Note that returned location is only valid until the next insertion -+ or deletion. */ -+hurd_ihash_locp_t hurd_ihash_locp_find (hurd_ihash_t ht, -+ hurd_ihash_key_t key); -+ -+/* Given an hash table bucket location LOCP, return the value stored -+ there, or NULL if it is empty. */ -+static inline void * -+hurd_ihash_locp_value (hurd_ihash_locp_t locp) -+{ -+ struct _hurd_ihash_item *item = (struct _hurd_ihash_item *) locp; -+ -+ if (locp == NULL) -+ return NULL; -+ -+ if (hurd_ihash_value_valid (item->value)) -+ return item->value; -+ -+ return NULL; -+} -+ - /* Iterate over all elements in the hash table. You use this macro - with a block, for example like this: - --- -2.0.0.rc0 - diff --git a/debian/patches/0005-include-add-lock-less-reference-counting-primitives.patch b/debian/patches/0005-include-add-lock-less-reference-counting-primitives.patch deleted file mode 100644 index 4a9db22e..00000000 --- a/debian/patches/0005-include-add-lock-less-reference-counting-primitives.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 2cd6446f734855f321db93bf2331d2d4ef8be36b Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 6 May 2014 19:52:04 +0200 -Subject: [PATCH 05/16] include: add lock-less reference counting primitives - -* include/refcount.h: New file. ---- - include/refcount.h | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 263 insertions(+) - create mode 100644 include/refcount.h - -diff --git a/include/refcount.h b/include/refcount.h -new file mode 100644 -index 0000000..eedefa8 ---- /dev/null -+++ b/include/refcount.h -@@ -0,0 +1,263 @@ -+/* Lock-less reference counting primitives -+ -+ Copyright (C) 2014 Free Software Foundation, Inc. -+ -+ Written by Justus Winter <4winter@informatik.uni-hamburg.de> -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd 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. -+ -+ The GNU Hurd 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ -+ -+#ifndef _HURD_REFCOUNT_H_ -+#define _HURD_REFCOUNT_H_ -+ -+#include <assert.h> -+#include <stdint.h> -+ -+/* Simple reference counting. */ -+ -+/* An opaque type. You must not access these values directly. */ -+typedef unsigned int refcount_t; -+ -+/* Initialize REF with REFERENCES. */ -+static inline void -+refcount_init (refcount_t *ref, unsigned int references) -+{ -+ *ref = references; -+} -+ -+/* Increment REF. Return the result of the operation. This function -+ uses atomic operations. It is not required to serialize calls to -+ this function. */ -+static inline unsigned int -+refcount_ref (refcount_t *ref) -+{ -+ unsigned int r; -+ r = __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED); -+ assert (r != UINT_MAX || !"refcount overflowed!"); -+ return r; -+} -+ -+/* Decrement REF. Return the result of the operation. This function -+ uses atomic operations. It is not required to serialize calls to -+ this function. */ -+static inline unsigned int -+refcount_deref (refcount_t *ref) -+{ -+ unsigned int r; -+ r = __atomic_sub_fetch (ref, 1, __ATOMIC_RELAXED); -+ assert (r != UINT_MAX || !"refcount underflowed!"); -+ return r; -+} -+ -+/* Return REF. This function uses atomic operations. It is not -+ required to serialize calls to this function. */ -+static inline unsigned int -+refcount_references (refcount_t *ref) -+{ -+ return __atomic_load_n (ref, __ATOMIC_RELAXED); -+} -+ -+/* Reference counting with weak references. */ -+ -+/* An opaque type. You must not access these values directly. */ -+typedef union _references refcounts_t; -+ -+/* Instead, the functions manipulating refcounts_t values write the -+ results into this kind of objects. */ -+struct references { -+ /* We chose the layout of this struct so that when it is used in the -+ union _references, the hard reference counts occupy the least -+ significant bits. We rely on this layout for atomic promotion -+ and demotion of references. See refcounts_promote and -+ refcounts_demote for details. */ -+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -+ uint32_t hard; -+ uint32_t weak; -+#else -+ uint32_t weak; -+ uint32_t hard; -+#endif -+}; -+ -+/* We use a union to convert struct reference values to uint64_t which -+ we can manipulate atomically. While this behavior is not -+ guaranteed by the C standard, it is supported by all major -+ compilers. */ -+union _references { -+ struct references references; -+ uint64_t value; -+}; -+ -+/* Initialize REF with HARD and WEAK references. */ -+static inline void -+refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak) -+{ -+ ref->references = (struct references) { .hard = hard, .weak = weak }; -+} -+ -+/* Increment the hard reference count of REF. If RESULT is not NULL, -+ the result of the operation is written there. This function uses -+ atomic operations. It is not required to serialize calls to this -+ function. */ -+static inline void -+refcounts_ref (refcounts_t *ref, struct references *result) -+{ -+ const union _references op = { .references = { .hard = 1 } }; -+ union _references r; -+ r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); -+ assert (r.references.hard != UINT32_MAX || !"refcount overflowed!"); -+ if (result) -+ *result = r.references; -+} -+ -+/* Decrement the hard reference count of REF. If RESULT is not NULL, -+ the result of the operation is written there. This function uses -+ atomic operations. It is not required to serialize calls to this -+ function. */ -+static inline void -+refcounts_deref (refcounts_t *ref, struct references *result) -+{ -+ const union _references op = { .references = { .hard = 1 } }; -+ union _references r; -+ r.value = __atomic_sub_fetch (&ref->value, op.value, __ATOMIC_RELAXED); -+ assert (r.references.hard != UINT32_MAX || !"refcount underflowed!"); -+ if (result) -+ *result = r.references; -+} -+ -+/* Promote a weak reference to a hard reference. If RESULT is not -+ NULL, the result of the operation is written there. This function -+ uses atomic operations. It is not required to serialize calls to -+ this function. */ -+static inline void -+refcounts_promote (refcounts_t *ref, struct references *result) -+{ -+ /* To promote a hard reference, we need to atomically subtract 1 from -+ the weak reference count, and add 1 to the hard reference -+ count. -+ -+ We can subtract by 1 by adding the two's complement of 1 = ~0 to -+ a fixed-width value, discarding the overflow. -+ -+ We do the same in our uint64_t value, but we have chosen the -+ layout of struct references so that when it is used in the union -+ _references, the weak reference counts occupy the most -+ significant bits. When we add ~0 to the weak references, the -+ overflow will be discarded as unsigned arithmetic is modulo 2^n. -+ So we just add a hard reference. In combination, this is the -+ desired operation. */ -+ const union _references op = -+ { .references = { .weak = ~0, .hard = 1} }; -+ union _references r; -+ r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); -+ assert (r.references.hard != UINT32_MAX || !"refcount overflowed!"); -+ assert (r.references.weak != UINT32_MAX || !"refcount underflowed!"); -+ if (result) -+ *result = r.references; -+} -+ -+/* Demote a hard reference to a weak reference. If RESULT is not -+ NULL, the result of the operation is written there. This function -+ uses atomic operations. It is not required to serialize calls to -+ this function. */ -+static inline void -+refcounts_demote (refcounts_t *ref, struct references *result) -+{ -+ /* To demote a hard reference, we need to atomically subtract 1 from -+ the hard reference count, and add 1 to the weak reference -+ count. -+ -+ We can subtract by 1 by adding the two's complement of 1 = ~0 to -+ a fixed-width value, discarding the overflow. -+ -+ We do the same in our uint64_t value, but we have chosen the -+ layout of struct references so that when it is used in the union -+ _references, the hard reference counts occupy the least -+ significant bits. When we add ~0 to the hard references, it will -+ overflow into the weak references. This is the desired -+ operation. */ -+ const union _references op = { .references = { .hard = ~0 } }; -+ union _references r; -+ r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); -+ assert (r.references.hard != UINT32_MAX || !"refcount underflowed!"); -+ assert (r.references.weak != UINT32_MAX || !"refcount overflowed!"); -+ if (result) -+ *result = r.references; -+} -+ -+/* Increment the weak reference count of REF. If RESULT is not NULL, -+ the result of the operation is written there. This function uses -+ atomic operations. It is not required to serialize calls to this -+ function. */ -+static inline void -+refcounts_ref_weak (refcounts_t *ref, struct references *result) -+{ -+ const union _references op = { .references = { .weak = 1 } }; -+ union _references r; -+ r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); -+ assert (r.references.weak != UINT32_MAX || !"refcount overflowed!"); -+ if (result) -+ *result = r.references; -+} -+ -+/* Decrement the weak reference count of REF. If RESULT is not NULL, -+ the result of the operation is written there. This function uses -+ atomic operations. It is not required to serialize calls to this -+ function. */ -+static inline void -+refcounts_deref_weak (refcounts_t *ref, struct references *result) -+{ -+ const union _references op = { .references = { .weak = 1 } }; -+ union _references r; -+ r.value = __atomic_sub_fetch (&ref->value, op.value, __ATOMIC_RELAXED); -+ assert (r.references.weak != UINT32_MAX || !"refcount underflowed!"); -+ if (result) -+ *result = r.references; -+} -+ -+/* Store the current reference counts of REF in RESULT. This function -+ uses atomic operations. It is not required to serialize calls to -+ this function. */ -+static inline void -+refcounts_references (refcounts_t *ref, struct references *result) -+{ -+ union _references r; -+ r.value =__atomic_load_n (&ref->value, __ATOMIC_RELAXED); -+ *result = r.references; -+} -+ -+/* Return the hard reference count of REF. This function uses atomic -+ operations. It is not required to serialize calls to this -+ function. */ -+static inline uint32_t -+refcounts_hard_references (refcounts_t *ref) -+{ -+ struct references result; -+ refcounts_references (ref, &result); -+ return result.hard; -+} -+ -+/* Return the weak reference count of REF. This function uses atomic -+ operations. It is not required to serialize calls to this -+ function. */ -+static inline uint32_t -+refcounts_weak_references (refcounts_t *ref) -+{ -+ struct references result; -+ refcounts_references (ref, &result); -+ return result.weak; -+} -+ -+#endif /* _HURD_REFCOUNT_H_ */ --- -2.0.0.rc0 - diff --git a/debian/patches/0006-libdiskfs-lock-less-reference-counting-for-peropen-o.patch b/debian/patches/0006-libdiskfs-lock-less-reference-counting-for-peropen-o.patch deleted file mode 100644 index 4d8a6227..00000000 --- a/debian/patches/0006-libdiskfs-lock-less-reference-counting-for-peropen-o.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 5a94cdec256306168490ec0e5de5292a9e9ce62d Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 6 May 2014 18:58:10 +0200 -Subject: [PATCH 06/16] libdiskfs: lock-less reference counting for peropen - objects - -* libdiskfs/diskfs.h (struct peropen): Use refcount_t for field refcnt. -* libdiskfs/peropen-make.c (diskfs_make_peropen): Initialize refcnt. -* libdiskfs/peropen-rele.c (diskfs_release_peropen): Adjust accordingly. -* libdiskfs/protid-make.c (diskfs_start_protid): Likewise. Also, the -node must no longer be locked, adjust comment accordingly. -(diskfs_create_protid): Likewise. ---- - libdiskfs/diskfs.h | 7 ++++--- - libdiskfs/peropen-make.c | 2 +- - libdiskfs/peropen-rele.c | 21 ++++++++++----------- - libdiskfs/protid-make.c | 8 ++++---- - 4 files changed, 19 insertions(+), 19 deletions(-) - -diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h -index 8151ddc..ae1a150 100644 ---- a/libdiskfs/diskfs.h -+++ b/libdiskfs/diskfs.h -@@ -28,6 +28,7 @@ - #include <hurd/iohelp.h> - #include <idvec.h> - #include <features.h> -+#include <refcount.h> - - #ifdef DISKFS_DEFINE_EXTERN_INLINE - #define DISKFS_EXTERN_INLINE -@@ -57,7 +58,7 @@ struct peropen - { - int filepointer; - int lock_status; -- int refcnt; -+ refcount_t refcnt; - int openstat; - - struct node *np; -@@ -792,12 +793,12 @@ diskfs_create_node (struct node *dir, const char *name, mode_t mode, - struct dirstat *ds); - - /* Create and return a protid for an existing peropen PO in CRED, -- referring to user USER. The node PO->np must be locked. */ -+ referring to user USER. */ - error_t diskfs_create_protid (struct peropen *po, struct iouser *user, - struct protid **cred); - - /* Build and return in CRED a protid which has no user identification, for -- peropen PO. The node PO->np must be locked. */ -+ peropen PO. */ - error_t diskfs_start_protid (struct peropen *po, struct protid **cred); - - /* Finish building protid CRED started with diskfs_start_protid; -diff --git a/libdiskfs/peropen-make.c b/libdiskfs/peropen-make.c -index eba037f..6d5ca01 100644 ---- a/libdiskfs/peropen-make.c -+++ b/libdiskfs/peropen-make.c -@@ -31,7 +31,7 @@ diskfs_make_peropen (struct node *np, int flags, struct peropen *context, - - po->filepointer = 0; - po->lock_status = LOCK_UN; -- po->refcnt = 0; -+ refcount_init (&po->refcnt, 0); - po->openstat = flags; - po->np = np; - po->path = NULL; -diff --git a/libdiskfs/peropen-rele.c b/libdiskfs/peropen-rele.c -index d3f7492..877137b 100644 ---- a/libdiskfs/peropen-rele.c -+++ b/libdiskfs/peropen-rele.c -@@ -22,13 +22,8 @@ - void - diskfs_release_peropen (struct peropen *po) - { -- pthread_mutex_lock (&po->np->lock); -- -- if (--po->refcnt) -- { -- pthread_mutex_unlock (&po->np->lock); -- return; -- } -+ if (refcount_deref (&po->refcnt) > 0) -+ return; - - if (po->root_parent) - mach_port_deallocate (mach_task_self (), po->root_parent); -@@ -40,10 +35,14 @@ diskfs_release_peropen (struct peropen *po) - mach_port_deallocate (mach_task_self (), po->shadow_root_parent); - - if (po->lock_status != LOCK_UN) -- fshelp_acquire_lock (&po->np->userlock, &po->lock_status, -- &po->np->lock, LOCK_UN); -- -- diskfs_nput (po->np); -+ { -+ pthread_mutex_lock (&po->np->lock); -+ fshelp_acquire_lock (&po->np->userlock, &po->lock_status, -+ &po->np->lock, LOCK_UN); -+ diskfs_nput (po->np); -+ } -+ else -+ diskfs_nrele (po->np); - - free (po->path); - free (po); -diff --git a/libdiskfs/protid-make.c b/libdiskfs/protid-make.c -index b39b92a..22aaa2e 100644 ---- a/libdiskfs/protid-make.c -+++ b/libdiskfs/protid-make.c -@@ -20,7 +20,7 @@ - #include <assert.h> - - /* Build and return in CRED a protid which has no user identification, for -- peropen PO. The node PO->np must be locked. */ -+ peropen PO. */ - error_t - diskfs_start_protid (struct peropen *po, struct protid **cred) - { -@@ -29,7 +29,7 @@ diskfs_start_protid (struct peropen *po, struct protid **cred) - sizeof (struct protid), cred); - if (! err) - { -- po->refcnt++; -+ refcount_ref (&po->refcnt); - (*cred)->po = po; - (*cred)->shared_object = MACH_PORT_NULL; - (*cred)->mapped = 0; -@@ -55,8 +55,8 @@ diskfs_finish_protid (struct protid *cred, struct iouser *user) - assert_perror (err); - } - --/* Create and return a protid for an existing peropen PO in CRED for USER. -- The node PO->np must be locked. */ -+/* Create and return a protid for an existing peropen PO in CRED for -+ USER. */ - error_t - diskfs_create_protid (struct peropen *po, struct iouser *user, - struct protid **cred) --- -2.0.0.rc0 - diff --git a/debian/patches/0007-libtrivfs-lock-less-reference-counting-for-trivfs_pe.patch b/debian/patches/0007-libtrivfs-lock-less-reference-counting-for-trivfs_pe.patch deleted file mode 100644 index fc9bb0e0..00000000 --- a/debian/patches/0007-libtrivfs-lock-less-reference-counting-for-trivfs_pe.patch +++ /dev/null @@ -1,172 +0,0 @@ -From e6ee505ef2d8f1489091a205ebab9e13e6a468cb Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 6 May 2014 19:07:13 +0200 -Subject: [PATCH 07/16] libtrivfs: lock-less reference counting for - trivfs_peropen objects - -* libtrivfs/trivfs.h (struct trivfs_peropen): Use refcount_t for field -refcnt. -(struct trivfs_control): Remove unused field lock. -* libtrivfs/cntl-create.c (trivfs_create_control): Drop the mutex -initialization. -* libtrivfs/io-reauthenticate.c (trivfs_S_io_reauthenticate): Adjust -accordingly. -* libtrivfs/io-restrict-auth.c (trivfs_S_io_restrict_auth): Likewise. -* libtrivfs/open.c (trivfs_open): Initialize refcnt. -* libtrivfs/protid-clean.c (trivfs_clean_protid): Likewise. -* libtrivfs/protid-dup.c (trivfs_protid_dup): Likewise. ---- - libtrivfs/cntl-create.c | 1 - - libtrivfs/io-reauthenticate.c | 5 +---- - libtrivfs/io-restrict-auth.c | 4 +--- - libtrivfs/open.c | 2 +- - libtrivfs/protid-clean.c | 26 +++++++++++++++----------- - libtrivfs/protid-dup.c | 5 +---- - libtrivfs/trivfs.h | 4 ++-- - 7 files changed, 21 insertions(+), 26 deletions(-) - -diff --git a/libtrivfs/cntl-create.c b/libtrivfs/cntl-create.c -index 910daf3..eb9a834 100644 ---- a/libtrivfs/cntl-create.c -+++ b/libtrivfs/cntl-create.c -@@ -85,7 +85,6 @@ trivfs_create_control (mach_port_t underlying, - } - - (*control)->hook = 0; -- pthread_mutex_init (&(*control)->lock, NULL); - } - - out: -diff --git a/libtrivfs/io-reauthenticate.c b/libtrivfs/io-reauthenticate.c -index 7677697..df0ed2e 100644 ---- a/libtrivfs/io-reauthenticate.c -+++ b/libtrivfs/io-reauthenticate.c -@@ -62,11 +62,8 @@ trivfs_S_io_reauthenticate (struct trivfs_protid *cred, - newcred->isroot = 1; - - newcred->hook = cred->hook; -- -- pthread_mutex_lock (&cred->po->cntl->lock); - newcred->po = cred->po; -- newcred->po->refcnt++; -- pthread_mutex_unlock (&cred->po->cntl->lock); -+ refcount_ref (&newcred->po->refcnt); - - do - err = io_restrict_auth (newcred->po->cntl->underlying, &newcred->realnode, -diff --git a/libtrivfs/io-restrict-auth.c b/libtrivfs/io-restrict-auth.c -index 65b4fd6..39670fe 100644 ---- a/libtrivfs/io-restrict-auth.c -+++ b/libtrivfs/io-restrict-auth.c -@@ -110,10 +110,8 @@ trivfs_S_io_restrict_auth (struct trivfs_protid *cred, - } - - newcred->isroot = 0; -- pthread_mutex_lock (&cred->po->cntl->lock); - newcred->po = cred->po; -- newcred->po->refcnt++; -- pthread_mutex_unlock (&cred->po->cntl->lock); -+ refcount_ref (&newcred->po->refcnt); - if (cred->isroot && idvec_contains (user->uids, 0)) - newcred->isroot = 1; - newcred->user = user; -diff --git a/libtrivfs/open.c b/libtrivfs/open.c -index f64d2ff..97e70a1 100644 ---- a/libtrivfs/open.c -+++ b/libtrivfs/open.c -@@ -40,7 +40,7 @@ trivfs_open (struct trivfs_control *cntl, - - ports_port_ref (cntl); - -- po->refcnt = 1; -+ refcount_init (&po->refcnt, 1); - po->cntl = cntl; - po->openmodes = flags; - po->hook = 0; -diff --git a/libtrivfs/protid-clean.c b/libtrivfs/protid-clean.c -index f98da6a..cce736d 100644 ---- a/libtrivfs/protid-clean.c -+++ b/libtrivfs/protid-clean.c -@@ -31,19 +31,23 @@ trivfs_clean_protid (void *arg) - (*trivfs_protid_destroy_hook) (cred); - - /* If we hold the only reference to the peropen, try to get rid of it. */ -- pthread_mutex_lock (&cntl->lock); -- if (cred->po->refcnt == 1 && trivfs_peropen_destroy_hook) -+ if (refcount_deref (&cred->po->refcnt) == 0) - { -- pthread_mutex_unlock (&cntl->lock); -- (*trivfs_peropen_destroy_hook) (cred->po); -- pthread_mutex_lock (&cntl->lock); -+ if (trivfs_peropen_destroy_hook) -+ { -+ /* Reaquire a reference while we call the hook. */ -+ refcount_ref (&cred->po->refcnt); -+ (*trivfs_peropen_destroy_hook) (cred->po); -+ if (refcount_deref (&cred->po->refcnt) == 0) -+ goto free_po; -+ } -+ else -+ { -+ free_po: -+ ports_port_deref (cntl); -+ free (cred->po); -+ } - } -- if (--cred->po->refcnt == 0) -- { -- ports_port_deref (cntl); -- free (cred->po); -- } -- pthread_mutex_unlock (&cntl->lock); - - iohelp_free_iouser (cred->user); - -diff --git a/libtrivfs/protid-dup.c b/libtrivfs/protid-dup.c -index 6169603..75f3ca8 100644 ---- a/libtrivfs/protid-dup.c -+++ b/libtrivfs/protid-dup.c -@@ -35,11 +35,8 @@ trivfs_protid_dup (struct trivfs_protid *cred, struct trivfs_protid **dup) - - if (! err) - { -- pthread_mutex_lock (&cred->po->cntl->lock); - new->po = cred->po; -- new->po->refcnt++; -- pthread_mutex_unlock (&cred->po->cntl->lock); -- -+ refcount_ref (&new->po->refcnt); - new->isroot = cred->isroot; - - err = iohelp_dup_iouser (&new->user, cred->user); -diff --git a/libtrivfs/trivfs.h b/libtrivfs/trivfs.h -index bb456ff..8902338 100644 ---- a/libtrivfs/trivfs.h -+++ b/libtrivfs/trivfs.h -@@ -24,6 +24,7 @@ - #include <mach/mach.h> - #include <hurd/ports.h> - #include <hurd/iohelp.h> -+#include <refcount.h> - - struct trivfs_protid - { -@@ -41,14 +42,13 @@ struct trivfs_peropen - { - void *hook; /* for user use */ - int openmodes; -- int refcnt; -+ refcount_t refcnt; - struct trivfs_control *cntl; - }; - - struct trivfs_control - { - struct port_info pi; -- pthread_mutex_t lock; - struct port_class *protid_class; - struct port_bucket *protid_bucket; - mach_port_t filesys_id; --- -2.0.0.rc0 - diff --git a/debian/patches/0008-libports-use-a-single-hash-table.patch b/debian/patches/0008-libports-use-a-single-hash-table.patch deleted file mode 100644 index 1ec65464..00000000 --- a/debian/patches/0008-libports-use-a-single-hash-table.patch +++ /dev/null @@ -1,650 +0,0 @@ -From 27f62296caa15367a8c9cd99fd1c127d31e06d1f 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: [PATCH 08/16] libports: use a single hash table - -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 single hash table instead. Furthermore, serialize access to it -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 to treat -the bucket argument the same way as the class argument. -* libports/class-iterate.c (ports_class_iterate): Just call the -generalized _ports_bucket_class_iterate with NULL as class. -* 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 | 22 +++++++++++++++------- - libports/claim-right.c | 5 ++++- - libports/class-iterate.c | 10 +--------- - libports/complete-deallocate.c | 7 +++---- - libports/create-bucket.c | 6 ------ - libports/create-class.c | 1 - - libports/create-internal.c | 19 +++++++++++++------ - libports/destroy-right.c | 5 +++-- - libports/import-port.c | 19 +++++++++++++------ - libports/inhibit-all-rpcs.c | 27 +++++++++++++-------------- - libports/inhibit-bucket-rpcs.c | 3 ++- - libports/inhibit-class-rpcs.c | 27 ++++++++++++++++++--------- - libports/init.c | 7 ++++++- - libports/lookup-port.c | 21 ++++++++------------- - libports/ports.h | 13 ++++++++----- - libports/reallocate-from-external.c | 15 +++++++++++---- - libports/reallocate-port.c | 9 ++++++++- - libports/transfer-right.c | 18 ++++++++++++++---- - 18 files changed, 140 insertions(+), 94 deletions(-) - -diff --git a/libports/bucket-iterate.c b/libports/bucket-iterate.c -index babc204..06d8f7d 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,24 @@ _ports_bucket_class_iterate (struct port_bucket *bucket, - error_t err; - - pthread_mutex_lock (&_ports_lock); -+ pthread_mutex_lock (&_ports_htable_lock); - -- if (bucket->htable.nr_items == 0) -+ if (ht->nr_items == 0) - { -- pthread_mutex_unlock (&_ports_lock); -+ pthread_mutex_unlock (&_ports_htable_lock); - return 0; - } - -- nr_items = bucket->htable.nr_items; -+ nr_items = ht->nr_items; - p = malloc (nr_items * sizeof *p); - if (p == NULL) - { -- pthread_mutex_unlock (&_ports_lock); -+ pthread_mutex_unlock (&_ports_htable_lock); - return ENOMEM; - } - - n = 0; -- HURD_IHASH_ITERATE (&bucket->htable, arg) -+ HURD_IHASH_ITERATE (ht, arg) - { - struct port_info *const pi = arg; - -@@ -63,8 +64,15 @@ _ports_bucket_class_iterate (struct port_bucket *bucket, - n++; - } - } -+ pthread_mutex_unlock (&_ports_htable_lock); - pthread_mutex_unlock (&_ports_lock); - -+ if (n == 0) -+ { -+ free (p); -+ return 0; -+ } -+ - if (n != nr_items) - { - /* We allocated too much. Release unused memory. */ -@@ -89,5 +97,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); - } -diff --git a/libports/claim-right.c b/libports/claim-right.c -index 4851ea3..11cc3ad 100644 ---- a/libports/claim-right.c -+++ b/libports/claim-right.c -@@ -34,10 +34,13 @@ ports_claim_right (void *portstruct) - if (ret == MACH_PORT_NULL) - return ret; - -- pthread_mutex_lock (&_ports_lock); -+ pthread_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); - hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry); -+ pthread_mutex_unlock (&_ports_htable_lock); - err = mach_port_move_member (mach_task_self (), ret, MACH_PORT_NULL); - assert_perror (err); -+ pthread_mutex_lock (&_ports_lock); - pi->port_right = MACH_PORT_NULL; - if (pi->flags & PORT_HAS_SENDRIGHTS) - { -diff --git a/libports/class-iterate.c b/libports/class-iterate.c -index 1f8878a..df33818 100644 ---- a/libports/class-iterate.c -+++ b/libports/class-iterate.c -@@ -23,13 +23,5 @@ error_t - ports_class_iterate (struct port_class *class, - error_t (*fun)(void *)) - { -- pthread_mutex_lock (&_ports_lock); -- if (class->ports != 0) -- { -- struct port_bucket *bucket = class->ports->bucket; -- pthread_mutex_unlock (&_ports_lock); -- return _ports_bucket_class_iterate (bucket, class, fun); -- } -- pthread_mutex_unlock (&_ports_lock); -- return 0; -+ return _ports_bucket_class_iterate (&_ports_htable, class, fun); - } -diff --git a/libports/complete-deallocate.c b/libports/complete-deallocate.c -index 8ce095b..50548ec 100644 ---- a/libports/complete-deallocate.c -+++ b/libports/complete-deallocate.c -@@ -29,16 +29,15 @@ _ports_complete_deallocate (struct port_info *pi) - - if (pi->port_right) - { -+ pthread_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); - hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry); -+ pthread_mutex_unlock (&_ports_htable_lock); - mach_port_mod_refs (mach_task_self (), pi->port_right, - MACH_PORT_RIGHT_RECEIVE, -1); - pi->port_right = MACH_PORT_NULL; - } - -- *pi->prevp = pi->next; -- if (pi->next) -- pi->next->prevp = pi->prevp; -- - pi->bucket->count--; - pi->class->count--; - -diff --git a/libports/create-bucket.c b/libports/create-bucket.c -index 52d50c3..2c5f1b6 100644 ---- a/libports/create-bucket.c -+++ b/libports/create-bucket.c -@@ -48,11 +48,5 @@ ports_create_bucket () - - hurd_ihash_init (&ret->htable, offsetof (struct port_info, hentry)); - ret->rpcs = ret->flags = ret->count = 0; -- -- pthread_mutex_lock (&_ports_lock); -- ret->next = _ports_all_buckets; -- _ports_all_buckets = ret; -- pthread_mutex_unlock (&_ports_lock); -- - return ret; - } -diff --git a/libports/create-class.c b/libports/create-class.c -index 12c8add..782f52b 100644 ---- a/libports/create-class.c -+++ b/libports/create-class.c -@@ -39,7 +39,6 @@ ports_create_class (void (*clean_routine)(void *), - cl->dropweak_routine = dropweak_routine; - cl->flags = 0; - cl->rpcs = 0; -- cl->ports = NULL; - cl->count = 0; - cl->uninhibitable_rpcs = ports_default_uninhibitable_rpcs; - -diff --git a/libports/create-internal.c b/libports/create-internal.c -index 8551297..2981e74 100644 ---- a/libports/create-internal.c -+++ b/libports/create-internal.c -@@ -81,15 +81,22 @@ _ports_create_port_internal (struct port_class *class, - goto loop; - } - -+ pthread_mutex_lock (&_ports_htable_lock); -+ err = hurd_ihash_add (&_ports_htable, port, pi); -+ if (err) -+ { -+ pthread_mutex_unlock (&_ports_htable_lock); -+ goto lose; -+ } - err = hurd_ihash_add (&bucket->htable, port, pi); - if (err) -- goto lose; -+ { -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); -+ pthread_mutex_unlock (&_ports_htable_lock); -+ goto lose; -+ } -+ pthread_mutex_unlock (&_ports_htable_lock); - -- pi->next = class->ports; -- pi->prevp = &class->ports; -- if (class->ports) -- class->ports->prevp = &pi->next; -- class->ports = pi; - bucket->count++; - class->count++; - pthread_mutex_unlock (&_ports_lock); -diff --git a/libports/destroy-right.c b/libports/destroy-right.c -index 65e19c7..aff7c02 100644 ---- a/libports/destroy-right.c -+++ b/libports/destroy-right.c -@@ -30,12 +30,13 @@ ports_destroy_right (void *portstruct) - - if (pi->port_right != MACH_PORT_NULL) - { -- pthread_mutex_lock (&_ports_lock); -+ pthread_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); - hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry); -+ pthread_mutex_unlock (&_ports_htable_lock); - err = mach_port_mod_refs (mach_task_self (), pi->port_right, - MACH_PORT_RIGHT_RECEIVE, -1); - assert_perror (err); -- pthread_mutex_unlock (&_ports_lock); - - pi->port_right = MACH_PORT_NULL; - -diff --git a/libports/import-port.c b/libports/import-port.c -index 226f47e..91afaa7 100644 ---- a/libports/import-port.c -+++ b/libports/import-port.c -@@ -75,15 +75,22 @@ ports_import_port (struct port_class *class, struct port_bucket *bucket, - goto loop; - } - -+ pthread_mutex_lock (&_ports_htable_lock); -+ err = hurd_ihash_add (&_ports_htable, port, pi); -+ if (err) -+ { -+ pthread_mutex_unlock (&_ports_htable_lock); -+ goto lose; -+ } - err = hurd_ihash_add (&bucket->htable, port, pi); - if (err) -- goto lose; -+ { -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); -+ pthread_mutex_unlock (&_ports_htable_lock); -+ goto lose; -+ } -+ pthread_mutex_unlock (&_ports_htable_lock); - -- pi->next = class->ports; -- pi->prevp = &class->ports; -- if (class->ports) -- class->ports->prevp = &pi->next; -- class->ports = pi; - bucket->count++; - class->count++; - pthread_mutex_unlock (&_ports_lock); -diff --git a/libports/inhibit-all-rpcs.c b/libports/inhibit-all-rpcs.c -index d4a54ba..83c291f 100644 ---- a/libports/inhibit-all-rpcs.c -+++ b/libports/inhibit-all-rpcs.c -@@ -36,24 +36,23 @@ ports_inhibit_all_rpcs () - struct port_bucket *bucket; - int this_one = 0; - -- for (bucket = _ports_all_buckets; bucket; bucket = bucket->next) -+ pthread_mutex_lock (&_ports_htable_lock); -+ HURD_IHASH_ITERATE (&_ports_htable, portstruct) - { -- HURD_IHASH_ITERATE (&bucket->htable, portstruct) -+ struct rpc_info *rpc; -+ struct port_info *pi = portstruct; -+ -+ for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) - { -- struct rpc_info *rpc; -- struct port_info *pi = portstruct; -- -- for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) -- { -- /* Avoid cancelling the calling thread if it's currently -- handling a RPC. */ -- if (rpc->thread == hurd_thread_self ()) -- this_one = 1; -- else -- hurd_thread_cancel (rpc->thread); -- } -+ /* Avoid cancelling the calling thread if it's currently -+ handling a RPC. */ -+ if (rpc->thread == hurd_thread_self ()) -+ this_one = 1; -+ else -+ hurd_thread_cancel (rpc->thread); - } - } -+ pthread_mutex_unlock (&_ports_htable_lock); - - while (_ports_total_rpcs > this_one) - { -diff --git a/libports/inhibit-bucket-rpcs.c b/libports/inhibit-bucket-rpcs.c -index 965aa03..8c5a486 100644 ---- a/libports/inhibit-bucket-rpcs.c -+++ b/libports/inhibit-bucket-rpcs.c -@@ -35,6 +35,7 @@ ports_inhibit_bucket_rpcs (struct port_bucket *bucket) - { - int this_one = 0; - -+ pthread_mutex_lock (&_ports_htable_lock); - HURD_IHASH_ITERATE (&bucket->htable, portstruct) - { - struct rpc_info *rpc; -@@ -49,7 +50,7 @@ ports_inhibit_bucket_rpcs (struct port_bucket *bucket) - hurd_thread_cancel (rpc->thread); - } - } -- -+ pthread_mutex_unlock (&_ports_htable_lock); - - while (bucket->rpcs > this_one) - { -diff --git a/libports/inhibit-class-rpcs.c b/libports/inhibit-class-rpcs.c -index 7ee8653..1580bdb 100644 ---- a/libports/inhibit-class-rpcs.c -+++ b/libports/inhibit-class-rpcs.c -@@ -36,15 +36,24 @@ ports_inhibit_class_rpcs (struct port_class *class) - struct rpc_info *rpc; - int this_one = 0; - -- for (pi = class->ports; pi; pi = pi->next) -- for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) -- { -- /* Avoid cancelling the calling thread. */ -- if (rpc->thread == hurd_thread_self ()) -- this_one = 1; -- else -- hurd_thread_cancel (rpc->thread); -- } -+ pthread_mutex_lock (&_ports_htable_lock); -+ HURD_IHASH_ITERATE (&_ports_htable, portstruct) -+ { -+ struct rpc_info *rpc; -+ struct port_info *pi = portstruct; -+ if (pi->class != class) -+ continue; -+ -+ for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) -+ { -+ /* Avoid cancelling the calling thread. */ -+ if (rpc->thread == hurd_thread_self ()) -+ this_one = 1; -+ else -+ hurd_thread_cancel (rpc->thread); -+ } -+ } -+ pthread_mutex_unlock (&_ports_htable_lock); - - while (class->rpcs > this_one) - { -diff --git a/libports/init.c b/libports/init.c -index 3ef5388..d3aa90c 100644 ---- a/libports/init.c -+++ b/libports/init.c -@@ -19,9 +19,14 @@ - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - #include "ports.h" -+#include <stddef.h> - - pthread_mutex_t _ports_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_cond_t _ports_block = PTHREAD_COND_INITIALIZER; --struct port_bucket *_ports_all_buckets; -+ -+struct hurd_ihash _ports_htable = -+ HURD_IHASH_INITIALIZER (offsetof (struct port_info, ports_htable_entry)); -+pthread_mutex_t _ports_htable_lock = PTHREAD_MUTEX_INITIALIZER; -+ - int _ports_total_rpcs; - int _ports_flags; -diff --git a/libports/lookup-port.c b/libports/lookup-port.c -index f79f6f0..fbb13ef 100644 ---- a/libports/lookup-port.c -+++ b/libports/lookup-port.c -@@ -26,26 +26,21 @@ ports_lookup_port (struct port_bucket *bucket, - mach_port_t port, - struct port_class *class) - { -- struct port_info *pi = 0; -- -+ struct port_info *pi; -+ - pthread_mutex_lock (&_ports_lock); -+ pthread_mutex_lock (&_ports_htable_lock); - -- if (bucket) -- pi = hurd_ihash_find (&bucket->htable, port); -- else -- for (bucket = _ports_all_buckets; bucket; bucket = bucket->next) -- { -- pi = hurd_ihash_find (&bucket->htable, port); -- if (pi) -- break; -- } -- -- if (pi && class && pi->class != class) -+ pi = hurd_ihash_find (&_ports_htable, port); -+ if (pi -+ && ((class && pi->class != class) -+ || (bucket && pi->bucket != bucket))) - pi = 0; - - if (pi) - pi->refcnt++; - -+ pthread_mutex_unlock (&_ports_htable_lock); - pthread_mutex_unlock (&_ports_lock); - - return pi; -diff --git a/libports/ports.h b/libports/ports.h -index 7f13124..c29d78a 100644 ---- a/libports/ports.h -+++ b/libports/ports.h -@@ -48,7 +48,7 @@ struct port_info - struct rpc_info *current_rpcs; - struct port_bucket *bucket; - hurd_ihash_locp_t hentry; -- struct port_info *next, **prevp; /* links on port_class list */ -+ hurd_ihash_locp_t ports_htable_entry; - }; - typedef struct port_info *port_info_t; - -@@ -65,7 +65,6 @@ struct port_bucket - int rpcs; - int flags; - int count; -- struct port_bucket *next; - }; - /* FLAGS above are the following: */ - #define PORT_BUCKET_INHIBITED PORTS_INHIBITED -@@ -78,7 +77,6 @@ struct port_class - { - int flags; - int rpcs; -- struct port_info *ports; - int count; - void (*clean_routine) (void *); - void (*dropweak_routine) (void *); -@@ -277,7 +275,7 @@ error_t ports_class_iterate (struct port_class *class, - error_t (*fun)(void *port)); - - /* Internal entrypoint for above two. */ --error_t _ports_bucket_class_iterate (struct port_bucket *bucket, -+error_t _ports_bucket_class_iterate (struct hurd_ihash *ht, - struct port_class *class, - error_t (*fun)(void *port)); - -@@ -402,7 +400,12 @@ extern kern_return_t - /* Private data */ - extern pthread_mutex_t _ports_lock; - extern pthread_cond_t _ports_block; --extern struct port_bucket *_ports_all_buckets; -+ -+/* A hash table mapping port names to port_info objects. */ -+extern struct hurd_ihash _ports_htable; -+/* Access to the hash table is protected by this lock. */ -+extern pthread_mutex_t _ports_htable_lock; -+ - extern int _ports_total_rpcs; - extern int _ports_flags; - #define _PORTS_INHIBITED PORTS_INHIBITED -diff --git a/libports/reallocate-from-external.c b/libports/reallocate-from-external.c -index 8cccb2a..678b5d9 100644 ---- a/libports/reallocate-from-external.c -+++ b/libports/reallocate-from-external.c -@@ -43,8 +43,11 @@ ports_reallocate_from_external (void *portstruct, mach_port_t receive) - MACH_PORT_RIGHT_RECEIVE, -1); - assert_perror (err); - -+ pthread_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); - hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry); -- -+ pthread_mutex_unlock (&_ports_htable_lock); -+ - if ((pi->flags & PORT_HAS_SENDRIGHTS) && !stat.mps_srights) - { - dropref = 1; -@@ -59,11 +62,15 @@ ports_reallocate_from_external (void *portstruct, mach_port_t receive) - pi->port_right = receive; - pi->cancel_threshold = 0; - pi->mscount = stat.mps_mscount; -- -- err = hurd_ihash_add (&pi->bucket->htable, receive, pi); -+ -+ pthread_mutex_lock (&_ports_htable_lock); -+ err = hurd_ihash_add (&_ports_htable, receive, pi); - assert_perror (err); -+ err = hurd_ihash_add (&pi->bucket->htable, receive, pi); -+ pthread_mutex_unlock (&_ports_htable_lock); - pthread_mutex_unlock (&_ports_lock); -- -+ assert_perror (err); -+ - 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..4a719e4 100644 ---- a/libports/reallocate-port.c -+++ b/libports/reallocate-port.c -@@ -36,7 +36,10 @@ ports_reallocate_port (void *portstruct) - MACH_PORT_RIGHT_RECEIVE, -1); - assert_perror (err); - -+ pthread_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); - hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry); -+ pthread_mutex_unlock (&_ports_htable_lock); - - err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &pi->port_right); -@@ -48,9 +51,13 @@ ports_reallocate_port (void *portstruct) - } - pi->cancel_threshold = 0; - pi->mscount = 0; -- err = hurd_ihash_add (&pi->bucket->htable, pi->port_right, pi); -+ pthread_mutex_lock (&_ports_htable_lock); -+ err = hurd_ihash_add (&_ports_htable, pi->port_right, pi); - assert_perror (err); -+ err = hurd_ihash_add (&pi->bucket->htable, pi->port_right, pi); -+ pthread_mutex_unlock (&_ports_htable_lock); - pthread_mutex_unlock (&_ports_lock); -+ assert_perror (err); - - err = mach_port_move_member (mach_task_self (), pi->port_right, - pi->bucket->portset); -diff --git a/libports/transfer-right.c b/libports/transfer-right.c -index 72488a9..3f23d93 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_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, frompi->ports_htable_entry); - hurd_ihash_locp_remove (&frompi->bucket->htable, frompi->hentry); -+ pthread_mutex_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_mutex_lock (&_ports_htable_lock); -+ hurd_ihash_locp_remove (&_ports_htable, topi->ports_htable_entry); - hurd_ihash_locp_remove (&topi->bucket->htable, topi->hentry); -+ pthread_mutex_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_mutex_lock (&_ports_htable_lock); -+ err = hurd_ihash_add (&_ports_htable, port, topi); -+ assert_perror (err); - err = hurd_ihash_add (&topi->bucket->htable, port, topi); -+ pthread_mutex_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); --- -2.0.0.rc0 - diff --git a/debian/patches/0009-libports-lock-less-reference-counting-for-port_info-.patch b/debian/patches/0009-libports-lock-less-reference-counting-for-port_info-.patch deleted file mode 100644 index 69fdb436..00000000 --- a/debian/patches/0009-libports-lock-less-reference-counting-for-port_info-.patch +++ /dev/null @@ -1,345 +0,0 @@ -From ecf9c905ced17aa4475aa176b51b906b7ea6106e Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Sat, 3 May 2014 01:02:35 +0200 -Subject: [PATCH 09/16] libports: lock-less reference counting for port_info - objects - -* libports/ports.h (struct port_info): Use the new type. -* libports/lookup-port.c: No need to lock _ports_lock anymore. -* libports/bucket-iterate.c: Likewise. -* libports/complete-deallocate.c: Check if someone reacquired a -reference through a hash table lookup. -* libports/create-internal.c: Use the new reference counting primitives. -* libports/get-right.c: Likewise. -* libports/import-port.c: Likewise. -* libports/port-deref-weak.c: Likewise. -* libports/port-deref.c: Likewise. -* libports/port-ref-weak.c: Likewise. -* libports/port-ref.c: Likewise. -* libports/reallocate-from-external.c: Likewise. -* libports/transfer-right.c: Likewise. -* utils/rpctrace.c: Likewise. ---- - libports/bucket-iterate.c | 4 +--- - libports/complete-deallocate.c | 14 ++++++++++++++ - libports/create-internal.c | 3 +-- - libports/get-right.c | 2 +- - libports/import-port.c | 3 +-- - libports/lookup-port.c | 6 ++---- - libports/port-deref-weak.c | 10 +++------- - libports/port-deref.c | 34 ++++++++++++++++------------------ - libports/port-ref-weak.c | 8 +++----- - libports/port-ref.c | 8 +++----- - libports/ports.h | 4 ++-- - libports/reallocate-from-external.c | 2 +- - libports/transfer-right.c | 2 +- - utils/rpctrace.c | 10 ++++++++-- - 14 files changed, 57 insertions(+), 53 deletions(-) - -diff --git a/libports/bucket-iterate.c b/libports/bucket-iterate.c -index 06d8f7d..8a28827 100644 ---- a/libports/bucket-iterate.c -+++ b/libports/bucket-iterate.c -@@ -35,7 +35,6 @@ _ports_bucket_class_iterate (struct hurd_ihash *ht, - size_t i, n, nr_items; - error_t err; - -- pthread_mutex_lock (&_ports_lock); - pthread_mutex_lock (&_ports_htable_lock); - - if (ht->nr_items == 0) -@@ -59,13 +58,12 @@ _ports_bucket_class_iterate (struct hurd_ihash *ht, - - if (class == 0 || pi->class == class) - { -- pi->refcnt++; -+ refcounts_ref (&pi->refcounts, NULL); - p[n] = pi; - n++; - } - } - pthread_mutex_unlock (&_ports_htable_lock); -- pthread_mutex_unlock (&_ports_lock); - - if (n == 0) - { -diff --git a/libports/complete-deallocate.c b/libports/complete-deallocate.c -index 50548ec..a239957 100644 ---- a/libports/complete-deallocate.c -+++ b/libports/complete-deallocate.c -@@ -29,15 +29,29 @@ _ports_complete_deallocate (struct port_info *pi) - - if (pi->port_right) - { -+ struct references result; -+ - pthread_mutex_lock (&_ports_htable_lock); -+ refcounts_references (&pi->refcounts, &result); -+ if (result.hard > 0 || result.weak > 0) -+ { -+ /* A reference was reacquired through a hash table lookup. -+ It's fine, we didn't touch anything yet. */ -+ pthread_mutex_unlock (&_ports_htable_lock); -+ return; -+ } -+ - hurd_ihash_locp_remove (&_ports_htable, pi->ports_htable_entry); - hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry); - pthread_mutex_unlock (&_ports_htable_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); -+ - pi->bucket->count--; - pi->class->count--; - -diff --git a/libports/create-internal.c b/libports/create-internal.c -index 2981e74..4f1e512 100644 ---- a/libports/create-internal.c -+++ b/libports/create-internal.c -@@ -54,8 +54,7 @@ _ports_create_port_internal (struct port_class *class, - } - - pi->class = class; -- pi->refcnt = 1; -- pi->weakrefcnt = 0; -+ refcounts_init (&pi->refcounts, 1, 0); - pi->cancel_threshold = 0; - pi->mscount = 0; - pi->flags = 0; -diff --git a/libports/get-right.c b/libports/get-right.c -index 89050c6..8681f46 100644 ---- a/libports/get-right.c -+++ b/libports/get-right.c -@@ -41,7 +41,7 @@ ports_get_right (void *port) - if ((pi->flags & PORT_HAS_SENDRIGHTS) == 0) - { - pi->flags |= PORT_HAS_SENDRIGHTS; -- pi->refcnt++; -+ refcounts_ref (&pi->refcounts, NULL); - err = mach_port_request_notification (mach_task_self (), - pi->port_right, - MACH_NOTIFY_NO_SENDERS, -diff --git a/libports/import-port.c b/libports/import-port.c -index 91afaa7..8601d0e 100644 ---- a/libports/import-port.c -+++ b/libports/import-port.c -@@ -48,8 +48,7 @@ ports_import_port (struct port_class *class, struct port_bucket *bucket, - return ENOMEM; - - pi->class = class; -- pi->refcnt = 1 + !!stat.mps_srights; -- pi->weakrefcnt = 0; -+ refcounts_init (&pi->refcounts, 1 + !!stat.mps_srights, 0); - pi->cancel_threshold = 0; - pi->mscount = stat.mps_mscount; - pi->flags = stat.mps_srights ? PORT_HAS_SENDRIGHTS : 0; -diff --git a/libports/lookup-port.c b/libports/lookup-port.c -index fbb13ef..1bf012f 100644 ---- a/libports/lookup-port.c -+++ b/libports/lookup-port.c -@@ -28,7 +28,6 @@ ports_lookup_port (struct port_bucket *bucket, - { - struct port_info *pi; - -- pthread_mutex_lock (&_ports_lock); - pthread_mutex_lock (&_ports_htable_lock); - - pi = hurd_ihash_find (&_ports_htable, port); -@@ -38,10 +37,9 @@ ports_lookup_port (struct port_bucket *bucket, - pi = 0; - - if (pi) -- pi->refcnt++; -+ ports_port_ref (pi); - - pthread_mutex_unlock (&_ports_htable_lock); -- pthread_mutex_unlock (&_ports_lock); -- -+ - return pi; - } -diff --git a/libports/port-deref-weak.c b/libports/port-deref-weak.c -index beb4842..8432660 100644 ---- a/libports/port-deref-weak.c -+++ b/libports/port-deref-weak.c -@@ -25,12 +25,8 @@ void - ports_port_deref_weak (void *portstruct) - { - struct port_info *pi = portstruct; -- -- pthread_mutex_lock (&_ports_lock); -- assert (pi->weakrefcnt); -- pi->weakrefcnt--; -- if (pi->refcnt == 0 && pi->weakrefcnt == 0) -+ struct references result; -+ refcounts_deref_weak (&pi->refcounts, &result); -+ if (result.hard == 0 && result.weak == 0) - _ports_complete_deallocate (pi); -- else -- pthread_mutex_unlock (&_ports_lock); - } -diff --git a/libports/port-deref.c b/libports/port-deref.c -index cf9b238..b97dd13 100644 ---- a/libports/port-deref.c -+++ b/libports/port-deref.c -@@ -25,26 +25,24 @@ void - ports_port_deref (void *portstruct) - { - struct port_info *pi = portstruct; -- int trieddroppingweakrefs = 0; -- -- retry: -- -- pthread_mutex_lock (&_ports_lock); -- -- if (pi->refcnt == 1 && pi->weakrefcnt -- && pi->class->dropweak_routine && !trieddroppingweakrefs) -+ struct references result; -+ -+ if (pi->class->dropweak_routine) - { -- pthread_mutex_unlock (&_ports_lock); -- (*pi->class->dropweak_routine) (pi); -- trieddroppingweakrefs = 1; -- goto retry; -+ /* If we need to call the dropweak routine, we need to hold one -+ reference while doing so. We use a weak reference for this -+ purpose, which we acquire by demoting our hard reference to a -+ weak one. */ -+ refcounts_demote (&pi->refcounts, &result); -+ -+ if (result.hard == 0 && result.weak > 1) -+ (*pi->class->dropweak_routine) (pi); -+ -+ refcounts_deref_weak (&pi->refcounts, &result); - } -- -- assert (pi->refcnt); -+ else -+ refcounts_deref (&pi->refcounts, &result); - -- pi->refcnt--; -- if (pi->refcnt == 0 && pi->weakrefcnt == 0) -+ if (result.hard == 0 && result.weak == 0) - _ports_complete_deallocate (pi); -- else -- pthread_mutex_unlock (&_ports_lock); - } -diff --git a/libports/port-ref-weak.c b/libports/port-ref-weak.c -index c7d3c69..e4b7fc8 100644 ---- a/libports/port-ref-weak.c -+++ b/libports/port-ref-weak.c -@@ -25,9 +25,7 @@ void - ports_port_ref_weak (void *portstruct) - { - struct port_info *pi = portstruct; -- -- pthread_mutex_lock (&_ports_lock); -- assert (pi->refcnt || pi->weakrefcnt); -- pi->weakrefcnt++; -- pthread_mutex_unlock (&_ports_lock); -+ struct references result; -+ refcounts_ref_weak (&pi->refcounts, &result); -+ assert (result.hard > 0 || result.weak > 1); - } -diff --git a/libports/port-ref.c b/libports/port-ref.c -index 92b7118..761c50f 100644 ---- a/libports/port-ref.c -+++ b/libports/port-ref.c -@@ -25,9 +25,7 @@ void - ports_port_ref (void *portstruct) - { - struct port_info *pi = portstruct; -- -- pthread_mutex_lock (&_ports_lock); -- assert (pi->refcnt || pi->weakrefcnt); -- pi->refcnt++; -- pthread_mutex_unlock (&_ports_lock); -+ struct references result; -+ refcounts_ref (&pi->refcounts, &result); -+ assert (result.hard > 1 || result.weak > 0); - } -diff --git a/libports/ports.h b/libports/ports.h -index c29d78a..3439443 100644 ---- a/libports/ports.h -+++ b/libports/ports.h -@@ -27,6 +27,7 @@ - #include <hurd/ihash.h> - #include <mach/notify.h> - #include <pthread.h> -+#include <refcount.h> - - /* These are global values for common flags used in the various structures. - Not all of these are meaningful in all flag fields. */ -@@ -39,8 +40,7 @@ - struct port_info - { - struct port_class *class; -- int refcnt; -- int weakrefcnt; -+ refcounts_t refcounts; - mach_port_mscount_t mscount; - mach_msg_seqno_t cancel_threshold; - int flags; -diff --git a/libports/reallocate-from-external.c b/libports/reallocate-from-external.c -index 678b5d9..a912725 100644 ---- a/libports/reallocate-from-external.c -+++ b/libports/reallocate-from-external.c -@@ -56,7 +56,7 @@ ports_reallocate_from_external (void *portstruct, mach_port_t receive) - else if (((pi->flags & PORT_HAS_SENDRIGHTS) == 0) && stat.mps_srights) - { - pi->flags |= PORT_HAS_SENDRIGHTS; -- pi->refcnt++; -+ refcounts_ref (&pi->refcounts, NULL); - } - - pi->port_right = receive; -diff --git a/libports/transfer-right.c b/libports/transfer-right.c -index 3f23d93..0e898ba 100644 ---- a/libports/transfer-right.c -+++ b/libports/transfer-right.c -@@ -72,7 +72,7 @@ ports_transfer_right (void *tostruct, - else if (((topi->flags & PORT_HAS_SENDRIGHTS) == 0) && hassendrights) - { - topi->flags |= PORT_HAS_SENDRIGHTS; -- topi->refcnt++; -+ refcounts_ref (&topi->refcounts, NULL); - } - } - -diff --git a/utils/rpctrace.c b/utils/rpctrace.c -index fc913e3..b11fea4 100644 ---- a/utils/rpctrace.c -+++ b/utils/rpctrace.c -@@ -431,7 +431,9 @@ destroy_receiver_info (struct receiver_info *info) - while (send_wrapper) - { - struct sender_info *next = send_wrapper->next; -- assert (TRACED_INFO (send_wrapper)->pi.refcnt == 1); -+ assert ( -+ refcounts_hard_references (&TRACED_INFO (send_wrapper)->pi.refcounts) -+ == 1); - /* Reset the receive_right of the send wrapper in advance to avoid - * destroy_receiver_info is called when the port info is destroyed. */ - send_wrapper->receive_right = NULL; -@@ -848,7 +850,11 @@ rewrite_right (mach_port_t *right, mach_msg_type_name_t *type, - hurd_ihash_locp_remove (&traced_names, receiver_info->locp); - - send_wrapper2 = get_send_wrapper (receiver_info, dest, &rr); -- assert (TRACED_INFO (send_wrapper2)->pi.refcnt == 1); -+ assert ( -+ refcounts_hard_references ( -+ &TRACED_INFO (send_wrapper2)->pi.refcounts) -+ == 1); -+ - name = TRACED_INFO (send_wrapper2)->name; - TRACED_INFO (send_wrapper2)->name = NULL; - /* send_wrapper2 isn't destroyed normally, so we need to unlink --- -2.0.0.rc0 - diff --git a/debian/patches/0010-ext2fs-improve-enable-disable-_caching.patch b/debian/patches/0010-ext2fs-improve-enable-disable-_caching.patch deleted file mode 100644 index bc8160bc..00000000 --- a/debian/patches/0010-ext2fs-improve-enable-disable-_caching.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 129f1d249df8a04c6d20f26822327831d9085219 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Fri, 9 May 2014 10:07:28 +0200 -Subject: [PATCH 10/16] ext2fs: improve {enable,disable}_caching - -* ext2fs/pager.c (enable_caching, disable_caching): Iterate over the -pager class instead of over both pager buckets. ---- - ext2fs/pager.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/ext2fs/pager.c b/ext2fs/pager.c -index 017efcc..6328f3b 100644 ---- a/ext2fs/pager.c -+++ b/ext2fs/pager.c -@@ -1409,8 +1409,7 @@ disable_caching () - - /* Loop through the pagers and turn off caching one by one, - synchronously. That should cause termination of each pager. */ -- ports_bucket_iterate (disk_pager_bucket, block_cache); -- ports_bucket_iterate (file_pager_bucket, block_cache); -+ ports_class_iterate (_pager_class, block_cache); - } - - static void -@@ -1438,8 +1437,7 @@ enable_caching () - return 0; - } - -- ports_bucket_iterate (disk_pager_bucket, enable_cache); -- ports_bucket_iterate (file_pager_bucket, enable_cache); -+ ports_class_iterate (_pager_class, enable_cache); - } - - /* Tell diskfs if there are pagers exported, and if none, then --- -2.0.0.rc0 - diff --git a/debian/patches/0011-fatfs-improve-enable-disable-_caching.patch b/debian/patches/0011-fatfs-improve-enable-disable-_caching.patch deleted file mode 100644 index aa12134c..00000000 --- a/debian/patches/0011-fatfs-improve-enable-disable-_caching.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 2fa5aeb1c5df847ab3045a89d12d0e469a6c14f8 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Fri, 9 May 2014 10:11:45 +0200 -Subject: [PATCH 11/16] fatfs: improve {enable,disable}_caching - -* fatfs/pager.c (enable_caching, disable_caching): Iterate over the -pager class instead of over both pager buckets. ---- - fatfs/pager.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/fatfs/pager.c b/fatfs/pager.c -index f855ecf..7aa5c5e 100644 ---- a/fatfs/pager.c -+++ b/fatfs/pager.c -@@ -23,6 +23,9 @@ - #include <hurd/store.h> - #include "fatfs.h" - -+/* XXX */ -+#include "../libpager/priv.h" -+ - /* A ports bucket to hold disk pager ports. */ - struct port_bucket *disk_pager_bucket; - -@@ -963,8 +966,7 @@ disable_caching () - - /* Loop through the pagers and turn off caching one by one, - synchronously. That should cause termination of each pager. */ -- ports_bucket_iterate (disk_pager_bucket, block_cache); -- ports_bucket_iterate (file_pager_bucket, block_cache); -+ ports_class_iterate (_pager_class, block_cache); - } - - static void -@@ -992,8 +994,7 @@ enable_caching () - return 0; - } - -- ports_bucket_iterate (disk_pager_bucket, enable_cache); -- ports_bucket_iterate (file_pager_bucket, enable_cache); -+ ports_class_iterate (_pager_class, enable_cache); - } - - /* Tell diskfs if there are pagers exported, and if none, then --- -2.0.0.rc0 - diff --git a/debian/patches/0012-ext2fs-use-a-seperate-lock-to-protect-nodehash.patch b/debian/patches/0012-ext2fs-use-a-seperate-lock-to-protect-nodehash.patch deleted file mode 100644 index f05f177d..00000000 --- a/debian/patches/0012-ext2fs-use-a-seperate-lock-to-protect-nodehash.patch +++ /dev/null @@ -1,190 +0,0 @@ -From ba80b1eb24f673d5bce784b0c600ac0b1ec9d59d Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 13 May 2014 13:09:15 +0200 -Subject: [PATCH 12/16] ext2fs: use a seperate lock to protect nodehash - -Previously, ext2fs used diskfs_node_refcnt_lock to serialize access to -the nodehash. - -Use a separate lock to protect nodehash. Adjust the reference -counting accordingly. Every node in the nodehash carries a light -reference. When we are asked to give up that light reference, we -reacquire our lock momentarily to check whether someone else -reacquired a reference through the nodehash. - -* ext2fs/inode.c (nodehash_lock): New lock. -(diskfs_cached_lookup): Use a separate lock to protect nodehash. -Adjust the reference counting accordingly. -(ifind): Likewise. -(diskfs_node_iterate): Likewise. -(diskfs_node_norefs): Move the code removing the node from nodehash... -(diskfs_try_dropping_softrefs): ... here, where we check whether -someone reacquired a reference, and if so hold on to our light -reference. ---- - ext2fs/inode.c | 68 ++++++++++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 50 insertions(+), 18 deletions(-) - -diff --git a/ext2fs/inode.c b/ext2fs/inode.c -index ed78265..aa070a2 100644 ---- a/ext2fs/inode.c -+++ b/ext2fs/inode.c -@@ -46,8 +46,18 @@ - #define INOHASH(ino) (((unsigned)(ino))%INOHSZ) - #endif - -+/* The nodehash is a cache of nodes. -+ -+ Access to nodehash and nodehash_nr_items is protected by -+ nodehash_lock. -+ -+ Every node in the nodehash carries a light reference. When we are -+ asked to give up that light reference, we reacquire our lock -+ momentarily to check whether someone else reacquired a reference -+ through the nodehash. */ - static struct node *nodehash[INOHSZ]; - static size_t nodehash_nr_items; -+static pthread_mutex_t nodehash_lock = PTHREAD_MUTEX_INITIALIZER; - - static error_t read_node (struct node *np); - -@@ -71,12 +81,12 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) - struct node *np; - struct disknode *dn; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - if (np->cache_id == inum) - { -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref (np); -+ pthread_mutex_unlock (&nodehash_lock); - pthread_mutex_lock (&np->lock); - *npp = np; - return 0; -@@ -86,7 +96,7 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) - dn = malloc (sizeof (struct disknode)); - if (! dn) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - return ENOMEM; - } - dn->dirents = 0; -@@ -107,9 +117,10 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) - dn->hnext->dn->hprevp = &dn->hnext; - dn->hprevp = &nodehash[INOHASH(inum)]; - nodehash[INOHASH(inum)] = np; -+ diskfs_nref_light (np); - nodehash_nr_items += 1; - -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - - /* Get the contents of NP off disk. */ - err = read_node (np); -@@ -140,14 +151,13 @@ ifind (ino_t inum) - { - struct node *np; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - { - if (np->cache_id != inum) - continue; - -- assert (np->references); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - return np; - } - assert (0); -@@ -158,11 +168,6 @@ ifind (ino_t inum) - void - diskfs_node_norefs (struct node *np) - { -- *np->dn->hprevp = np->dn->hnext; -- if (np->dn->hnext) -- np->dn->hnext->dn->hprevp = np->dn->hprevp; -- nodehash_nr_items -= 1; -- - if (np->dn->dirents) - free (np->dn->dirents); - assert (!np->dn->pager); -@@ -180,6 +185,33 @@ diskfs_node_norefs (struct node *np) - void - diskfs_try_dropping_softrefs (struct node *np) - { -+ pthread_mutex_lock (&nodehash_lock); -+ if (np->dn->hnext != NULL) -+ { -+ /* Check if someone reacquired a reference through the -+ nodehash. */ -+ unsigned int references; -+ pthread_spin_lock (&diskfs_node_refcnt_lock); -+ references = np->references; -+ pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ -+ if (references > 0) -+ { -+ /* A reference was reacquired through a hash table lookup. -+ It's fine, we didn't touch anything yet. */ -+ pthread_mutex_unlock (&nodehash_lock); -+ return; -+ } -+ -+ *np->dn->hprevp = np->dn->hnext; -+ if (np->dn->hnext) -+ np->dn->hnext->dn->hprevp = np->dn->hprevp; -+ np->dn->hnext = NULL; -+ nodehash_nr_items -= 1; -+ diskfs_nrele_light (np); -+ } -+ pthread_mutex_unlock (&nodehash_lock); -+ - drop_pager_softrefs (np); - } - -@@ -556,12 +588,12 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) - size_t num_nodes; - struct node *node, **node_list, **p; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - - /* We must copy everything from the hash table into another data structure - to avoid running into any problems with the hash-table being modified - during processing (normally we delegate access to hash-table with -- diskfs_node_refcnt_lock, but we can't hold this while locking the -+ nodehash_lock, but we can't hold this while locking the - individual node locks). */ - num_nodes = nodehash_nr_items; - -@@ -570,7 +602,7 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) - node_list = malloc (num_nodes * sizeof (struct node *)); - if (node_list == NULL) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - ext2_debug ("unable to allocate temporary node table"); - return ENOMEM; - } -@@ -580,10 +612,10 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) - for (node = nodehash[n]; node; node = node->dn->hnext) - { - *p++ = node; -- node->references++; -+ diskfs_nref (node); - } - -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - - p = node_list; - while (num_nodes-- > 0) --- -2.0.0.rc0 - diff --git a/debian/patches/0013-fatfs-use-a-seperate-lock-to-protect-nodehash.patch b/debian/patches/0013-fatfs-use-a-seperate-lock-to-protect-nodehash.patch deleted file mode 100644 index 55fefa79..00000000 --- a/debian/patches/0013-fatfs-use-a-seperate-lock-to-protect-nodehash.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 09a2c13e7dce747e283a28dbbdd525834a4c60d8 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 13 May 2014 15:14:53 +0200 -Subject: [PATCH 13/16] fatfs: use a seperate lock to protect nodehash - -Previously, fatfs used diskfs_node_refcnt_lock to serialize access to -the nodehash. - -Use a separate lock to protect nodehash. Adjust the reference -counting accordingly. Every node in the nodehash carries a light -reference. When we are asked to give up that light reference, we -reacquire our lock momentarily to check whether someone else -reacquired a reference through the nodehash. - -* fatfs/inode.c (nodehash_lock): New lock. -(diskfs_cached_lookup): Use a separate lock to protect nodehash. -Adjust the reference counting accordingly. -(ifind): Likewise. -(diskfs_node_iterate): Likewise. -(diskfs_node_norefs): Move the code removing the node from nodehash... -(diskfs_try_dropping_softrefs): ... here, where we check whether -someone reacquired a reference, and if so hold on to our light -reference. ---- - fatfs/inode.c | 81 +++++++++++++++++++++++++++++++++++++++++------------------ - 1 file changed, 57 insertions(+), 24 deletions(-) - -diff --git a/fatfs/inode.c b/fatfs/inode.c -index ed6f3f0..8b3385b 100644 ---- a/fatfs/inode.c -+++ b/fatfs/inode.c -@@ -44,8 +44,18 @@ - #define INOHASH(ino) (((unsigned)(ino))%INOHSZ) - #endif - -+/* The nodehash is a cache of nodes. -+ -+ Access to nodehash and nodehash_nr_items is protected by -+ nodehash_lock. -+ -+ Every node in the nodehash carries a light reference. When we are -+ asked to give up that light reference, we reacquire our lock -+ momentarily to check whether someone else reacquired a reference -+ through the nodehash. */ - static struct node *nodehash[INOHSZ]; - static size_t nodehash_nr_items; -+static pthread_mutex_t nodehash_lock = PTHREAD_MUTEX_INITIALIZER; - - static error_t read_node (struct node *np, vm_address_t buf); - -@@ -67,12 +77,12 @@ diskfs_cached_lookup (ino64_t inum, struct node **npp) - struct node *np; - struct disknode *dn; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - if (np->cache_id == inum) - { -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref (np); -+ pthread_mutex_unlock (&nodehash_lock); - pthread_mutex_lock (&np->lock); - *npp = np; - return 0; -@@ -82,7 +92,7 @@ diskfs_cached_lookup (ino64_t inum, struct node **npp) - dn = malloc (sizeof (struct disknode)); - if (! dn) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - return ENOMEM; - } - dn->pager = 0; -@@ -107,10 +117,11 @@ diskfs_cached_lookup (ino64_t inum, struct node **npp) - dn->hnext->dn->hprevp = &dn->hnext; - dn->hprevp = &nodehash[INOHASH(inum)]; - nodehash[INOHASH(inum)] = np; -+ diskfs_nref_light (np); - nodehash_nr_items += 1; - -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -+ pthread_mutex_unlock (&nodehash_lock); -+ - /* Get the contents of NP off disk. */ - err = read_node (np, 0); - -@@ -133,12 +144,12 @@ diskfs_cached_lookup_in_dirbuf (int inum, struct node **npp, vm_address_t buf) - struct node *np; - struct disknode *dn; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - if (np->cache_id == inum) - { -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref (np); -+ pthread_mutex_unlock (&nodehash_lock); - pthread_mutex_lock (&np->lock); - *npp = np; - return 0; -@@ -148,7 +159,7 @@ diskfs_cached_lookup_in_dirbuf (int inum, struct node **npp, vm_address_t buf) - dn = malloc (sizeof (struct disknode)); - if (! dn) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - return ENOMEM; - } - dn->pager = 0; -@@ -173,10 +184,11 @@ diskfs_cached_lookup_in_dirbuf (int inum, struct node **npp, vm_address_t buf) - dn->hnext->dn->hprevp = &dn->hnext; - dn->hprevp = &nodehash[INOHASH(inum)]; - nodehash[INOHASH(inum)] = np; -+ diskfs_nref_light (np); - nodehash_nr_items += 1; - -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -+ pthread_mutex_unlock (&nodehash_lock); -+ - /* Get the contents of NP off disk. */ - err = read_node (np, buf); - -@@ -196,14 +208,13 @@ ifind (ino_t inum) - { - struct node *np; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - { - if (np->cache_id != inum) - continue; - -- assert (np->references); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - return np; - } - assert (0); -@@ -216,11 +227,6 @@ diskfs_node_norefs (struct node *np) - { - struct cluster_chain *last = np->dn->first; - -- *np->dn->hprevp = np->dn->hnext; -- if (np->dn->hnext) -- np->dn->hnext->dn->hprevp = np->dn->hprevp; -- nodehash_nr_items -= 1; -- - while (last) - { - struct cluster_chain *next = last->next; -@@ -251,6 +257,33 @@ diskfs_node_norefs (struct node *np) - void - diskfs_try_dropping_softrefs (struct node *np) - { -+ pthread_mutex_lock (&nodehash_lock); -+ if (np->dn->hnext != NULL) -+ { -+ /* Check if someone reacquired a reference through the -+ nodehash. */ -+ unsigned int references; -+ pthread_spin_lock (&diskfs_node_refcnt_lock); -+ references = np->references; -+ pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ -+ if (references > 0) -+ { -+ /* A reference was reacquired through a hash table lookup. -+ It's fine, we didn't touch anything yet. */ -+ pthread_mutex_unlock (&nodehash_lock); -+ return; -+ } -+ -+ *np->dn->hprevp = np->dn->hnext; -+ if (np->dn->hnext) -+ np->dn->hnext->dn->hprevp = np->dn->hprevp; -+ np->dn->hnext = NULL; -+ nodehash_nr_items -= 1; -+ diskfs_nrele_light (np); -+ } -+ pthread_mutex_unlock (&nodehash_lock); -+ - drop_pager_softrefs (np); - } - -@@ -554,12 +587,12 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) - size_t num_nodes; - struct node *node, **node_list, **p; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&nodehash_lock); - - /* We must copy everything from the hash table into another data structure - to avoid running into any problems with the hash-table being modified - during processing (normally we delegate access to hash-table with -- diskfs_node_refcnt_lock, but we can't hold this while locking the -+ nodehash_lock, but we can't hold this while locking the - individual node locks). */ - - num_nodes = nodehash_nr_items; -@@ -570,10 +603,10 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) - for (node = nodehash[n]; node; node = node->dn->hnext) - { - *p++ = node; -- node->references++; -+ diskfs_nref (node); - } - -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&nodehash_lock); - - p = node_list; - while (num_nodes-- > 0) --- -2.0.0.rc0 - diff --git a/debian/patches/0014-isofs-use-a-seperate-lock-to-protect-node_cache.patch b/debian/patches/0014-isofs-use-a-seperate-lock-to-protect-node_cache.patch deleted file mode 100644 index a78c4699..00000000 --- a/debian/patches/0014-isofs-use-a-seperate-lock-to-protect-node_cache.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 6ba30d2af6cb07cecab433aa330c6a0201e930da Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 13 May 2014 15:16:31 +0200 -Subject: [PATCH 14/16] isofs: use a seperate lock to protect node_cache - -Previously, isofs used diskfs_node_refcnt_lock to serialize access to -the node_cache. - -Use a separate lock to protect node_cache. Adjust the reference -counting accordingly. Every node in the node_cache carries a light -reference. When we are asked to give up that light reference, we -reacquire our lock momentarily to check whether someone else -reacquired a reference through the node_cache. - -* isofs/inode.c (node_cache_lock): New lock. -(inode_cache_find): Use a separate lock to protect node_cache. -Adjust the reference counting accordingly. -(diskfs_cached_lookup): Likewise. -(load_inode): Likewise. -(cache_inode): Update comment accordingly. -(diskfs_node_iterate): Likewise. -(diskfs_node_norefs): Move the code removing the node from node_cache... -(diskfs_try_dropping_softrefs): ... here, where we check whether -someone reacquired a reference, and if so hold on to our light -reference. ---- - isofs/inode.c | 72 +++++++++++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 53 insertions(+), 19 deletions(-) - -diff --git a/isofs/inode.c b/isofs/inode.c -index cdc05ae..4f22086 100644 ---- a/isofs/inode.c -+++ b/isofs/inode.c -@@ -48,9 +48,19 @@ struct node_cache - struct node *np; /* if live */ - }; - -+/* The node_cache is a cache of nodes. -+ -+ Access to node_cache, node_cache_size, and node_cache_alloced is -+ protected by node_cache_lock. -+ -+ Every node in the node_cache carries a light reference. When we -+ are asked to give up that light reference, we reacquire our lock -+ momentarily to check whether someone else reacquired a reference -+ through the node_cache. */ - static int node_cache_size = 0; - static int node_cache_alloced = 0; - struct node_cache *node_cache = 0; -+static pthread_mutex_t node_cache_lock = PTHREAD_MUTEX_INITIALIZER; - - /* Forward */ - static error_t read_disknode (struct node *, -@@ -58,7 +68,7 @@ static error_t read_disknode (struct node *, - - - /* See if node with identifier ID is in the cache. If so, return it, -- with one additional reference. diskfs_node_refcnt_lock must be held -+ with one additional reference. node_cache_lock must be held - on entry to the call, and will be released iff the node was found - in the cache. */ - void -@@ -71,8 +81,8 @@ inode_cache_find (off_t id, struct node **npp) - && node_cache[i].np) - { - *npp = node_cache[i].np; -- (*npp)->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref (*npp); -+ pthread_mutex_unlock (&node_cache_lock); - pthread_mutex_lock (&(*npp)->lock); - return; - } -@@ -92,7 +102,7 @@ use_file_start_id (struct dirrect *record, struct rrip_lookup *rr) - } - - /* Enter NP into the cache. The directory entry we used is DR, the -- cached Rock-Ridge info RR. diskfs_node_refcnt_lock must be held. */ -+ cached Rock-Ridge info RR. node_cache_lock must be held. */ - void - cache_inode (struct node *np, struct dirrect *record, - struct rrip_lookup *rr) -@@ -155,7 +165,7 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - to avoid presenting zero cache ID's. */ - id--; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&node_cache_lock); - assert (id < node_cache_size); - - np = node_cache[id].np; -@@ -174,7 +184,7 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - dn = malloc (sizeof (struct disknode)); - if (!dn) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&node_cache_lock); - release_rrip (&rr); - return ENOMEM; - } -@@ -185,16 +195,17 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - if (!np) - { - free (dn); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&node_cache_lock); - release_rrip (&rr); - return ENOMEM; - } - np->cache_id = id + 1; /* see above for rationale for increment */ - pthread_mutex_lock (&np->lock); - c->np = np; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref_light (np); -+ pthread_mutex_unlock (&node_cache_lock); - -- err = read_disknode (np, node_cache[id].dr, &rr); -+ err = read_disknode (np, dn->dr, &rr); - if (!err) - *npp = np; - -@@ -204,8 +215,8 @@ diskfs_cached_lookup (ino_t id, struct node **npp) - } - - -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref (np); -+ pthread_mutex_unlock (&node_cache_lock); - pthread_mutex_lock (&np->lock); - *npp = np; - return 0; -@@ -315,7 +326,7 @@ load_inode (struct node **npp, struct dirrect *record, - if (rr->valid & VALID_CL) - record = rr->realdirent; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&node_cache_lock); - - /* First check the cache */ - if (use_file_start_id (record, rr)) -@@ -325,7 +336,7 @@ load_inode (struct node **npp, struct dirrect *record, - - if (*npp) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&node_cache_lock); - return 0; - } - -@@ -333,7 +344,7 @@ load_inode (struct node **npp, struct dirrect *record, - dn = malloc (sizeof (struct disknode)); - if (!dn) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&node_cache_lock); - return ENOMEM; - } - dn->fileinfo = 0; -@@ -344,14 +355,14 @@ load_inode (struct node **npp, struct dirrect *record, - if (!np) - { - free (dn); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&node_cache_lock); - return ENOMEM; - } - - pthread_mutex_lock (&np->lock); - - cache_inode (np, record, rr); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&node_cache_lock); - - err = read_disknode (np, record, rr); - *npp = np; -@@ -505,9 +516,6 @@ error_t (*diskfs_read_symlink_hook) (struct node *, char *) - void - diskfs_node_norefs (struct node *np) - { -- assert (node_cache[np->cache_id - 1].np == np); -- node_cache[np->cache_id - 1].np = 0; -- - if (np->dn->translator) - free (np->dn->translator); - -@@ -521,6 +529,32 @@ diskfs_node_norefs (struct node *np) - void - diskfs_try_dropping_softrefs (struct node *np) - { -+ pthread_mutex_lock (&node_cache_lock); -+ if (np->cache_id != 0) -+ { -+ assert (node_cache[np->cache_id - 1].np == np); -+ -+ /* Check if someone reacquired a reference through the -+ node_cache. */ -+ unsigned int references; -+ pthread_spin_lock (&diskfs_node_refcnt_lock); -+ references = np->references; -+ pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ -+ if (references > 0) -+ { -+ /* A reference was reacquired through a hash table lookup. -+ It's fine, we didn't touch anything yet. */ -+ pthread_mutex_unlock (&node_cache_lock); -+ return; -+ } -+ -+ node_cache[np->cache_id - 1].np = 0; -+ np->cache_id = 0; -+ diskfs_nrele_light (np); -+ } -+ pthread_mutex_unlock (&node_cache_lock); -+ - drop_pager_softrefs (np); - } - --- -2.0.0.rc0 - diff --git a/debian/patches/0015-tmpfs-use-a-seperate-lock-to-protect-all_nodes.patch b/debian/patches/0015-tmpfs-use-a-seperate-lock-to-protect-all_nodes.patch deleted file mode 100644 index e42b4254..00000000 --- a/debian/patches/0015-tmpfs-use-a-seperate-lock-to-protect-all_nodes.patch +++ /dev/null @@ -1,263 +0,0 @@ -From b63735e2311d3afb919e39ae67ad24e71ff1d545 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 13 May 2014 15:35:42 +0200 -Subject: [PATCH 15/16] tmpfs: use a seperate lock to protect all_nodes - -Previously, tmpfs used diskfs_node_refcnt_lock to serialize access to -the all_nodes and some other related global state related to memory -consumption. - -Use a separate lock to protect all_nodes, and to the state related to -memory consumption as this is updated during insertion and removal -operations. Adjust the reference counting accordingly. Every node in -the all_nodes carries a light reference. When we are asked to give up -that light reference, we reacquire our lock momentarily to check -whether someone else reacquired a reference through the all_nodes. - -* tmpfs/node.c (all_nodes_lock): New lock. -(diskfs_alloc_node): Use a separate lock to protect all_nodes. -Adjust the reference counting accordingly. -(diskfs_free_node): Likewise. -(diskfs_cached_lookup):Likewise. -(diskfs_node_iterate): Likewise. -(diskfs_node_norefs): Move the code removing the node from all_nodes... -(diskfs_try_dropping_softrefs): ... here, where we check whether -someone reacquired a reference, and if so hold on to our light -reference. -* tmpfs/tmpfs.c (diskfs_set_statfs): Use all_nodes_lock. -* tmpfs/tmpfs.h (all_nodes_lock): New declaration. -(adjust_used): Use all_nodes_lock. ---- - tmpfs/node.c | 76 +++++++++++++++++++++++++++++++++++++++++++---------------- - tmpfs/tmpfs.c | 4 ++-- - tmpfs/tmpfs.h | 6 +++-- - 3 files changed, 62 insertions(+), 24 deletions(-) - -diff --git a/tmpfs/node.c b/tmpfs/node.c -index acc029a..74971ec 100644 ---- a/tmpfs/node.c -+++ b/tmpfs/node.c -@@ -29,8 +29,18 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - unsigned int num_files; - static unsigned int gen; - -+/* all_nodes is a cache of nodes. -+ -+ Access to all_nodes and all_nodes_nr_items is protected by -+ all_nodes_lock. -+ -+ Every node in the all_nodes carries a light reference. When we are -+ asked to give up that light reference, we reacquire our lock -+ momentarily to check whether someone else reacquired a reference -+ through the all_nodes. */ - struct node *all_nodes; - static size_t all_nodes_nr_items; -+pthread_mutex_t all_nodes_lock = PTHREAD_MUTEX_INITIALIZER; - - error_t - diskfs_alloc_node (struct node *dp, mode_t mode, struct node **npp) -@@ -40,18 +50,18 @@ diskfs_alloc_node (struct node *dp, mode_t mode, struct node **npp) - dn = calloc (1, sizeof *dn); - if (dn == 0) - return ENOSPC; -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&all_nodes_lock); - if (round_page (tmpfs_space_used + sizeof *dn) / vm_page_size - > tmpfs_page_limit) - { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&all_nodes_lock); - free (dn); - return ENOSPC; - } - dn->gen = gen++; - ++num_files; - tmpfs_space_used += sizeof *dn; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&all_nodes_lock); - - dn->type = IFTODT (mode & S_IFMT); - return diskfs_cached_lookup ((ino_t) (uintptr_t) dn, npp); -@@ -75,15 +85,18 @@ diskfs_free_node (struct node *np, mode_t mode) - free (np->dn->u.lnk); - break; - } -+ -+ pthread_mutex_lock (&all_nodes_lock); - *np->dn->hprevp = np->dn->hnext; - if (np->dn->hnext != 0) - np->dn->hnext->dn->hprevp = np->dn->hprevp; - all_nodes_nr_items -= 1; -- free (np->dn); -- np->dn = 0; -- - --num_files; - tmpfs_space_used -= sizeof *np->dn; -+ pthread_mutex_unlock (&all_nodes_lock); -+ -+ free (np->dn); -+ np->dn = 0; - } - - void -@@ -117,14 +130,6 @@ diskfs_node_norefs (struct node *np) - np->dn->u.chr = np->dn_stat.st_rdev; - break; - } -- -- /* Remove this node from the cache list rooted at `all_nodes'. */ -- *np->dn->hprevp = np->dn->hnext; -- if (np->dn->hnext != 0) -- np->dn->hnext->dn->hprevp = np->dn->hprevp; -- all_nodes_nr_items -= 1; -- np->dn->hnext = 0; -- np->dn->hprevp = 0; - } - - free (np); -@@ -167,11 +172,14 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) - - assert (npp); - -+ pthread_mutex_lock (&all_nodes_lock); -+ - if (dn->hprevp != 0) /* There is already a node. */ - { - np = *dn->hprevp; - assert (np->dn == dn); - assert (*dn->hprevp == np); -+ pthread_mutex_unlock (&all_nodes_lock); - - diskfs_nref (np); - } -@@ -183,14 +191,14 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) - np = diskfs_make_node (dn); - np->cache_id = (ino_t) (uintptr_t) dn; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); - dn->hnext = all_nodes; - if (dn->hnext) - dn->hnext->dn->hprevp = &dn->hnext; - dn->hprevp = &all_nodes; - all_nodes = np; - all_nodes_nr_items += 1; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ diskfs_nref_light (np); -+ pthread_mutex_unlock (&all_nodes_lock); - - st = &np->dn_stat; - memset (st, 0, sizeof *st); -@@ -229,12 +237,12 @@ diskfs_node_iterate (error_t (*fun) (struct node *)) - size_t num_nodes; - struct node *node, **node_list, **p; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&all_nodes_lock); - - /* We must copy everything from the hash table into another data structure - to avoid running into any problems with the hash-table being modified - during processing (normally we delegate access to hash-table with -- diskfs_node_refcnt_lock, but we can't hold this while locking the -+ all_nodes_lock, but we can't hold this while locking the - individual node locks). */ - - num_nodes = all_nodes_nr_items; -@@ -243,10 +251,10 @@ diskfs_node_iterate (error_t (*fun) (struct node *)) - for (node = all_nodes; node != 0; node = node->dn->hnext) - { - *p++ = node; -- node->references++; -+ diskfs_nref (node); - } - -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&all_nodes_lock); - - p = node_list; - while (num_nodes-- > 0) -@@ -272,6 +280,34 @@ diskfs_node_iterate (error_t (*fun) (struct node *)) - void - diskfs_try_dropping_softrefs (struct node *np) - { -+ pthread_mutex_lock (&all_nodes_lock); -+ if (np->dn->hnext != NULL) -+ { -+ /* Check if someone reacquired a reference through the -+ all_nodes. */ -+ unsigned int references; -+ pthread_spin_lock (&diskfs_node_refcnt_lock); -+ references = np->references; -+ pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ -+ if (references > 0) -+ { -+ /* A reference was reacquired through a hash table lookup. -+ It's fine, we didn't touch anything yet. */ -+ pthread_mutex_unlock (&all_nodes_lock); -+ return; -+ } -+ -+ /* Remove this node from the cache list rooted at `all_nodes'. */ -+ *np->dn->hprevp = np->dn->hnext; -+ if (np->dn->hnext != 0) -+ np->dn->hnext->dn->hprevp = np->dn->hprevp; -+ all_nodes_nr_items -= 1; -+ np->dn->hnext = NULL; -+ np->dn->hprevp = NULL; -+ diskfs_nrele_light (np); -+ } -+ pthread_mutex_unlock (&all_nodes_lock); - } - - /* The user must define this funcction. Node NP has some light -diff --git a/tmpfs/tmpfs.c b/tmpfs/tmpfs.c -index a45d343..024b818 100644 ---- a/tmpfs/tmpfs.c -+++ b/tmpfs/tmpfs.c -@@ -67,10 +67,10 @@ diskfs_set_statfs (struct statfs *st) - st->f_bsize = vm_page_size; - st->f_blocks = tmpfs_page_limit; - -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&all_nodes_lock); - st->f_files = num_files; - pages = round_page (tmpfs_space_used) / vm_page_size; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&all_nodes_lock); - - st->f_bfree = pages < tmpfs_page_limit ? tmpfs_page_limit - pages : 0; - st->f_bavail = st->f_bfree; -diff --git a/tmpfs/tmpfs.h b/tmpfs/tmpfs.h -index b3c636d..187249e 100644 ---- a/tmpfs/tmpfs.h -+++ b/tmpfs/tmpfs.h -@@ -24,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include <sys/types.h> - #include <dirent.h> - #include <stdint.h> -+#include <pthread.h> - - struct disknode - { -@@ -71,15 +72,16 @@ struct tmpfs_dirent - - extern unsigned int num_files; - extern off_t tmpfs_page_limit, tmpfs_space_used; -+extern pthread_mutex_t all_nodes_lock; - - extern mach_port_t default_pager; - - static inline void - adjust_used (off_t change) - { -- pthread_spin_lock (&diskfs_node_refcnt_lock); -+ pthread_mutex_lock (&all_nodes_lock); - tmpfs_space_used += change; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ pthread_mutex_unlock (&all_nodes_lock); - } - - #endif --- -2.0.0.rc0 - diff --git a/debian/patches/0016-libdiskfs-lock-less-reference-counting-of-nodes.patch b/debian/patches/0016-libdiskfs-lock-less-reference-counting-of-nodes.patch deleted file mode 100644 index 78bc773d..00000000 --- a/debian/patches/0016-libdiskfs-lock-less-reference-counting-of-nodes.patch +++ /dev/null @@ -1,531 +0,0 @@ -From efe44d1781ae42ec25654894c44b3eeeb97853ee Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Wed, 14 May 2014 11:19:35 +0200 -Subject: [PATCH 16/16] libdiskfs: lock-less reference counting of nodes - -* libdiskfs/diskfs.h (struct node): Use refcounts_t for reference counting. -(diskfs_node_refcnt_lock): Remove. -(diskfs_node_norefs,diskfs_drop_node): Change comments accordingly. -* libdiskfs/init-init.c: Likewise. -* libdiskfs/node-drop.c: Likewise. -* libdiskfs/node-make.c: Likewise. -* libdiskfs/node-nput.c: Likewise. -* libdiskfs/node-nputl.c: Likewise. -* libdiskfs/node-nref.c: Likewise. -* libdiskfs/node-nrefl.c: Likewise. -* libdiskfs/node-nrele.c: Likewise. -* libdiskfs/node-nrelel.c: Likewise. -* ext2fs/inode.c: Likewise. -* fatfs/inode.c: Likewise. -* isofs/inode.c: Likewise. -* tmpfs/node.c: Likewise. -* doc/hurd.texi: Likewise. ---- - doc/hurd.texi | 11 ++-------- - ext2fs/inode.c | 9 +++------ - fatfs/inode.c | 21 ++++++------------- - isofs/inode.c | 9 +++------ - libdiskfs/diskfs.h | 12 ++++------- - libdiskfs/init-init.c | 2 -- - libdiskfs/node-drop.c | 9 +++------ - libdiskfs/node-make.c | 3 +-- - libdiskfs/node-nput.c | 54 +++++++++++++++++++------------------------------ - libdiskfs/node-nputl.c | 12 ++++------- - libdiskfs/node-nref.c | 10 ++++----- - libdiskfs/node-nrefl.c | 6 +++--- - libdiskfs/node-nrele.c | 48 +++++++++++++++++++++---------------------- - libdiskfs/node-nrelel.c | 9 +++------ - tmpfs/node.c | 9 +++------ - 15 files changed, 83 insertions(+), 141 deletions(-) - -diff --git a/doc/hurd.texi b/doc/hurd.texi -index 07ddfb4..6cafdb9 100644 ---- a/doc/hurd.texi -+++ b/doc/hurd.texi -@@ -3780,10 +3780,6 @@ new thread and (eventually) get rid of the old one; the old thread won't - do any more syncs, regardless. - @end deftypefun - --@deftypevar spin_lock_t diskfs_node_refcnt_lock --Pager reference count lock. --@end deftypevar -- - @deftypevar int diskfs_readonly - Set to zero if the filesystem is currently writable. - @end deftypevar -@@ -3818,9 +3814,7 @@ Every file or directory is a diskfs @dfn{node}. The following functions - help your diskfs callbacks manage nodes and their references: - - @deftypefun void diskfs_drop_node (@w{struct node *@var{np}}) --Node @var{np} now has no more references; clean all state. The --@var{diskfs_node_refcnt_lock} must be held, and will be released upon --return. @var{np} must be locked. -+Node @var{np} now has no more references; clean all state. - @end deftypefun - - @deftypefun void diskfs_node_update (@w{struct node *@var{np}}, @w{int @var{wait}}) -@@ -4236,14 +4230,13 @@ without real users. - @deftypefun void diskfs_try_dropping_softrefs (@w{struct node *@var{np}}) - Node @var{np} has some light references, but has just lost its last hard - references. Take steps so that if any light references can be freed, --they are. Both @var{diskfs_node_refcnt_lock} and @var{np} are locked. -+they are. @var{np} is locked. - This function will be called after @code{diskfs_lost_hardrefs}. - @end deftypefun - - @deftypefun void diskfs_node_norefs (@w{struct node *@var{np}}) - Node @var{np} has no more references; free local state, including - @code{*@var{np}} if it shouldn't be retained. --@var{diskfs_node_refcnt_lock} is held. - @end deftypefun - - @deftypefun error_t diskfs_set_hypermetadata (@w{int @var{wait}}, @w{int @var{clean}}) -diff --git a/ext2fs/inode.c b/ext2fs/inode.c -index aa070a2..7ec343f 100644 ---- a/ext2fs/inode.c -+++ b/ext2fs/inode.c -@@ -190,12 +190,9 @@ diskfs_try_dropping_softrefs (struct node *np) - { - /* Check if someone reacquired a reference through the - nodehash. */ -- unsigned int references; -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- references = np->references; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -- if (references > 0) -+ struct references result; -+ refcounts_references (&np->refcounts, &result); -+ if (result.hard > 0 || result.weak > 1) - { - /* A reference was reacquired through a hash table lookup. - It's fine, we didn't touch anything yet. */ -diff --git a/fatfs/inode.c b/fatfs/inode.c -index 8b3385b..d5750b4 100644 ---- a/fatfs/inode.c -+++ b/fatfs/inode.c -@@ -237,14 +237,8 @@ diskfs_node_norefs (struct node *np) - if (np->dn->translator) - free (np->dn->translator); - -- /* It is safe to unlock diskfs_node_refcnt_lock here for a while because -- all references to the node have been deleted. */ - if (np->dn->dirnode) -- { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- diskfs_nrele (np->dn->dirnode); -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- } -+ diskfs_nrele (np->dn->dirnode); - - assert (!np->dn->pager); - -@@ -262,12 +256,9 @@ diskfs_try_dropping_softrefs (struct node *np) - { - /* Check if someone reacquired a reference through the - nodehash. */ -- unsigned int references; -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- references = np->references; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -- if (references > 0) -+ struct references result; -+ refcounts_references (&np->refcounts, &result); -+ if (result.hard > 0 || result.weak > 1) - { - /* A reference was reacquired through a hash table lookup. - It's fine, we didn't touch anything yet. */ -@@ -372,7 +363,7 @@ read_node (struct node *np, vm_address_t buf) - /* Files in fatfs depend on the directory that hold the file. */ - np->dn->dirnode = dp; - if (dp) -- dp->references++; -+ refcounts_ref (&dp->refcounts, NULL); - - pthread_rwlock_rdlock (&np->dn->dirent_lock); - -@@ -814,7 +805,7 @@ diskfs_alloc_node (struct node *dir, mode_t mode, struct node **node) - - /* FIXME: We know that readnode couldn't put this in. */ - np->dn->dirnode = dir; -- dir->references++; -+ refcounts_ref (&dir->refcounts, NULL); - - *node = np; - return 0; -diff --git a/isofs/inode.c b/isofs/inode.c -index 4f22086..b36a289 100644 ---- a/isofs/inode.c -+++ b/isofs/inode.c -@@ -536,12 +536,9 @@ diskfs_try_dropping_softrefs (struct node *np) - - /* Check if someone reacquired a reference through the - node_cache. */ -- unsigned int references; -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- references = np->references; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -- if (references > 0) -+ struct references result; -+ refcounts_references (&np->refcounts, &result); -+ if (result.hard > 0 || result.weak > 1) - { - /* A reference was reacquired through a hash table lookup. - It's fine, we didn't touch anything yet. */ -diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h -index ae1a150..2f5a76c 100644 ---- a/libdiskfs/diskfs.h -+++ b/libdiskfs/diskfs.h -@@ -96,8 +96,7 @@ struct node - - pthread_mutex_t lock; - -- int references; /* hard references */ -- int light_references; /* light references */ -+ refcounts_t refcounts; - - mach_port_t sockaddr; /* address for S_IFSOCK shortcut */ - -@@ -198,8 +197,6 @@ extern volatile struct mapped_time_value *diskfs_mtime; - be done by format independent code. */ - extern int diskfs_synchronous; - --extern pthread_spinlock_t diskfs_node_refcnt_lock; -- - extern int pager_port_type; - - /* Whether the filesystem is currently writable or not. */ -@@ -448,7 +445,7 @@ error_t diskfs_alloc_node (struct node *dp, mode_t mode, struct node **np); - void diskfs_free_node (struct node *np, mode_t mode); - - /* Node NP has no more references; free local state, including *NP -- if it isn't to be retained. diskfs_node_refcnt_lock is held. */ -+ if it isn't to be retained. */ - void diskfs_node_norefs (struct node *np); - - /* The user must define this function. Node NP has some light -@@ -611,9 +608,8 @@ void diskfs_spawn_first_thread (ports_demuxer_type demuxer); - diskfs_init_completed once it has a valid proc and auth port. */ - void diskfs_start_bootstrap (); - --/* Node NP now has no more references; clean all state. The -- _diskfs_node_refcnt_lock must be held, and will be released -- upon return. NP must be locked. */ -+/* Node NP now has no more references; clean all state. NP must be -+ locked. */ - void diskfs_drop_node (struct node *np); - - /* Set on disk fields from NP->dn_stat; update ctime, atime, and mtime -diff --git a/libdiskfs/init-init.c b/libdiskfs/init-init.c -index 35be7ed..976b4e8 100644 ---- a/libdiskfs/init-init.c -+++ b/libdiskfs/init-init.c -@@ -37,8 +37,6 @@ int _diskfs_noatime; - - struct hurd_port _diskfs_exec_portcell; - --pthread_spinlock_t diskfs_node_refcnt_lock = PTHREAD_SPINLOCK_INITIALIZER; -- - pthread_spinlock_t _diskfs_control_lock = PTHREAD_SPINLOCK_INITIALIZER; - int _diskfs_ncontrol_ports; - -diff --git a/libdiskfs/node-drop.c b/libdiskfs/node-drop.c -index 83eb590..fab3cfa 100644 ---- a/libdiskfs/node-drop.c -+++ b/libdiskfs/node-drop.c -@@ -31,9 +31,8 @@ free_modreqs (struct modreq *mr) - } - - --/* Node NP now has no more references; clean all state. The -- diskfs_node_refcnt_lock must be held, and will be released -- upon return. NP must be locked. */ -+/* Node NP now has no more references; clean all state. NP must be -+ locked. */ - void - diskfs_drop_node (struct node *np) - { -@@ -60,8 +59,7 @@ diskfs_drop_node (struct node *np) - and an nput. The next time through, this routine - will notice that the size is zero, and not have to - do anything. */ -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ refcounts_ref (&np->refcounts, NULL); - diskfs_truncate (np, 0); - - /* Force allocsize to zero; if truncate consistently fails this -@@ -94,5 +92,4 @@ diskfs_drop_node (struct node *np) - assert (!np->sockaddr); - - diskfs_node_norefs (np); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); - } -diff --git a/libdiskfs/node-make.c b/libdiskfs/node-make.c -index 2b6ef2a..fc4f54c 100644 ---- a/libdiskfs/node-make.c -+++ b/libdiskfs/node-make.c -@@ -36,8 +36,7 @@ diskfs_make_node (struct disknode *dn) - np->dn_stat_dirty = 0; - - pthread_mutex_init (&np->lock, NULL); -- np->references = 1; -- np->light_references = 0; -+ refcounts_init (&np->refcounts, 1, 0); - np->owner = 0; - np->sockaddr = MACH_PORT_NULL; - -diff --git a/libdiskfs/node-nput.c b/libdiskfs/node-nput.c -index 5043ad1..2935ae2 100644 ---- a/libdiskfs/node-nput.c -+++ b/libdiskfs/node-nput.c -@@ -26,56 +26,44 @@ - void - diskfs_nput (struct node *np) - { -- int tried_drop_softrefs = 0; -+ struct references result; - -- loop: -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- assert (np->references); -- np->references--; -- if (np->references + np->light_references == 0) -- diskfs_drop_node (np); -- else if (np->references == 0 && !tried_drop_softrefs) -- { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ /* While we call the diskfs_try_dropping_softrefs, we need to hold -+ one reference. We use a weak reference for this purpose, which -+ we acquire by demoting our hard reference to a weak one. */ -+ refcounts_demote (&np->refcounts, &result); - -+ if (result.hard == 0) -+ { - /* This is our cue that something akin to "last process closes file" - in the POSIX.1 sense happened, so make sure any pending node time - updates now happen in a timely fashion. */ - diskfs_set_node_times (np); -- - diskfs_lost_hardrefs (np); - if (!np->dn_stat.st_nlink) - { -- /* There are no links. If there are soft references that -- can be dropped, we can't let them postpone deallocation. -- So attempt to drop them. But that's a user-supplied -- routine, which might result in further recursive calls to -- the ref-counting system. So we have to reacquire our -- reference around the call to forestall disaster. */ -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- - if (np->sockaddr != MACH_PORT_NULL) - { - mach_port_deallocate (mach_task_self (), np->sockaddr); - np->sockaddr = MACH_PORT_NULL; - } - -+ /* There are no links. If there are soft references that -+ can be dropped, we can't let them postpone deallocation. -+ So attempt to drop them. But that's a user-supplied -+ routine, which might result in further recursive calls to -+ the ref-counting system. This is not a problem, as we -+ hold a weak reference ourselves. */ - diskfs_try_dropping_softrefs (np); -- -- /* But there's no value in looping forever in this -- routine; only try to drop soft refs once. */ -- tried_drop_softrefs = 1; -- -- /* Now we can drop the reference back... */ -- goto loop; - } - pthread_mutex_unlock (&np->lock); - } -- else -- { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- pthread_mutex_unlock (&np->lock); -- } -+ -+ /* Finally get rid of our reference. */ -+ refcounts_deref_weak (&np->refcounts, &result); -+ -+ if (result.hard == 0 && result.weak == 0) -+ diskfs_drop_node (np); -+ -+ pthread_mutex_unlock (&np->lock); - } -diff --git a/libdiskfs/node-nputl.c b/libdiskfs/node-nputl.c -index 1959665..8dac16e 100644 ---- a/libdiskfs/node-nputl.c -+++ b/libdiskfs/node-nputl.c -@@ -25,14 +25,10 @@ - void - diskfs_nput_light (struct node *np) - { -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- assert (np->light_references); -- np->light_references--; -- if (np->references + np->light_references == 0) -+ struct references result; -+ refcounts_deref_weak (&np->refcounts, &result); -+ if (result.hard == 0 && result.weak == 0) - diskfs_drop_node (np); - else -- { -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- pthread_mutex_unlock (&np->lock); -- } -+ pthread_mutex_unlock (&np->lock); - } -diff --git a/libdiskfs/node-nref.c b/libdiskfs/node-nref.c -index 13cea05..89ffa4f 100644 ---- a/libdiskfs/node-nref.c -+++ b/libdiskfs/node-nref.c -@@ -26,12 +26,10 @@ - void - diskfs_nref (struct node *np) - { -- int new_hardref; -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- np->references++; -- new_hardref = (np->references == 1); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- if (new_hardref) -+ struct references result; -+ refcounts_ref (&np->refcounts, &result); -+ assert (result.hard > 1 || result.weak > 0); -+ if (result.hard == 1) - { - pthread_mutex_lock (&np->lock); - diskfs_new_hardrefs (np); -diff --git a/libdiskfs/node-nrefl.c b/libdiskfs/node-nrefl.c -index 9692247..b7af409 100644 ---- a/libdiskfs/node-nrefl.c -+++ b/libdiskfs/node-nrefl.c -@@ -24,7 +24,7 @@ - void - diskfs_nref_light (struct node *np) - { -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- np->light_references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ struct references result; -+ refcounts_ref_weak (&np->refcounts, &result); -+ assert (result.hard > 0 || result.weak > 1); - } -diff --git a/libdiskfs/node-nrele.c b/libdiskfs/node-nrele.c -index cc68089..d962846 100644 ---- a/libdiskfs/node-nrele.c -+++ b/libdiskfs/node-nrele.c -@@ -28,38 +28,36 @@ - void - diskfs_nrele (struct node *np) - { -- int tried_drop_softrefs = 0; -+ struct references result; - -- loop: -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- assert (np->references); -- np->references--; -- if (np->references + np->light_references == 0) -- { -- pthread_mutex_lock (&np->lock); -- diskfs_drop_node (np); -- } -- else if (np->references == 0) -+ /* While we call the diskfs_try_dropping_softrefs, we need to hold -+ one reference. We use a weak reference for this purpose, which -+ we acquire by demoting our hard reference to a weak one. */ -+ refcounts_demote (&np->refcounts, &result); -+ -+ if (result.hard == 0) - { - pthread_mutex_lock (&np->lock); -- pthread_spin_unlock (&diskfs_node_refcnt_lock); - diskfs_lost_hardrefs (np); -- if (!np->dn_stat.st_nlink && !tried_drop_softrefs) -+ if (!np->dn_stat.st_nlink) - { -- /* Same issue here as in nput; see that for explanation */ -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- np->references++; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -+ /* There are no links. If there are soft references that -+ can be dropped, we can't let them postpone deallocation. -+ So attempt to drop them. But that's a user-supplied -+ routine, which might result in further recursive calls to -+ the ref-counting system. This is not a problem, as we -+ hold a weak reference ourselves. */ - diskfs_try_dropping_softrefs (np); -- tried_drop_softrefs = 1; -- -- /* Now we can drop the reference back... */ -- pthread_mutex_unlock (&np->lock); -- goto loop; - } - pthread_mutex_unlock (&np->lock); - } -- else -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -+ -+ /* Finally get rid of our reference. */ -+ refcounts_deref_weak (&np->refcounts, &result); -+ -+ if (result.hard == 0 && result.weak == 0) -+ { -+ pthread_mutex_lock (&np->lock); -+ diskfs_drop_node (np); -+ } - } -diff --git a/libdiskfs/node-nrelel.c b/libdiskfs/node-nrelel.c -index ee53b22..dc4f920 100644 ---- a/libdiskfs/node-nrelel.c -+++ b/libdiskfs/node-nrelel.c -@@ -26,14 +26,11 @@ - void - diskfs_nrele_light (struct node *np) - { -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- assert (np->light_references); -- np->light_references--; -- if (np->references + np->light_references == 0) -+ struct references result; -+ refcounts_deref_weak (&np->refcounts, &result); -+ if (result.hard == 0 && result.weak == 0) - { - pthread_mutex_lock (&np->lock); - diskfs_drop_node (np); - } -- else -- pthread_spin_unlock (&diskfs_node_refcnt_lock); - } -diff --git a/tmpfs/node.c b/tmpfs/node.c -index 74971ec..275bb3c 100644 ---- a/tmpfs/node.c -+++ b/tmpfs/node.c -@@ -285,12 +285,9 @@ diskfs_try_dropping_softrefs (struct node *np) - { - /* Check if someone reacquired a reference through the - all_nodes. */ -- unsigned int references; -- pthread_spin_lock (&diskfs_node_refcnt_lock); -- references = np->references; -- pthread_spin_unlock (&diskfs_node_refcnt_lock); -- -- if (references > 0) -+ struct references result; -+ refcounts_references (&np->refcounts, &result); -+ if (result.hard > 0 || result.weak > 1) - { - /* A reference was reacquired through a hash table lookup. - It's fine, we didn't touch anything yet. */ --- -2.0.0.rc0 - diff --git a/debian/patches/series b/debian/patches/series index fa1ba2c1..c08b0f99 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -40,19 +40,3 @@ xkb-compat.patch mach-defpager-protected-payload.patch -0001-libihash-fix-typo.patch -0002-libihash-add-hurd_ihash_get_load.patch -0003-libihash-add-hurd_ihash_value_valid.patch -0004-libihash-optimize-lookup-or-insert-operations.patch -0005-include-add-lock-less-reference-counting-primitives.patch -0006-libdiskfs-lock-less-reference-counting-for-peropen-o.patch -0007-libtrivfs-lock-less-reference-counting-for-trivfs_pe.patch -0008-libports-use-a-single-hash-table.patch -0009-libports-lock-less-reference-counting-for-port_info-.patch -0010-ext2fs-improve-enable-disable-_caching.patch -0011-fatfs-improve-enable-disable-_caching.patch -0012-ext2fs-use-a-seperate-lock-to-protect-nodehash.patch -0013-fatfs-use-a-seperate-lock-to-protect-nodehash.patch -0014-isofs-use-a-seperate-lock-to-protect-node_cache.patch -0015-tmpfs-use-a-seperate-lock-to-protect-all_nodes.patch -0016-libdiskfs-lock-less-reference-counting-of-nodes.patch |