projects
/
urcu.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fix: urcu-bp: Bulletproof RCU arena resize bug
[urcu.git]
/
urcu-bp.c
diff --git
a/urcu-bp.c
b/urcu-bp.c
index f3249b43b313decebc29e193b5c82ebf1114a735..f28ef89df4de7a6c5723c13f964d452aa72d5969 100644
(file)
--- a/
urcu-bp.c
+++ b/
urcu-bp.c
@@
-40,6
+40,9
@@
#include "urcu/map/urcu-bp.h"
#include "urcu/static/urcu-bp.h"
#include "urcu-pointer.h"
#include "urcu/map/urcu-bp.h"
#include "urcu/static/urcu-bp.h"
#include "urcu-pointer.h"
+#include "urcu/tls-compat.h"
+
+#include "urcu-die.h"
/* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
#undef _LGPL_SOURCE
/* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
#undef _LGPL_SOURCE
@@
-50,7
+53,14
@@
#define MAP_ANONYMOUS MAP_ANON
#endif
#define MAP_ANONYMOUS MAP_ANON
#endif
-#ifndef __linux__
+#ifdef __linux__
+static
+void *mremap_wrapper(void *old_address, size_t old_size,
+ size_t new_size, int flags)
+{
+ return mremap(old_address, old_size, new_size, flags);
+}
+#else
#define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2
#define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2
@@
-59,7
+69,9
@@
* mremap wrapper for non-Linux systems. Maps a RW, anonymous private mapping.
* This is not generic.
*/
* mremap wrapper for non-Linux systems. Maps a RW, anonymous private mapping.
* This is not generic.
*/
-void *mremap(void *old_address, size_t old_size, size_t new_size, int flags)
+static
+void *mremap_wrapper(void *old_address, size_t old_size,
+ size_t new_size, int flags)
{
void *new_address;
{
void *new_address;
@@
-94,7
+106,7
@@
static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
#ifdef DEBUG_YIELD
unsigned int yield_active;
#ifdef DEBUG_YIELD
unsigned int yield_active;
-
unsigned int __thread rand_yield
;
+
DEFINE_URCU_TLS(unsigned int, rand_yield)
;
#endif
/*
#endif
/*
@@
-109,7
+121,7
@@
long rcu_gp_ctr = RCU_GP_COUNT;
* Pointer to registry elements. Written to only by each individual reader. Read
* by both the reader and the writers.
*/
* Pointer to registry elements. Written to only by each individual reader. Read
* by both the reader and the writers.
*/
-
struct rcu_reader __thread *rcu_reader
;
+
DEFINE_URCU_TLS(struct rcu_reader *, rcu_reader)
;
static CDS_LIST_HEAD(registry);
static CDS_LIST_HEAD(registry);
@@
-132,17
+144,12
@@
static void mutex_lock(pthread_mutex_t *mutex)
#ifndef DISTRUST_SIGNALS_EXTREME
ret = pthread_mutex_lock(mutex);
#ifndef DISTRUST_SIGNALS_EXTREME
ret = pthread_mutex_lock(mutex);
- if (ret) {
- perror("Error in pthread mutex lock");
- exit(-1);
- }
+ if (ret)
+ urcu_die(ret);
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
while ((ret = pthread_mutex_trylock(mutex)) != 0) {
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
while ((ret = pthread_mutex_trylock(mutex)) != 0) {
- if (ret != EBUSY && ret != EINTR) {
- printf("ret = %d, errno = %d\n", ret, errno);
- perror("Error in pthread mutex lock");
- exit(-1);
- }
+ if (ret != EBUSY && ret != EINTR)
+ urcu_die(ret);
poll(NULL,0,10);
}
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
poll(NULL,0,10);
}
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
@@
-153,10
+160,8
@@
static void mutex_unlock(pthread_mutex_t *mutex)
int ret;
ret = pthread_mutex_unlock(mutex);
int ret;
ret = pthread_mutex_unlock(mutex);
- if (ret) {
- perror("Error in pthread mutex unlock");
- exit(-1);
- }
+ if (ret)
+ urcu_die(ret);
}
void update_counter_and_wait(void)
}
void update_counter_and_wait(void)
@@
-210,9
+215,9
@@
void synchronize_rcu(void)
sigset_t newmask, oldmask;
int ret;
sigset_t newmask, oldmask;
int ret;
- ret = sig
empty
set(&newmask);
+ ret = sig
fill
set(&newmask);
assert(!ret);
assert(!ret);
- ret = pthread_sigmask(SIG_
SETMAS
K, &newmask, &oldmask);
+ ret = pthread_sigmask(SIG_
BLOC
K, &newmask, &oldmask);
assert(!ret);
mutex_lock(&rcu_gp_lock);
assert(!ret);
mutex_lock(&rcu_gp_lock);
@@
-275,26
+280,37
@@
void rcu_read_unlock(void)
*/
static void resize_arena(struct registry_arena *arena, size_t len)
{
*/
static void resize_arena(struct registry_arena *arena, size_t len)
{
- void *new_arena;
+ void *new_p;
+ size_t old_len;
+
+ old_len = arena->len;
if (!arena->p)
if (!arena->p)
- new_
arena
= mmap(arena->p, len,
-
PROT_READ | PROT_WRITE,
-
MAP_ANONYMOUS | MAP_PRIVATE,
-
-1, 0);
+ new_
p
= mmap(arena->p, len,
+ PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE,
+ -1, 0);
else
else
- new_
arena = mremap(arena->p, arena->
len,
-
len, MREMAP_MAYMOVE);
- assert(new_
arena
!= MAP_FAILED);
+ new_
p = mremap_wrapper(arena->p, old_
len,
+ len, MREMAP_MAYMOVE);
+ assert(new_
p
!= MAP_FAILED);
/*
/*
- * re-used the same region ?
+ * Zero the newly allocated memory. Since mmap() does not
+ * clearly specify if memory is zeroed or not (although it is
+ * very likely that it is), be extra careful by not expecting
+ * the new range to be zeroed by mremap.
*/
*/
- if (new_arena == arena->p)
- return;
+ bzero(new_p + old_len, len - old_len);
- bzero(new_arena + arena->len, len - arena->len);
- arena->p = new_arena;
+ /*
+ * If we did not re-use the same region, we need to update the
+ * arena pointer.
+ */
+ if (new_p != arena->p)
+ arena->p = new_p;
+
+ arena->len = len;
}
/* Called with signals off and mutex locked */
}
/* Called with signals off and mutex locked */
@@
-322,7
+338,7
@@
static void add_thread(void)
rcu_reader_reg->tid = pthread_self();
assert(rcu_reader_reg->ctr == 0);
cds_list_add(&rcu_reader_reg->node, ®istry);
rcu_reader_reg->tid = pthread_self();
assert(rcu_reader_reg->ctr == 0);
cds_list_add(&rcu_reader_reg->node, ®istry);
-
rcu_reader
= rcu_reader_reg;
+
URCU_TLS(rcu_reader)
= rcu_reader_reg;
}
/* Called with signals off and mutex locked */
}
/* Called with signals off and mutex locked */
@@
-355,15
+371,15
@@
void rcu_bp_register(void)
sigset_t newmask, oldmask;
int ret;
sigset_t newmask, oldmask;
int ret;
- ret = sig
empty
set(&newmask);
+ ret = sig
fill
set(&newmask);
assert(!ret);
assert(!ret);
- ret = pthread_sigmask(SIG_
SETMAS
K, &newmask, &oldmask);
+ ret = pthread_sigmask(SIG_
BLOC
K, &newmask, &oldmask);
assert(!ret);
/*
* Check if a signal concurrently registered our thread since
* the check in rcu_read_lock(). */
assert(!ret);
/*
* Check if a signal concurrently registered our thread since
* the check in rcu_read_lock(). */
- if (
rcu_reader
)
+ if (
URCU_TLS(rcu_reader)
)
goto end;
mutex_lock(&rcu_gp_lock);
goto end;
mutex_lock(&rcu_gp_lock);
@@
-390,9
+406,9
@@
void rcu_bp_before_fork(void)
sigset_t newmask, oldmask;
int ret;
sigset_t newmask, oldmask;
int ret;
- ret = sig
empty
set(&newmask);
+ ret = sig
fill
set(&newmask);
assert(!ret);
assert(!ret);
- ret = pthread_sigmask(SIG_
SETMAS
K, &newmask, &oldmask);
+ ret = pthread_sigmask(SIG_
BLOC
K, &newmask, &oldmask);
assert(!ret);
mutex_lock(&rcu_gp_lock);
saved_fork_signal_mask = oldmask;
assert(!ret);
mutex_lock(&rcu_gp_lock);
saved_fork_signal_mask = oldmask;
@@
-429,7
+445,8
@@
void *rcu_dereference_sym_bp(void *p)
void *rcu_set_pointer_sym_bp(void **p, void *v)
{
cmm_wmb();
void *rcu_set_pointer_sym_bp(void **p, void *v)
{
cmm_wmb();
- return uatomic_set(p, v);
+ uatomic_set(p, v);
+ return v;
}
void *rcu_xchg_pointer_sym_bp(void **p, void *v)
}
void *rcu_xchg_pointer_sym_bp(void **p, void *v)
@@
-444,5
+461,7
@@
void *rcu_cmpxchg_pointer_sym_bp(void **p, void *old, void *_new)
return uatomic_cmpxchg(p, old, _new);
}
return uatomic_cmpxchg(p, old, _new);
}
+DEFINE_RCU_FLAVOR(rcu_flavor);
+
#include "urcu-call-rcu-impl.h"
#include "urcu-defer-impl.h"
#include "urcu-call-rcu-impl.h"
#include "urcu-defer-impl.h"
This page took
0.025892 seconds
and
4
git commands to generate.