bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/8] libnetfs: remove global lock and use hard and soft reference


From: Flavio Cruz
Subject: [PATCH 1/8] libnetfs: remove global lock and use hard and soft references for netfs nodes. libnetfs translators can add soft references to nodes and then drop them using netfs_try_dropping_softrefs.
Date: Sun, 6 Mar 2016 17:05:24 -0500
User-agent: Mutt/1.5.24 (2015-08-30)

* libnetfs/drop-node.c: Remove use of netfs_node_refcnt_lock.
* libnetfs/init-init.c: Remove netfs_node_refcnt_lock.
* libnetfs/make-node.c: Initialize refcounts in refcounts_init.
* libnetfs/netfs.h: Use refcounts_t for tracking node references. Remove
netfs_node_refcnt_lock. Add netfs_nref_light, netfs_nrele_light and
handler netfs_try_dropping_softrefs. Adjust comments.
* libnetfs/nput.c: Use refcounts_t. Call netfs_try_dropping_softrefs to
remove any soft reference that the translator might have acquired
during the lifetime of the node. Implement empty
netfs_try_dropping_softrefs.
* libnetfs/nref.c: Implement netfs_nref_light.c.
* libnetfs/nrele.c: Use refcounts_t and netfs_try_dropping_softrefs.
Implement netfs_nrele_light.
---
 libnetfs/drop-node.c |  1 -
 libnetfs/init-init.c |  2 --
 libnetfs/make-node.c |  2 +-
 libnetfs/netfs.h     | 42 +++++++++++++++++++++++++++---------------
 libnetfs/nput.c      | 27 ++++++++++++++++++---------
 libnetfs/nref.c      | 12 +++++++++---
 libnetfs/nrele.c     | 37 ++++++++++++++++++++++++++++++-------
 7 files changed, 85 insertions(+), 38 deletions(-)

diff --git a/libnetfs/drop-node.c b/libnetfs/drop-node.c
index 2fe5ce9..f0d69be 100644
--- a/libnetfs/drop-node.c
+++ b/libnetfs/drop-node.c
@@ -25,5 +25,4 @@ netfs_drop_node (struct node *np)
 {
   fshelp_drop_transbox (&np->transbox);
   netfs_node_norefs (np);
-  pthread_spin_unlock (&netfs_node_refcnt_lock);
 }
diff --git a/libnetfs/init-init.c b/libnetfs/init-init.c
index a088ad5..9ca1aac 100644
--- a/libnetfs/init-init.c
+++ b/libnetfs/init-init.c
@@ -24,8 +24,6 @@
 /* For safe inlining of netfs_node_netnode and netfs_netnode_node.  */
 size_t const _netfs_sizeof_struct_node = sizeof (struct node);
 
-pthread_spinlock_t netfs_node_refcnt_lock = PTHREAD_SPINLOCK_INITIALIZER;
-
 struct node *netfs_root_node = 0;
 struct port_bucket *netfs_port_bucket = 0;
 struct port_class *netfs_protid_class = 0;
diff --git a/libnetfs/make-node.c b/libnetfs/make-node.c
index 6bd8109..a292dc6 100644
--- a/libnetfs/make-node.c
+++ b/libnetfs/make-node.c
@@ -27,7 +27,7 @@ init_node (struct node *np, struct netnode *nn)
   np->nn = nn;
 
   pthread_mutex_init (&np->lock, NULL);
-  np->references = 1;
+  refcounts_init (&np->refcounts, 1, 0);
   np->sockaddr = MACH_PORT_NULL;
   np->owner = 0;
 
diff --git a/libnetfs/netfs.h b/libnetfs/netfs.h
index 67a6a9a..6c989a4 100644
--- a/libnetfs/netfs.h
+++ b/libnetfs/netfs.h
@@ -82,8 +82,8 @@ struct node
 
   pthread_mutex_t lock;
 
-  /* The number of references to this node.  */
-  int references;
+  /* Hard and soft references to this node.  */
+  refcounts_t refcounts;
 
   mach_port_t sockaddr;
 
@@ -397,10 +397,6 @@ netfs_netnode_node (struct netnode *netnode)
   return (struct node *) ((char *) netnode - _netfs_sizeof_struct_node);
 }
 
-/* Whenever node->references is to be touched, this lock must be
-   held.  Cf. netfs_nrele, netfs_nput, netfs_nref and netfs_drop_node.  */
-extern pthread_spinlock_t netfs_node_refcnt_lock;
-
 /* Normally called in main.  This function sets up some of the netfs
    server's internal state.  */
 void netfs_init (void);
@@ -425,22 +421,38 @@ struct protid *netfs_make_protid (struct peropen *po, 
struct iouser *user);
 struct peropen *netfs_make_peropen (struct node *, int,
                                    struct peropen *context);
 
-/* Add a reference to node NP. Unless you already hold a reference,
+/* Add a hard reference to node NP. Unless you already hold a reference,
    NP must be locked.  */
 void netfs_nref (struct node *np);
 
