[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