diff options
author | Simon Rettberg | 2019-08-27 16:13:07 +0200 |
---|---|---|
committer | Simon Rettberg | 2019-08-27 16:13:07 +0200 |
commit | 69f5bf408b9587a6e2008fba2224c2d506f1a895 (patch) | |
tree | 8fc9eda7e3a0b105007b7a85a4cc35ecc1d4431d /src/server/reference.c | |
parent | [SERVER] Fix warnings, simplify locking (diff) | |
download | dnbd3-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.c | 33 |
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 ); +} |