| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| #define USE_VOLATILE 0 |
|
|
| #if USE_POSIX_THREADS && HAVE_SEMAPHORE_H |
| |
| |
| |
| # define USE_SEMAPHORE 1 |
| |
| |
| # if defined __APPLE__ && defined __MACH__ |
| # define USE_NAMED_SEMAPHORE 1 |
| # else |
| # define USE_UNNAMED_SEMAPHORE 1 |
| # endif |
| #endif |
|
|
|
|
| #if USE_SEMAPHORE |
| # include <errno.h> |
| # include <fcntl.h> |
| # include <semaphore.h> |
| # include <unistd.h> |
| #endif |
|
|
|
|
| #if USE_VOLATILE |
| struct atomic_int { |
| volatile int value; |
| }; |
| static void |
| init_atomic_int (struct atomic_int *ai) |
| { |
| } |
| static int |
| get_atomic_int_value (struct atomic_int *ai) |
| { |
| return ai->value; |
| } |
| static void |
| set_atomic_int_value (struct atomic_int *ai, int new_value) |
| { |
| ai->value = new_value; |
| } |
| #elif USE_SEMAPHORE |
| |
| |
| # if USE_UNNAMED_SEMAPHORE |
| struct atomic_int { |
| sem_t semaphore; |
| }; |
| #define atomic_int_semaphore(ai) (&(ai)->semaphore) |
| static void |
| init_atomic_int (struct atomic_int *ai) |
| { |
| sem_init (&ai->semaphore, 0, 0); |
| } |
| # endif |
| # if USE_NAMED_SEMAPHORE |
| struct atomic_int { |
| sem_t *semaphore; |
| }; |
| #define atomic_int_semaphore(ai) ((ai)->semaphore) |
| static void |
| init_atomic_int (struct atomic_int *ai) |
| { |
| sem_t *s; |
| unsigned int count; |
| for (count = 0; ; count++) |
| { |
| char name[80]; |
| |
| |
| |
| |
| |
| sprintf (name, "test-lock-%lu-%p-%u", |
| (unsigned long) getpid (), ai, count); |
| s = sem_open (name, O_CREAT | O_EXCL, 0600, 0); |
| if (s == SEM_FAILED) |
| { |
| if (errno == EEXIST) |
| |
| continue; |
| else |
| { |
| perror ("sem_open failed"); |
| fflush (stderr); |
| abort (); |
| } |
| } |
| else |
| { |
| |
| |
| sem_unlink (name); |
| break; |
| } |
| } |
| ai->semaphore = s; |
| } |
| # endif |
| static int |
| get_atomic_int_value (struct atomic_int *ai) |
| { |
| if (sem_trywait (atomic_int_semaphore (ai)) == 0) |
| { |
| if (sem_post (atomic_int_semaphore (ai))) |
| abort (); |
| return 1; |
| } |
| else if (errno == EAGAIN) |
| return 0; |
| else |
| abort (); |
| } |
| static void |
| set_atomic_int_value (struct atomic_int *ai, int new_value) |
| { |
| if (new_value == 0) |
| |
| return; |
| |
| if (sem_post (atomic_int_semaphore (ai))) |
| abort (); |
| } |
| #else |
| struct atomic_int { |
| mtx_t lock; |
| int value; |
| }; |
| static void |
| init_atomic_int (struct atomic_int *ai) |
| { |
| ASSERT (mtx_init (&ai->lock, mtx_plain) == thrd_success); |
| } |
| static int |
| get_atomic_int_value (struct atomic_int *ai) |
| { |
| ASSERT (mtx_lock (&ai->lock) == thrd_success); |
| int ret = ai->value; |
| ASSERT (mtx_unlock (&ai->lock) == thrd_success); |
| return ret; |
| } |
| static void |
| set_atomic_int_value (struct atomic_int *ai, int new_value) |
| { |
| ASSERT (mtx_lock (&ai->lock) == thrd_success); |
| ai->value = new_value; |
| ASSERT (mtx_unlock (&ai->lock) == thrd_success); |
| } |
| #endif |
|
|