summaryrefslogtreecommitdiffstats
path: root/src/server/reference.c
diff options
context:
space:
mode:
authorSimon Rettberg2019-08-27 16:13:07 +0200
committerSimon Rettberg2019-08-27 16:13:07 +0200
commit69f5bf408b9587a6e2008fba2224c2d506f1a895 (patch)
tree8fc9eda7e3a0b105007b7a85a4cc35ecc1d4431d /src/server/reference.c
parent[SERVER] Fix warnings, simplify locking (diff)
downloaddnbd3-69f5bf408b9587a6e2008fba2224c2d506f1a895.tar.gz
dnbd3-69f5bf408b9587a6e2008fba2224c2d506f1a895.tar.xz
dnbd3-69f5bf408b9587a6e2008fba2224c2d506f1a895.zip
[SERVER] Use reference counting for uplink
First step towards less locking for proxy mode
Diffstat (limited to 'src/server/reference.c')
-rw-r--r--src/server/reference.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/server/reference.c b/src/server/reference.c
new file mode 100644
index 0000000..468e00b
--- /dev/null
+++ b/src/server/reference.c
@@ -0,0 +1,33 @@
+#ifndef unlikely
+#define unlikely(x) (x)
+#endif
+#include "reference.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+void ref_init( ref *reference, void ( *freefun )( ref * ), long count )
+{
+ reference->count = count;
+ reference->free = freefun;
+}
+
+_Noreturn void _ref_error( const char *message )
+{
+ fprintf( stderr, "Reference counter overflow\n" );
+ abort();
+}
+
+void ref_setref( weakref *weakref, ref *ref )
+{
+ union _aligned_ref_ *new_weakref = 0;
+ if ( ref ) {
+ ( new_weakref = aligned_ref( ref->_aligned_ref ) )->ref = ref;
+ ref->count += sizeof( union _aligned_ref_ ) + 1;
+ }
+ char *old_weakref = (char *)atomic_exchange( weakref, new_weakref );
+ if ( !old_weakref )
+ return;
+ struct _ref_ *old_ref = aligned_ref( old_weakref )->ref;
+ old_ref->count += old_weakref - (char *)aligned_ref( old_weakref ) - sizeof( union _aligned_ref_ );
+ ref_put( old_ref );
+}