1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "../../config.h"
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h>
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <signal.h>
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string.h>
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <time.h>
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef HAVE_ASM_UNISTD_H
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <asm/unistd.h> // __NR_gettid
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "../drd.h"
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_debug = 0;
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int getktid()
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __NR_gettid
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return syscall(__NR_gettid);
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return -1;
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void print_thread_id(const char* const label)
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (s_debug)
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char msg[256];
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    snprintf(msg, sizeof(msg),
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             "%spid %d / kernel thread ID %d / Valgrind thread ID %d\n",
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             label, getpid(), getktid(), DRD_GET_VALGRIND_THREADID);
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    write(STDOUT_FILENO, msg, strlen(msg));
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void SignalHandler(const int iSignal)
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print_thread_id("Signal was delivered to ");
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* thread_func(void* thread_arg)
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print_thread_id("thread: ");
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sleep(10);
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //assert(result < 0 && errno == EINTR);
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0;
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char** argv)
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_t threadid;
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  struct timespec tsDelay;
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Primitive argument parsing.
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (argc > 1)
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s_debug = 1;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print_thread_id("main: ");
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct sigaction sa;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(&sa, 0, sizeof(sa));
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sa.sa_handler = &SignalHandler;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sigemptyset(&sa.sa_mask);
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sigaction(SIGALRM, &sa, 0);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_create(&threadid, 0, thread_func, 0);
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Wait until the thread is inside clock_nanosleep().
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tsDelay.tv_sec = 0;
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tsDelay.tv_nsec = 20 * 1000 * 1000;
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  nanosleep(&tsDelay, 0);
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // And send SIGALRM to the thread.
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_kill(threadid, SIGALRM);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_join(threadid, 0);
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
86