void AO_store_full_emulation(volatile AO_T *addr, AO_T val)
{
    AO_TS_T *my_lock = AO_locks + AO_HASH(addr);
    lock(my_lock);
    *addr = val;
    unlock(my_lock);
}
int AO_compare_and_swap_emulation(volatile AO_T *addr, AO_T old,
                                  AO_T new_val)
{
    AO_TS_T *my_lock = AO_locks + AO_HASH(addr);
    sigset_t old_sigs;
    int result;

    if (!AO_load_acquire(&initialized))
    {
        lock(&init_lock);
        if (!initialized) sigfillset(&all_sigs);
        unlock(&init_lock);
        AO_store_release(&initialized, 1);
    }
    sigprocmask(SIG_BLOCK, &all_sigs, &old_sigs);
    /* Neither sigprocmask nor pthread_sigmask is 100%	*/
    /* guaranteed to work here.  Sigprocmask is not 	*/
    /* guaranteed be thread safe, and pthread_sigmask	*/
    /* is not async-signal-safe.  Under linuxthreads,	*/
    /* sigprocmask may block some pthreads-internal		*/
    /* signals.  So long as we do that for short periods,	*/
    /* we should be OK.					*/
    lock(my_lock);
    if (*addr == old)
    {
        *addr = new_val;
        result = 1;
    }
    else
        result = 0;
    unlock(my_lock);
    sigprocmask(SIG_SETMASK, &old_sigs, NULL);
    return result;
}
Example #3
0
int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr,
                                                AO_t old_val1, AO_t old_val2,
                                                AO_t new_val1, AO_t new_val2)
{
  AO_TS_t *my_lock = AO_locks + AO_HASH(addr);
  int result;

# ifndef AO_USE_NO_SIGNALS
    sigset_t old_sigs;
    block_all_signals(&old_sigs);
# endif
  lock(my_lock);
  if (addr -> AO_val1 == old_val1 && addr -> AO_val2 == old_val2)
    {
      addr -> AO_val1 = new_val1;
      addr -> AO_val2 = new_val2;
      result = 1;
    }
  else
    result = 0;
  unlock(my_lock);
# ifndef AO_USE_NO_SIGNALS
    sigprocmask(SIG_SETMASK, &old_sigs, NULL);
# endif
  return result;
}
Example #4
0
AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr, AO_t old_val,
                                         AO_t new_val)
{
  AO_TS_t *my_lock = AO_locks + AO_HASH(addr);
  AO_t fetched_val;

# ifndef AO_USE_NO_SIGNALS
    sigset_t old_sigs;
    block_all_signals(&old_sigs);
# endif
  lock(my_lock);
  fetched_val = *addr;
  if (fetched_val == old_val)
    *addr = new_val;
  unlock(my_lock);
# ifndef AO_USE_NO_SIGNALS
    sigprocmask(SIG_SETMASK, &old_sigs, NULL);
# endif
  return fetched_val;
}
Example #5
0
int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr,
                                                AO_t old_val1, AO_t old_val2,
                                                AO_t new_val1, AO_t new_val2)
{
  AO_TS_t *my_lock = AO_locks + AO_HASH(addr);
  int result;

# ifndef AO_USE_NO_SIGNALS
    sigset_t old_sigs;
    if (!AO_load_acquire(&initialized))
    {
      lock(&init_lock);
      if (!initialized) sigfillset(&all_sigs);
      unlock(&init_lock);
      AO_store_release(&initialized, 1);
    }
    sigprocmask(SIG_BLOCK, &all_sigs, &old_sigs);
        /* Neither sigprocmask nor pthread_sigmask is 100%      */
        /* guaranteed to work here.  Sigprocmask is not         */
        /* guaranteed be thread safe, and pthread_sigmask       */
        /* is not async-signal-safe.  Under linuxthreads,       */
        /* sigprocmask may block some pthreads-internal         */
        /* signals.  So long as we do that for short periods,   */
        /* we should be OK.                                     */
# endif
  lock(my_lock);
  if (addr -> AO_val1 == old_val1 && addr -> AO_val2 == old_val2)
    {
      addr -> AO_val1 = new_val1;
      addr -> AO_val2 = new_val2;
      result = 1;
    }
  else
    result = 0;
  unlock(my_lock);
# ifndef AO_USE_NO_SIGNALS
    sigprocmask(SIG_SETMASK, &old_sigs, NULL);
# endif
  return result;
}