#include <pthread.h>
#include <signal.h>
#include <assert.h>
-#include <urcu/uatomic_arch.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
* 1: available
* 0: unavailable
*/
+__attribute__((weak))
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
int ret;
/* Disable signals */
- ret = sigemptyset(&newmask);
+ ret = sigfillset(&newmask);
assert(!ret);
- ret = pthread_sigmask(SIG_SETMASK, &newmask, oldmask);
+ ret = pthread_sigmask(SIG_BLOCK, &newmask, oldmask);
assert(!ret);
- ret = pthread_mutex_lock(&compat_mutex);
+ ret = pthread_mutex_lock(&__urcu_x86_compat_mutex);
assert(!ret);
}
{
int ret;
- 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);
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;
* generate an illegal instruction. Cannot catch this with
* linker tricks when optimizations are disabled.
*/
+ result = 0;
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
- return _new;
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
+ return result;
}
unsigned long _compat_uatomic_xchg(void *addr, unsigned long _new, int len)
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;
* generate an illegal instruction. Cannot catch this with
* linker tricks when optimizations are disabled.
*/
+ retval = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
return retval;
}
unsigned long retval;
sigset_t mask;
- mutex_lock_signal_save(&compat_mutex, &mask);
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
switch (len) {
case 1:
{
* generate an illegal instruction. Cannot catch this with
* linker tricks when optimizations are disabled.
*/
+ retval = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
return retval;
}
{
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;
*/
__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;
+
+ mutex_lock_signal_save(&__urcu_x86_compat_mutex, &mask);
+ switch (len) {
+ case 1:
+ *(unsigned char *)addr &= (unsigned char)v;
+ break;
+ case 2:
+ *(unsigned short *)addr &= (unsigned short)v;
+ break;
+ case 4:
+ *(unsigned int *)addr &= (unsigned int)v;
+ break;
+ default:
+ /*
+ * generate an illegal instruction. Cannot catch this with
+ * linker tricks when optimizations are disabled.
+ */
+ __asm__ __volatile__("ud2");
+ }
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
}
unsigned long _compat_uatomic_add_return(void *addr, unsigned long v, int len)
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;
* generate an illegal instruction. Cannot catch this with
* linker tricks when optimizations are disabled.
*/
+ result = 0; /* silence gcc warnings */
__asm__ __volatile__("ud2");
}
- mutex_lock_signal_restore(&compat_mutex, &mask);
+ mutex_lock_signal_restore(&__urcu_x86_compat_mutex, &mask);
return result;
}