-/* Releases a node.  Drops a reference to node NP, which must not be
-   locked by the caller.  If this was the last reference, drops the
-   node.  The node cannot be used again without first obtaining a
-   reference to it.  */
+/* Add a light reference to a node.  */
+void netfs_nref_light (struct node *np);
+
+/* Releases a hard reference on NP. If NP is locked by anyone, then
+   this cannot be the last hard reference (because you must hold a
+   hard reference in order to hold the lock). If this is the last
+   hard reference then request soft references to be dropped.  */
 void netfs_nrele (struct node *np);
 
-/* Puts a node back.  Drops a reference to the node NP, which must be
-   locked by the caller (this lock will be released by netfs_nput).
-   If this was the last reference, drops the node.  The node cannot be
-   used again without first obtaining a reference to it.  */
+/* Release a soft reference on NP. If NP is locked by anyone, then
+   this cannot be the last reference (because you must hold a hard
+   reference in order to hold the lock).  */
+void netfs_nrele_light (struct node *np);
+
+/* Puts a node back by releasing a hard reference on NP, which must
+   be locked by the caller (this lock will be released by netfs_nput).
+   If this was the last reference, then request soft references to be
+   dropped.  */
 void netfs_nput (struct node *np);
 
+/* The user must define this function in order to drop the soft references
+   that this node may have. When this function is called, node NP has just
+   lost its hard references and is now trying to also drop its soft references.
+   If the node is stored in another data structure (for caching purposes),
+   this allows the user to remove it so that the node can be safely deleted
+   from memory.  */
+void netfs_try_dropping_softrefs (struct node *np);
+
 /* Called internally when no more references to node NP exist. */
 void netfs_drop_node (struct node *np);
 
diff --git a/libnetfs/nput.c b/libnetfs/nput.c
index 522c714..b04fc4b 100644
--- a/libnetfs/nput.c
+++ b/libnetfs/nput.c
@@ -23,15 +23,24 @@
 void
 netfs_nput (struct node *np)
 {
-  pthread_spin_lock (&netfs_node_refcnt_lock);
-  assert (np->references);
-  np->references--;
-  if (np->references == 0)
+  struct references result;
+
+  refcounts_demote (&np->refcounts, &result);
+
+  if (result.hard == 0)
+    netfs_try_dropping_softrefs (np);
+
+  refcounts_deref_weak (&np->refcounts, &result);
+
+  if (result.hard == 0 && result.weak == 0)
     netfs_drop_node (np);
-    /* netfs_drop_node drops netfs_node_refcnt_lock for us.  */
   else
-    {
-      pthread_spin_unlock (&netfs_node_refcnt_lock);
-      pthread_mutex_unlock (&np->lock);
-    }
+    pthread_mutex_unlock (&np->lock);
+}
+
+/* The last hard reference to NP has gone away; the user must define
+   this function in order to drop all the soft references.  */
+void __attribute__ ((weak))
+netfs_try_dropping_softrefs (struct node *np)
+{
 }
diff --git a/libnetfs/nref.c b/libnetfs/nref.c
index 86b4992..d48d9c8 100644
--- a/libnetfs/nref.c
+++ b/libnetfs/nref.c
@@ -23,7 +23,13 @@
 void
 netfs_nref (struct node *np)
 {
-  pthread_spin_lock (&netfs_node_refcnt_lock);
-  np->references++;
-  pthread_spin_unlock (&netfs_node_refcnt_lock);
+  struct references result;
+  refcounts_ref (&np->refcounts, &result);
+}
+
+void
+netfs_nref_light (struct node *np)
+{
+  struct references result;
+  refcounts_ref_weak (&np->refcounts, &result);
 }
diff --git a/libnetfs/nrele.c b/libnetfs/nrele.c
index 6f9a014..4dddd1f 100644
--- a/libnetfs/nrele.c
+++ b/libnetfs/nrele.c
@@ -23,15 +23,38 @@
 void
 netfs_nrele (struct node *np)
 {
-  pthread_spin_lock (&netfs_node_refcnt_lock);
-  assert (np->references);
-  np->references--;
-  if (np->references == 0)
+  struct references result;
+  int locked = FALSE;
+
+  refcounts_demote (&np->refcounts, &result);
+
+  if (result.hard == 0)
+    {
+      pthread_mutex_lock (&np->lock);
+      netfs_try_dropping_softrefs (np);
+      locked = TRUE;
+    }
+
+  refcounts_deref_weak (&np->refcounts, &result);
+
+  if (result.hard == 0 && result.weak == 0)
+    {
+      if (! locked)
+        pthread_mutex_lock (&np->lock);
+      netfs_drop_node (np);
+    } else if (locked)
+      pthread_mutex_unlock (&np->lock);
+}
+
+void
+netfs_nrele_light (struct node *np)
+{
+  struct references result;
+
+  refcounts_deref_weak (&np->refcounts, &result);
+  if (result.hard == 0 && result.weak == 0)
     {
       pthread_mutex_lock (&np->lock);
       netfs_drop_node (np);
-      /* netfs_drop_node drops netfs_node_refcnt_lock for us.  */
     }
-  else
-    pthread_spin_unlock (&netfs_node_refcnt_lock);
 }
-- 
2.6.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]