[tor-commits] [torsocks/master] Add registry lock API and connection's refcount

dgoulet at torproject.org dgoulet at torproject.org
Fri Apr 4 22:40:25 UTC 2014


commit d00d7dab5a31c9967e14971493e9650621e5d656
Author: David Goulet <dgoulet at ev0ke.net>
Date:   Tue Jun 18 22:14:24 2013 -0400

    Add registry lock API and connection's refcount
    
    Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
 src/common/Makefile.am  |    2 +-
 src/common/connection.c |   47 ++++++++++++++++++++++++++++++++++++++
 src/common/connection.h |   14 ++++++++++++
 src/common/macros.h     |   18 ++++++++++++++-
 src/common/ref.h        |   58 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 6714617..8d8e074 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -5,4 +5,4 @@ AM_CFLAGS = -fno-strict-aliasing
 noinst_LTLIBRARIES = libcommon.la
 libcommon_la_SOURCES = log.c log.h config-file.c config-file.h utils.c utils.h \
                        compat.c compat.h socks5.c socks5.h \
-                       connection.c connection.h ht.h
+                       connection.c connection.h ht.h ref.h
diff --git a/src/common/connection.c b/src/common/connection.c
index 8ee60b9..ba1890a 100644
--- a/src/common/connection.c
+++ b/src/common/connection.c
@@ -22,6 +22,20 @@
 #include "connection.h"
 #include "macros.h"
 
+/* Connection registry mutex. */
+static TSOCKS_INIT_MUTEX(connection_registry_mutex);
+
+/*
+ * Release connection using the given refcount located inside the connection
+ * object. This is ONLY called from the connection put reference. After this
+ * call, the connection object associated with that refcount object is freed.
+ */
+static void release_conn(struct ref *ref)
+{
+	struct connection *conn = container_of(ref, struct connection, refcount);
+	connection_destroy(conn);
+}
+
 /*
  * Return 0 if the two connections are equal else 1.
  */
@@ -68,6 +82,22 @@ HT_GENERATE(connection_registry, connection, node, conn_hash_fct,
 		conn_equal_fct, 0.5, malloc, realloc, free);
 
 /*
+ * Acquire connection registry mutex.
+ */
+void connection_registry_lock(void)
+{
+	tsocks_mutex_lock(&connection_registry_mutex);
+}
+
+/*
+ * Release connection registry mutex.
+ */
+void connection_registry_unlock(void)
+{
+	tsocks_mutex_unlock(&connection_registry_mutex);
+}
+
+/*
  * Initialize connection registry.
  */
 void connection_registry_init(void)
@@ -221,3 +251,20 @@ void connection_destroy(struct connection *conn)
 
 	free(conn);
 }
+
+/*
+ * Get a reference of the given connection object.
+ */
+void connection_get_ref(struct connection *c)
+{
+	ref_get(&c->refcount);
+}
+
+/*
+ * Put back a reference of the given connection object. If the refcount drops
+ * to 0, the release connection function is called which frees the object.
+ */
+void connection_put_ref(struct connection *c)
+{
+	ref_put(&c->refcount, release_conn);
+}
diff --git a/src/common/connection.h b/src/common/connection.h
index 058a1f6..d1163a9 100644
--- a/src/common/connection.h
+++ b/src/common/connection.h
@@ -24,6 +24,8 @@
 
 #include "defaults.h"
 #include "ht.h"
+#include "macros.h"
+#include "ref.h"
 
 enum connection_domain {
 	CONNECTION_DOMAIN_INET	= 1,
@@ -52,6 +54,13 @@ struct connection {
 	/* Remote destination that passes through Tor. */
 	struct connection_addr dest_addr;
 
+	/*
+	 * Object refcount needed to access this object outside the registry lock.
+	 * This is always initialized to 1 so only the destroy process can bring
+	 * the refcount to 0 so to delete it.
+	 */
+	struct ref refcount;
+
 	/* Hash table node. */
 	HT_ENTRY(connection) node;
 };
@@ -67,5 +76,10 @@ void connection_remove(struct connection *conn);
 void connection_insert(struct connection *conn);
 
 void connection_registry_init(void);
+void connection_registry_lock(void);
+void connection_registry_unlock(void);
+
+void connection_get_ref(struct connection *c);
+void connection_put_ref(struct connection *c);
 
 #endif /* TORSOCKS_CONNECTION_H */
diff --git a/src/common/macros.h b/src/common/macros.h
index 5702b2e..1e98fd6 100644
--- a/src/common/macros.h
+++ b/src/common/macros.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2013 - David Goulet <dgoulet at ev0ke.net>
+ * Copyright (c) 2009 - Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
+ *               2013 - David Goulet <dgoulet at ev0ke.net>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License, version 2 only, as
@@ -18,6 +19,21 @@
 #ifndef TORSOCKS_MACROS_H
 #define TORSOCKS_MACROS_H
 
+#include <stddef.h> /* for offsetof */
+
+/*
+ * container_of - Get the address of an object containing a field.
+ *
+ * @ptr: pointer to the field.
+ * @type: type of the object.
+ * @member: name of the field within the object.
+ */
+#define container_of(ptr, type, member)                            \
+    ({                                                             \
+        const __typeof__(((type *) NULL)->member) * __ptr = (ptr); \
+        (type *)((char *)__ptr - offsetof(type, member));          \
+    })
+
 /* Memory allocation zeroed. */
 #define zmalloc(x) calloc(1, x)
 
diff --git a/src/common/ref.h b/src/common/ref.h
new file mode 100644
index 0000000..e1ae6d9
--- /dev/null
+++ b/src/common/ref.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet at ev0ke.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TORSOCKS_REF_H
+#define TORSOCKS_REF_H
+
+struct ref {
+	long count;
+};
+
+#if (defined(__linux__) || defined(__FreeBSD__) || defined(__darwin__))
+
+/*
+ * Get a reference by incrementing the refcount.
+ */
+static inline void ref_get(struct ref *r)
+{
+	(void) __sync_add_and_fetch(&r->count, 1);
+}
+
+/*
+ * Put a reference back by decrementing the refcount.
+ *
+ * The release function MUST use container_of to get back the object pointer in
+ * which the ref structure is located.
+ */
+static inline void ref_put(struct ref *r,
+		void (*release)(struct ref *))
+{
+	long ret;
+
+	assert(release);
+	ret = __sync_sub_and_fetch(&r->count, 1);
+	assert(ret >= 0);
+	if (ret == 0) {
+		release(r);
+	}
+}
+
+#else
+#error "OS not supported"
+#endif /* __linux__, __FreeBSD__, __darwin__ */
+
+#endif /* TORSOCKS_REF_H */





More information about the tor-commits mailing list