summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-06 19:07:13 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-26 13:17:16 +0200
commit1d1da90042d2ee7a8215dc6291b54bc1ebe59fe4 (patch)
tree54c00f70a5703b40bb8243a6d76afd024c50cdaf
parent5b039a12bf5cfc9c65b8e169ed4503e306f971f3 (diff)
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.
-rw-r--r--libtrivfs/cntl-create.c1
-rw-r--r--libtrivfs/io-reauthenticate.c5
-rw-r--r--libtrivfs/io-restrict-auth.c4
-rw-r--r--libtrivfs/open.c2
-rw-r--r--libtrivfs/protid-clean.c29
-rw-r--r--libtrivfs/protid-dup.c5
-rw-r--r--libtrivfs/trivfs.h4
7 files changed, 24 insertions, 26 deletions
diff --git a/libtrivfs/cntl-create.c b/libtrivfs/cntl-create.c
index 910daf3b..eb9a8340 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 7677697a..df0ed2ee 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 65b4fd62..39670fe3 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 f64d2ffd..97e70a16 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 f98da6a5..86fbc191 100644
--- a/libtrivfs/protid-clean.c
+++ b/libtrivfs/protid-clean.c
@@ -31,19 +31,26 @@ 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 (trivfs_peropen_destroy_hook)
{
- pthread_mutex_unlock (&cntl->lock);
- (*trivfs_peropen_destroy_hook) (cred->po);
- pthread_mutex_lock (&cntl->lock);
+ if (refcount_deref (&cred->po->refcnt) == 0)
+ {
+ /* 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)
+ {
+ ports_port_deref (cntl);
+ free (cred->po);
+ }
+ }
}
- if (--cred->po->refcnt == 0)
- {
- ports_port_deref (cntl);
- free (cred->po);
- }
- pthread_mutex_unlock (&cntl->lock);
+ else
+ if (refcount_deref (&cred->po->refcnt) == 0)
+ {
+ ports_port_deref (cntl);
+ free (cred->po);
+ }
iohelp_free_iouser (cred->user);
diff --git a/libtrivfs/protid-dup.c b/libtrivfs/protid-dup.c
index 61696032..75f3ca88 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 bb456ffa..89023383 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;