mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-04 02:18:37 +00:00
Authors of this port:
Petr Pavlu setup@dagobah.cz
Ivo Raisr ivosh@ivosh.net
Theo Schlossnagle theo@omniti.com
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15426
143 lines
3.9 KiB
C
143 lines
3.9 KiB
C
/** Trigger two kinds of errors: once that condition variable s_cond is
|
|
* associated with two different mutexes (s_mutex1 and s_mutex2), and two
|
|
* times that pthread_cond_signal() is called without that the mutex
|
|
* associated with the condition variable is locked.
|
|
*/
|
|
|
|
|
|
#include <errno.h> // ETIMEDOUT
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h> // malloc()
|
|
#include <string.h> // memset()
|
|
#include <sys/time.h> // gettimeofday()
|
|
#include <time.h> // struct timespec
|
|
#include <fcntl.h> // O_CREAT
|
|
#include <unistd.h>
|
|
#include "../../config.h"
|
|
|
|
|
|
#define PTH_CALL(expr) \
|
|
do \
|
|
{ \
|
|
int err = (expr); \
|
|
if (! s_quiet && err) \
|
|
{ \
|
|
fprintf(stderr, \
|
|
"%s:%d %s returned error code %d (%s)\n", \
|
|
__FILE__, \
|
|
__LINE__, \
|
|
#expr, \
|
|
err, \
|
|
strerror(err)); \
|
|
} \
|
|
} while (0)
|
|
|
|
|
|
static pthread_cond_t s_cond;
|
|
static pthread_mutex_t s_mutex1;
|
|
static pthread_mutex_t s_mutex2;
|
|
static sem_t* s_sem;
|
|
static int s_quiet;
|
|
|
|
|
|
static sem_t* create_semaphore(const char* const name)
|
|
{
|
|
#ifdef VGO_darwin
|
|
char name_and_pid[32];
|
|
snprintf(name_and_pid, sizeof(name_and_pid), "%s-%d", name, getpid());
|
|
sem_t* p = sem_open(name_and_pid, O_CREAT | O_EXCL, 0600, 0);
|
|
if (p == SEM_FAILED) {
|
|
perror("sem_open");
|
|
return NULL;
|
|
}
|
|
return p;
|
|
#else
|
|
sem_t* p = malloc(sizeof(*p));
|
|
if (p)
|
|
sem_init(p, 0, 0);
|
|
return p;
|
|
#endif
|
|
}
|
|
|
|
static void destroy_semaphore(const char* const name, sem_t* p)
|
|
{
|
|
#ifdef VGO_darwin
|
|
sem_close(p);
|
|
sem_unlink(name);
|
|
#else
|
|
sem_destroy(p);
|
|
free(p);
|
|
#endif
|
|
}
|
|
|
|
static void* thread_func(void* mutex)
|
|
{
|
|
struct timeval now;
|
|
struct timespec deadline;
|
|
|
|
PTH_CALL(pthread_mutex_lock(mutex));
|
|
sem_post(s_sem);
|
|
gettimeofday(&now, 0);
|
|
memset(&deadline, 0, sizeof(deadline));
|
|
deadline.tv_sec = now.tv_sec + 2;
|
|
deadline.tv_nsec = now.tv_usec * 1000;
|
|
PTH_CALL(pthread_cond_timedwait(&s_cond, mutex, &deadline));
|
|
PTH_CALL(pthread_mutex_unlock(mutex));
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
char semaphore_name[32];
|
|
int optchar;
|
|
pthread_t tid1;
|
|
pthread_t tid2;
|
|
|
|
while ((optchar = getopt(argc, argv, "q")) != EOF)
|
|
{
|
|
switch (optchar)
|
|
{
|
|
case 'q': s_quiet = 1; break;
|
|
default:
|
|
fprintf(stderr, "Error: unknown option '%c'.\n", optchar);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* Initialize synchronization objects. */
|
|
snprintf(semaphore_name, sizeof(semaphore_name), "semaphore-%ld",
|
|
(long) getpid());
|
|
s_sem = create_semaphore(semaphore_name);
|
|
PTH_CALL(pthread_cond_init(&s_cond, 0));
|
|
PTH_CALL(pthread_mutex_init(&s_mutex1, 0));
|
|
PTH_CALL(pthread_mutex_init(&s_mutex2, 0));
|
|
|
|
/* Create two threads. */
|
|
PTH_CALL(pthread_create(&tid1, 0, &thread_func, &s_mutex1));
|
|
PTH_CALL(pthread_create(&tid2, 0, &thread_func, &s_mutex2));
|
|
|
|
/* Wait until both threads have called sem_post(). */
|
|
sem_wait(s_sem);
|
|
sem_wait(s_sem);
|
|
destroy_semaphore(semaphore_name, s_sem);
|
|
s_sem = 0;
|
|
|
|
/* Wait until both threads are waiting inside pthread_cond_wait(). */
|
|
PTH_CALL(pthread_mutex_lock(&s_mutex1));
|
|
PTH_CALL(pthread_mutex_lock(&s_mutex2));
|
|
PTH_CALL(pthread_mutex_unlock(&s_mutex2));
|
|
PTH_CALL(pthread_mutex_unlock(&s_mutex1));
|
|
|
|
/* Signal s_cond twice. */
|
|
PTH_CALL(pthread_cond_signal(&s_cond));
|
|
PTH_CALL(pthread_cond_signal(&s_cond));
|
|
|
|
/* Join both threads. */
|
|
PTH_CALL(pthread_join(tid1, 0));
|
|
PTH_CALL(pthread_join(tid2, 0));
|
|
|
|
return 0;
|
|
}
|