void __assert_fail (const char *assertion, const char *file, unsigned int line, const char *function) { char *buf; #ifdef FATAL_PREPARE FATAL_PREPARE; #endif if (__asprintf (&buf, _("%s%s%s:%u: %s%sAssertion `%s' failed.\n"), __progname, __progname[0] ? ": " : "", file, line, function ? function : "", function ? ": " : "", assertion) >= 0) { /* Print the message. */ (void) __fxprintf (NULL, "%s", buf); (void) fflush (stderr); /* We have to free the old buffer since the application might catch the SIGABRT signal. */ char *old = atomic_exchange_acq (&__abort_msg, buf); free (old); } else { /* At least print a minimal message. */ static const char errstr[] = "Unexpected error.\n"; __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); } abort (); }
void __lll_lock_wait_private (int *futex) { if (*futex == 2) lll_futex_wait (futex, 2, LLL_PRIVATE); while (atomic_exchange_acq (futex, 2) != 0) lll_futex_wait (futex, 2, LLL_PRIVATE); }
void __assert_fail_base (const char *fmt, const char *assertion, const char *file, unsigned int line, const char *function) { char *str; #ifdef FATAL_PREPARE FATAL_PREPARE; #endif int total; if (__asprintf (&str, fmt, __progname, __progname[0] ? ": " : "", file, line, function ? function : "", function ? ": " : "", assertion, &total) >= 0) { /* Print the message. */ (void) __fxprintf (NULL, "%s", str); (void) fflush (stderr); total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (__builtin_expect (buf != MAP_FAILED, 1)) { buf->size = total; strcpy (buf->msg, str); /* We have to free the old buffer since the application might catch the SIGABRT signal. */ struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, buf); if (old != NULL) __munmap (old, old->size); } free (str); } else { /* At least print a minimal message. */ static const char errstr[] = "Unexpected error.\n"; __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); } abort (); }
int pthread_spin_lock (pthread_spinlock_t *lock) { /* atomic_exchange usually takes less instructions than atomic_compare_and_exchange. On the other hand, atomic_compare_and_exchange potentially generates less bus traffic when the lock is locked. We assume that the first try mostly will be successful, and we use atomic_exchange. For the subsequent tries we use atomic_compare_and_exchange. */ if (atomic_exchange_acq (lock, 1) == 0) return 0; do { /* The lock is contended and we need to wait. Going straight back to cmpxchg is not a good idea on many targets as that will force expensive memory synchronizations among processors and penalize other running threads. On the other hand, we do want to update memory state on the local core once in a while to avoid spinning indefinitely until some event that will happen to update local memory as a side-effect. */ if (SPIN_LOCK_READS_BETWEEN_CMPXCHG >= 0) { int wait = SPIN_LOCK_READS_BETWEEN_CMPXCHG; while (*lock != 0 && wait > 0) --wait; } else { while (*lock != 0) ; } } while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0); return 0; }
int pthread_spin_trylock (pthread_spinlock_t *lock) { return atomic_exchange_acq (lock, 1) ? EBUSY : 0; }
/* Test various atomic.h macros. */ static int do_test (void) { atomic_t mem, expected; int ret = 0; #ifdef atomic_compare_and_exchange_val_acq mem = 24; if (atomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24 || mem != 35) { puts ("atomic_compare_and_exchange_val_acq test 1 failed"); ret = 1; } mem = 12; if (atomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12 || mem != 12) { puts ("atomic_compare_and_exchange_val_acq test 2 failed"); ret = 1; } mem = -15; if (atomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15 || mem != -56) { puts ("atomic_compare_and_exchange_val_acq test 3 failed"); ret = 1; } mem = -1; if (atomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1 || mem != -1) { puts ("atomic_compare_and_exchange_val_acq test 4 failed"); ret = 1; } #endif mem = 24; if (atomic_compare_and_exchange_bool_acq (&mem, 35, 24) || mem != 35) { puts ("atomic_compare_and_exchange_bool_acq test 1 failed"); ret = 1; } mem = 12; if (! atomic_compare_and_exchange_bool_acq (&mem, 10, 15) || mem != 12) { puts ("atomic_compare_and_exchange_bool_acq test 2 failed"); ret = 1; } mem = -15; if (atomic_compare_and_exchange_bool_acq (&mem, -56, -15) || mem != -56) { puts ("atomic_compare_and_exchange_bool_acq test 3 failed"); ret = 1; } mem = -1; if (! atomic_compare_and_exchange_bool_acq (&mem, 17, 0) || mem != -1) { puts ("atomic_compare_and_exchange_bool_acq test 4 failed"); ret = 1; } mem = 64; if (atomic_exchange_acq (&mem, 31) != 64 || mem != 31) { puts ("atomic_exchange_acq test failed"); ret = 1; } mem = 2; if (atomic_exchange_and_add (&mem, 11) != 2 || mem != 13) { puts ("atomic_exchange_and_add test failed"); ret = 1; } mem = 2; if (atomic_exchange_and_add_acq (&mem, 11) != 2 || mem != 13) { puts ("atomic_exchange_and_add test failed"); ret = 1; } mem = 2; if (atomic_exchange_and_add_rel (&mem, 11) != 2 || mem != 13) { puts ("atomic_exchange_and_add test failed"); ret = 1; } mem = -21; atomic_add (&mem, 22); if (mem != 1) { puts ("atomic_add test failed"); ret = 1; } mem = -1; atomic_increment (&mem); if (mem != 0) { puts ("atomic_increment test failed"); ret = 1; } mem = 2; if (atomic_increment_val (&mem) != 3) { puts ("atomic_increment_val test failed"); ret = 1; } mem = 0; if (atomic_increment_and_test (&mem) || mem != 1) { puts ("atomic_increment_and_test test 1 failed"); ret = 1; } mem = 35; if (atomic_increment_and_test (&mem) || mem != 36) { puts ("atomic_increment_and_test test 2 failed"); ret = 1; } mem = -1; if (! atomic_increment_and_test (&mem) || mem != 0) { puts ("atomic_increment_and_test test 3 failed"); ret = 1; } mem = 17; atomic_decrement (&mem); if (mem != 16) { puts ("atomic_decrement test failed"); ret = 1; } if (atomic_decrement_val (&mem) != 15) { puts ("atomic_decrement_val test failed"); ret = 1; } mem = 0; if (atomic_decrement_and_test (&mem) || mem != -1) { puts ("atomic_decrement_and_test test 1 failed"); ret = 1; } mem = 15; if (atomic_decrement_and_test (&mem) || mem != 14) { puts ("atomic_decrement_and_test test 2 failed"); ret = 1; } mem = 1; if (! atomic_decrement_and_test (&mem) || mem != 0) { puts ("atomic_decrement_and_test test 3 failed"); ret = 1; } mem = 1; if (atomic_decrement_if_positive (&mem) != 1 || mem != 0) { puts ("atomic_decrement_if_positive test 1 failed"); ret = 1; } mem = 0; if (atomic_decrement_if_positive (&mem) != 0 || mem != 0) { puts ("atomic_decrement_if_positive test 2 failed"); ret = 1; } mem = -1; if (atomic_decrement_if_positive (&mem) != -1 || mem != -1) { puts ("atomic_decrement_if_positive test 3 failed"); ret = 1; } mem = -12; if (! atomic_add_negative (&mem, 10) || mem != -2) { puts ("atomic_add_negative test 1 failed"); ret = 1; } mem = 0; if (atomic_add_negative (&mem, 100) || mem != 100) { puts ("atomic_add_negative test 2 failed"); ret = 1; } mem = 15; if (atomic_add_negative (&mem, -10) || mem != 5) { puts ("atomic_add_negative test 3 failed"); ret = 1; } mem = -12; if (atomic_add_negative (&mem, 14) || mem != 2) { puts ("atomic_add_negative test 4 failed"); ret = 1; } mem = 0; if (! atomic_add_negative (&mem, -1) || mem != -1) { puts ("atomic_add_negative test 5 failed"); ret = 1; } mem = -31; if (atomic_add_negative (&mem, 31) || mem != 0) { puts ("atomic_add_negative test 6 failed"); ret = 1; } mem = -34; if (atomic_add_zero (&mem, 31) || mem != -3) { puts ("atomic_add_zero test 1 failed"); ret = 1; } mem = -36; if (! atomic_add_zero (&mem, 36) || mem != 0) { puts ("atomic_add_zero test 2 failed"); ret = 1; } mem = 113; if (atomic_add_zero (&mem, -13) || mem != 100) { puts ("atomic_add_zero test 3 failed"); ret = 1; } mem = -18; if (atomic_add_zero (&mem, 20) || mem != 2) { puts ("atomic_add_zero test 4 failed"); ret = 1; } mem = 10; if (atomic_add_zero (&mem, -20) || mem != -10) { puts ("atomic_add_zero test 5 failed"); ret = 1; } mem = 10; if (! atomic_add_zero (&mem, -10) || mem != 0) { puts ("atomic_add_zero test 6 failed"); ret = 1; } mem = 0; atomic_bit_set (&mem, 1); if (mem != 2) { puts ("atomic_bit_set test 1 failed"); ret = 1; } mem = 8; atomic_bit_set (&mem, 3); if (mem != 8) { puts ("atomic_bit_set test 2 failed"); ret = 1; } #ifdef TEST_ATOMIC64 mem = 16; atomic_bit_set (&mem, 35); if (mem != 0x800000010LL) { puts ("atomic_bit_set test 3 failed"); ret = 1; } #endif mem = 0; if (atomic_bit_test_set (&mem, 1) || mem != 2) { puts ("atomic_bit_test_set test 1 failed"); ret = 1; } mem = 8; if (! atomic_bit_test_set (&mem, 3) || mem != 8) { puts ("atomic_bit_test_set test 2 failed"); ret = 1; } #ifdef TEST_ATOMIC64 mem = 16; if (atomic_bit_test_set (&mem, 35) || mem != 0x800000010LL) { puts ("atomic_bit_test_set test 3 failed"); ret = 1; } mem = 0x100000000LL; if (! atomic_bit_test_set (&mem, 32) || mem != 0x100000000LL) { puts ("atomic_bit_test_set test 4 failed"); ret = 1; } #endif #ifdef catomic_compare_and_exchange_val_acq mem = 24; if (catomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24 || mem != 35) { puts ("catomic_compare_and_exchange_val_acq test 1 failed"); ret = 1; } mem = 12; if (catomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12 || mem != 12) { puts ("catomic_compare_and_exchange_val_acq test 2 failed"); ret = 1; } mem = -15; if (catomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15 || mem != -56) { puts ("catomic_compare_and_exchange_val_acq test 3 failed"); ret = 1; } mem = -1; if (catomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1 || mem != -1) { puts ("catomic_compare_and_exchange_val_acq test 4 failed"); ret = 1; } #endif mem = 24; if (catomic_compare_and_exchange_bool_acq (&mem, 35, 24) || mem != 35) { puts ("catomic_compare_and_exchange_bool_acq test 1 failed"); ret = 1; } mem = 12; if (! catomic_compare_and_exchange_bool_acq (&mem, 10, 15) || mem != 12) { puts ("catomic_compare_and_exchange_bool_acq test 2 failed"); ret = 1; } mem = -15; if (catomic_compare_and_exchange_bool_acq (&mem, -56, -15) || mem != -56) { puts ("catomic_compare_and_exchange_bool_acq test 3 failed"); ret = 1; } mem = -1; if (! catomic_compare_and_exchange_bool_acq (&mem, 17, 0) || mem != -1) { puts ("catomic_compare_and_exchange_bool_acq test 4 failed"); ret = 1; } mem = 2; if (catomic_exchange_and_add (&mem, 11) != 2 || mem != 13) { puts ("catomic_exchange_and_add test failed"); ret = 1; } mem = -21; catomic_add (&mem, 22); if (mem != 1) { puts ("catomic_add test failed"); ret = 1; } mem = -1; catomic_increment (&mem); if (mem != 0) { puts ("catomic_increment test failed"); ret = 1; } mem = 2; if (catomic_increment_val (&mem) != 3) { puts ("catomic_increment_val test failed"); ret = 1; } mem = 17; catomic_decrement (&mem); if (mem != 16) { puts ("catomic_decrement test failed"); ret = 1; } if (catomic_decrement_val (&mem) != 15) { puts ("catomic_decrement_val test failed"); ret = 1; } /* Tests for C11-like atomics. */ mem = 11; if (atomic_load_relaxed (&mem) != 11 || atomic_load_acquire (&mem) != 11) { puts ("atomic_load_{relaxed,acquire} test failed"); ret = 1; } atomic_store_relaxed (&mem, 12); if (mem != 12) { puts ("atomic_store_relaxed test failed"); ret = 1; } atomic_store_release (&mem, 13); if (mem != 13) { puts ("atomic_store_release test failed"); ret = 1; } mem = 14; expected = 14; if (!atomic_compare_exchange_weak_relaxed (&mem, &expected, 25) || mem != 25 || expected != 14) { puts ("atomic_compare_exchange_weak_relaxed test 1 failed"); ret = 1; } if (atomic_compare_exchange_weak_relaxed (&mem, &expected, 14) || mem != 25 || expected != 25) { puts ("atomic_compare_exchange_weak_relaxed test 2 failed"); ret = 1; } mem = 14; expected = 14; if (!atomic_compare_exchange_weak_acquire (&mem, &expected, 25) || mem != 25 || expected != 14) { puts ("atomic_compare_exchange_weak_acquire test 1 failed"); ret = 1; } if (atomic_compare_exchange_weak_acquire (&mem, &expected, 14) || mem != 25 || expected != 25) { puts ("atomic_compare_exchange_weak_acquire test 2 failed"); ret = 1; } mem = 14; expected = 14; if (!atomic_compare_exchange_weak_release (&mem, &expected, 25) || mem != 25 || expected != 14) { puts ("atomic_compare_exchange_weak_release test 1 failed"); ret = 1; } if (atomic_compare_exchange_weak_release (&mem, &expected, 14) || mem != 25 || expected != 25) { puts ("atomic_compare_exchange_weak_release test 2 failed"); ret = 1; } mem = 23; if (atomic_exchange_acquire (&mem, 42) != 23 || mem != 42) { puts ("atomic_exchange_acquire test failed"); ret = 1; } mem = 23; if (atomic_exchange_release (&mem, 42) != 23 || mem != 42) { puts ("atomic_exchange_release test failed"); ret = 1; } mem = 23; if (atomic_fetch_add_relaxed (&mem, 1) != 23 || mem != 24) { puts ("atomic_fetch_add_relaxed test failed"); ret = 1; } mem = 23; if (atomic_fetch_add_acquire (&mem, 1) != 23 || mem != 24) { puts ("atomic_fetch_add_acquire test failed"); ret = 1; } mem = 23; if (atomic_fetch_add_release (&mem, 1) != 23 || mem != 24) { puts ("atomic_fetch_add_release test failed"); ret = 1; } mem = 23; if (atomic_fetch_add_acq_rel (&mem, 1) != 23 || mem != 24) { puts ("atomic_fetch_add_acq_rel test failed"); ret = 1; } mem = 3; if (atomic_fetch_and_acquire (&mem, 2) != 3 || mem != 2) { puts ("atomic_fetch_and_acquire test failed"); ret = 1; } mem = 4; if (atomic_fetch_or_relaxed (&mem, 2) != 4 || mem != 6) { puts ("atomic_fetch_or_relaxed test failed"); ret = 1; } mem = 4; if (atomic_fetch_or_acquire (&mem, 2) != 4 || mem != 6) { puts ("atomic_fetch_or_acquire test failed"); ret = 1; } /* This is a single-threaded test, so we can't test the effects of the fences. */ atomic_thread_fence_acquire (); atomic_thread_fence_release (); atomic_thread_fence_seq_cst (); return ret; }
/* Test various atomic.h macros. */ static int do_test (void) { atomic_t mem; int ret = 0; #ifdef atomic_compare_and_exchange_val_acq mem = 24; if (atomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24 || mem != 35) { puts ("atomic_compare_and_exchange_val_acq test 1 failed"); ret = 1; } mem = 12; if (atomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12 || mem != 12) { puts ("atomic_compare_and_exchange_val_acq test 2 failed"); ret = 1; } mem = -15; if (atomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15 || mem != -56) { puts ("atomic_compare_and_exchange_val_acq test 3 failed"); ret = 1; } mem = -1; if (atomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1 || mem != -1) { puts ("atomic_compare_and_exchange_val_acq test 4 failed"); ret = 1; } #endif mem = 24; if (atomic_compare_and_exchange_bool_acq (&mem, 35, 24) || mem != 35) { puts ("atomic_compare_and_exchange_bool_acq test 1 failed"); ret = 1; } mem = 12; if (! atomic_compare_and_exchange_bool_acq (&mem, 10, 15) || mem != 12) { puts ("atomic_compare_and_exchange_bool_acq test 2 failed"); ret = 1; } mem = -15; if (atomic_compare_and_exchange_bool_acq (&mem, -56, -15) || mem != -56) { puts ("atomic_compare_and_exchange_bool_acq test 3 failed"); ret = 1; } mem = -1; if (! atomic_compare_and_exchange_bool_acq (&mem, 17, 0) || mem != -1) { puts ("atomic_compare_and_exchange_bool_acq test 4 failed"); ret = 1; } mem = 64; if (atomic_exchange_acq (&mem, 31) != 64 || mem != 31) { puts ("atomic_exchange_acq test failed"); ret = 1; } mem = 2; if (atomic_exchange_and_add (&mem, 11) != 2 || mem != 13) { puts ("atomic_exchange_and_add test failed"); ret = 1; } mem = -21; atomic_add (&mem, 22); if (mem != 1) { puts ("atomic_add test failed"); ret = 1; } mem = -1; atomic_increment (&mem); if (mem != 0) { puts ("atomic_increment test failed"); ret = 1; } mem = 2; if (atomic_increment_val (&mem) != 3) { puts ("atomic_increment_val test failed"); ret = 1; } mem = 0; if (atomic_increment_and_test (&mem) || mem != 1) { puts ("atomic_increment_and_test test 1 failed"); ret = 1; } mem = 35; if (atomic_increment_and_test (&mem) || mem != 36) { puts ("atomic_increment_and_test test 2 failed"); ret = 1; } mem = -1; if (! atomic_increment_and_test (&mem) || mem != 0) { puts ("atomic_increment_and_test test 3 failed"); ret = 1; } mem = 17; atomic_decrement (&mem); if (mem != 16) { puts ("atomic_decrement test failed"); ret = 1; } if (atomic_decrement_val (&mem) != 15) { puts ("atomic_decrement_val test failed"); ret = 1; } mem = 0; if (atomic_decrement_and_test (&mem) || mem != -1) { puts ("atomic_decrement_and_test test 1 failed"); ret = 1; } mem = 15; if (atomic_decrement_and_test (&mem) || mem != 14) { puts ("atomic_decrement_and_test test 2 failed"); ret = 1; } mem = 1; if (! atomic_decrement_and_test (&mem) || mem != 0) { puts ("atomic_decrement_and_test test 3 failed"); ret = 1; } mem = 1; if (atomic_decrement_if_positive (&mem) != 1 || mem != 0) { puts ("atomic_decrement_if_positive test 1 failed"); ret = 1; } mem = 0; if (atomic_decrement_if_positive (&mem) != 0 || mem != 0) { puts ("atomic_decrement_if_positive test 2 failed"); ret = 1; } mem = -1; if (atomic_decrement_if_positive (&mem) != -1 || mem != -1) { puts ("atomic_decrement_if_positive test 3 failed"); ret = 1; } mem = -12; if (! atomic_add_negative (&mem, 10) || mem != -2) { puts ("atomic_add_negative test 1 failed"); ret = 1; } mem = 0; if (atomic_add_negative (&mem, 100) || mem != 100) { puts ("atomic_add_negative test 2 failed"); ret = 1; } mem = 15; if (atomic_add_negative (&mem, -10) || mem != 5) { puts ("atomic_add_negative test 3 failed"); ret = 1; } mem = -12; if (atomic_add_negative (&mem, 14) || mem != 2) { puts ("atomic_add_negative test 4 failed"); ret = 1; } mem = 0; if (! atomic_add_negative (&mem, -1) || mem != -1) { puts ("atomic_add_negative test 5 failed"); ret = 1; } mem = -31; if (atomic_add_negative (&mem, 31) || mem != 0) { puts ("atomic_add_negative test 6 failed"); ret = 1; } mem = -34; if (atomic_add_zero (&mem, 31) || mem != -3) { puts ("atomic_add_zero test 1 failed"); ret = 1; } mem = -36; if (! atomic_add_zero (&mem, 36) || mem != 0) { puts ("atomic_add_zero test 2 failed"); ret = 1; } mem = 113; if (atomic_add_zero (&mem, -13) || mem != 100) { puts ("atomic_add_zero test 3 failed"); ret = 1; } mem = -18; if (atomic_add_zero (&mem, 20) || mem != 2) { puts ("atomic_add_zero test 4 failed"); ret = 1; } mem = 10; if (atomic_add_zero (&mem, -20) || mem != -10) { puts ("atomic_add_zero test 5 failed"); ret = 1; } mem = 10; if (! atomic_add_zero (&mem, -10) || mem != 0) { puts ("atomic_add_zero test 6 failed"); ret = 1; } mem = 0; atomic_bit_set (&mem, 1); if (mem != 2) { puts ("atomic_bit_set test 1 failed"); ret = 1; } mem = 8; atomic_bit_set (&mem, 3); if (mem != 8) { puts ("atomic_bit_set test 2 failed"); ret = 1; } #ifdef TEST_ATOMIC64 mem = 16; atomic_bit_set (&mem, 35); if (mem != 0x800000010LL) { puts ("atomic_bit_set test 3 failed"); ret = 1; } #endif mem = 0; if (atomic_bit_test_set (&mem, 1) || mem != 2) { puts ("atomic_bit_test_set test 1 failed"); ret = 1; } mem = 8; if (! atomic_bit_test_set (&mem, 3) || mem != 8) { puts ("atomic_bit_test_set test 2 failed"); ret = 1; } #ifdef TEST_ATOMIC64 mem = 16; if (atomic_bit_test_set (&mem, 35) || mem != 0x800000010LL) { puts ("atomic_bit_test_set test 3 failed"); ret = 1; } mem = 0x100000000LL; if (! atomic_bit_test_set (&mem, 32) || mem != 0x100000000LL) { puts ("atomic_bit_test_set test 4 failed"); ret = 1; } #endif #ifdef catomic_compare_and_exchange_val_acq mem = 24; if (catomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24 || mem != 35) { puts ("catomic_compare_and_exchange_val_acq test 1 failed"); ret = 1; } mem = 12; if (catomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12 || mem != 12) { puts ("catomic_compare_and_exchange_val_acq test 2 failed"); ret = 1; } mem = -15; if (catomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15 || mem != -56) { puts ("catomic_compare_and_exchange_val_acq test 3 failed"); ret = 1; } mem = -1; if (catomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1 || mem != -1) { puts ("catomic_compare_and_exchange_val_acq test 4 failed"); ret = 1; } #endif mem = 24; if (catomic_compare_and_exchange_bool_acq (&mem, 35, 24) || mem != 35) { puts ("catomic_compare_and_exchange_bool_acq test 1 failed"); ret = 1; } mem = 12; if (! catomic_compare_and_exchange_bool_acq (&mem, 10, 15) || mem != 12) { puts ("catomic_compare_and_exchange_bool_acq test 2 failed"); ret = 1; } mem = -15; if (catomic_compare_and_exchange_bool_acq (&mem, -56, -15) || mem != -56) { puts ("catomic_compare_and_exchange_bool_acq test 3 failed"); ret = 1; } mem = -1; if (! catomic_compare_and_exchange_bool_acq (&mem, 17, 0) || mem != -1) { puts ("catomic_compare_and_exchange_bool_acq test 4 failed"); ret = 1; } mem = 2; if (catomic_exchange_and_add (&mem, 11) != 2 || mem != 13) { puts ("catomic_exchange_and_add test failed"); ret = 1; } mem = -21; catomic_add (&mem, 22); if (mem != 1) { puts ("catomic_add test failed"); ret = 1; } mem = -1; catomic_increment (&mem); if (mem != 0) { puts ("catomic_increment test failed"); ret = 1; } mem = 2; if (catomic_increment_val (&mem) != 3) { puts ("catomic_increment_val test failed"); ret = 1; } mem = 17; catomic_decrement (&mem); if (mem != 16) { puts ("catomic_decrement test failed"); ret = 1; } if (catomic_decrement_val (&mem) != 15) { puts ("catomic_decrement_val test failed"); ret = 1; } return ret; }
static int do_clone (struct pthread *pd, const struct pthread_attr *attr, int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, int stopped) { #ifdef PREPARE_CREATE PREPARE_CREATE; #endif if (__builtin_expect (stopped != 0, 0)) /* We make sure the thread does not run far by forcing it to get a lock. We lock it here too so that the new thread cannot continue until we tell it to. */ lll_lock (pd->lock, LLL_PRIVATE); /* One more thread. We cannot have the thread do this itself, since it might exist but not have been scheduled yet by the time we've returned and need to check the value to behave correctly. We must do it before creating the thread, in case it does get scheduled first and then might mistakenly think it was the only thread. In the failure case, we momentarily store a false value; this doesn't matter because there is no kosher thing a signal handler interrupting us right here can do that cares whether the thread count is correct. */ atomic_increment (&__nptl_nthreads); int rc = ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, pd, &pd->tid, TLS_VALUE, &pd->tid); if (__builtin_expect (rc == -1, 0)) { atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ /* Perhaps a thread wants to change the IDs and if waiting for this stillborn thread. */ if (__builtin_expect (atomic_exchange_acq (&pd->setxid_futex, 0) == -2, 0)) lll_futex_wake (&pd->setxid_futex, 1, LLL_PRIVATE); /* Free the resources. */ __deallocate_stack (pd); /* We have to translate error codes. */ return errno == ENOMEM ? EAGAIN : errno; } /* Now we have the possibility to set scheduling parameters etc. */ if (__builtin_expect (stopped != 0, 0)) { INTERNAL_SYSCALL_DECL (err); int res = 0; /* Set the affinity mask if necessary. */ if (attr->cpuset != NULL) { res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, attr->cpusetsize, attr->cpuset); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) { /* The operation failed. We have to kill the thread. First send it the cancellation signal. */ INTERNAL_SYSCALL_DECL (err2); err_out: (void) INTERNAL_SYSCALL (tgkill, err2, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); /* We do not free the stack here because the canceled thread itself will do this. */ return (INTERNAL_SYSCALL_ERROR_P (res, err) ? INTERNAL_SYSCALL_ERRNO (res, err) : 0); } } /* Set the scheduling parameters. */ if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) { res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, pd->schedpolicy, &pd->schedparam); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) goto err_out; } } /* We now have for sure more than one thread. The main thread might not yet have the flag set. No need to set the global variable again if this is what we use. */ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); return 0; }