summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
9d8612b)
compat_arch_x86.c is linked into many .so and even into test programs.
The basic problem with this is that it contains a statically defined
mutex, which will fail to protect concurrent use of this compat code by
different shared objects.
Fix this by defining both the mutex (now called __urcu_x86_compat_mutex)
and __rcu_cas_avail as weak symbols. Therefore, the first symbol that
gets loaded in a program will by used by everyone.
Reported-by: Vladimir Nikulichev <nvs@tbricks.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
#include <assert.h>
#include <urcu/uatomic.h>
#include <assert.h>
#include <urcu/uatomic.h>
+/*
+ * Using attribute "weak" for __rcu_cas_avail and
+ * __urcu_x86_compat_mutex. Those are globally visible by the entire
+ * program, even though many shared objects may have their own version.
+ * The first version that gets loaded will be used by the entire
+ * program (executable and all shared objects).
+ */
+
/*
* It does not really matter if the constructor is called before using
* the library, as long as the caller checks if __rcu_cas_avail < 0 and calls
/*
* It does not really matter if the constructor is called before using
* the library, as long as the caller checks if __rcu_cas_avail < 0 and calls
* 1: available
* 0: unavailable
*/
* 1: available
* 0: unavailable
*/
int __rcu_cas_avail = -1;
int __rcu_cas_avail = -1;
-static pthread_mutex_t compat_mutex = PTHREAD_MUTEX_INITIALIZER;
+__attribute__((weak))
+pthread_mutex_t __urcu_x86_compat_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* get_eflags/set_eflags/compare_and_swap_is_available imported from glibc
/*
* get_eflags/set_eflags/compare_and_swap_is_available imported from glibc
assert(!ret);
ret = pthread_sigmask(SIG_BLOCK, &newmask, oldmask);
assert(!ret);
assert(!ret);
ret = pthread_sigmask(SIG_BLOCK, &newmask, oldmask);
assert(!ret);
- ret = pthread_mutex_lock(&compat_mutex);
+ ret = pthread_mutex_lock(&__urcu_x86_compat_mutex);
- ret = pthread_mutex_unlock(&compat_mutex);
+ ret = pthread_mutex_unlock(&__urcu_x86_compat_mutex);
assert(!ret);
ret = pthread_sigmask(SIG_SETMASK, oldmask, NULL);
assert(!ret);
assert(!ret);
ret = pthread_sigmask(SIG_SETMASK, oldmask, NULL);
assert(!ret);
sigset_t mask;
unsigned long result;
sigset_t mask;
unsigned long result;
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
switch (len) {
case 1:
*(unsigned char *)addr = (unsigned char)_new;
switch (len) {
case 1:
*(unsigned char *)addr = (unsigned char)_new;
result = 0;
__asm__ __volatile__("ud2");
}
result = 0;
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
sigset_t mask;
unsigned long retval;
sigset_t mask;
unsigned long retval;
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
switch (len) {
case 1:
retval = *(unsigned char *)addr;
switch (len) {
case 1:
retval = *(unsigned char *)addr;
retval = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
retval = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
unsigned long retval;
sigset_t mask;
unsigned long retval;
sigset_t mask;
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
retval = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
retval = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
switch (len) {
case 1:
*(unsigned char *)addr |= (unsigned char)v;
switch (len) {
case 1:
*(unsigned char *)addr |= (unsigned char)v;
*/
__asm__ __volatile__("ud2");
}
*/
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
}
void _compat_uatomic_and(void *addr, unsigned long v, int len)
{
sigset_t mask;
}
void _compat_uatomic_and(void *addr, unsigned long v, int len)
{
sigset_t mask;
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
switch (len) {
case 1:
*(unsigned char *)addr &= (unsigned char)v;
switch (len) {
case 1:
*(unsigned char *)addr &= (unsigned char)v;
*/
__asm__ __volatile__("ud2");
}
*/
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
}
unsigned long _compat_uatomic_add_return(void *addr, unsigned long v, int len)
}
unsigned long _compat_uatomic_add_return(void *addr, unsigned long v, int len)
sigset_t mask;
unsigned long result;
sigset_t mask;
unsigned long result;
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
switch (len) {
case 1:
*(unsigned char *)addr += (unsigned char)v;
switch (len) {
case 1:
*(unsigned char *)addr += (unsigned char)v;
result = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
result = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);