File: fp_race.c

package info (click to toggle)
valgrind 1%3A3.3.1-3
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 34,452 kB
  • ctags: 27,778
  • sloc: ansic: 234,398; sh: 14,186; xml: 11,662; perl: 4,410; asm: 3,135; makefile: 3,011; exp: 625; cpp: 255; haskell: 195
file content (139 lines) | stat: -rw-r--r-- 3,445 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
  This file is part of drd, a data race detector.

  Copyright (C) 2006-2007 Bart Van Assche
  bart.vanassche@gmail.com

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 2 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  02111-1307, USA.

  The GNU General Public License is contained in the file COPYING.
*/

// Test data race detection between floating point variables.

#include <assert.h>
#include <stdio.h>      // printf()
#include <pthread.h>
#include <unistd.h>    // usleep()
#include "../drd_clientreq.h"


// Local functions declarations.

static void* thread_func(void*);

// Local variables.

// s_mutex protects s_d3.
static pthread_mutex_t s_mutex;

static double s_d1; // accessed before thread creation and in the created
                    // thread (not a race).
static double s_d2; // accessed in the created thread and after the join
                    // (not a race).
static double s_d3; // accessed simultaneously from both threads (race).
static int    s_debug     = 0;
static int    s_do_printf = 0;
static int    s_use_mutex = 0;


// Function definitions.

static void set_thread_name(const char* const name)
{
  int res;
  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_THREAD_NAME,
                             name, 0, 0, 0, 0);
}

int main(int argc, char** argv)
{
  int optchar;
  pthread_t threadid;

  set_thread_name("main");

  while ((optchar = getopt(argc, argv, "dmp")) != EOF)
  {
    switch (optchar)
    {
    case 'd':
      s_debug = 1;
      break;
    case 'm':
      s_use_mutex = 1;
      break;
    case 'p':
      s_do_printf = 1;
      break;
    default:
      assert(0);
    }
  }

  pthread_mutex_init(&s_mutex, 0);

  // Switch to line-buffered mode, such that timing information can be 
  // obtained for each printf() call with strace.
  setlinebuf(stdout);

  if (s_debug)
  {
    printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3);
  }

  s_d1 = 1;
  s_d3 = 3;

  pthread_create(&threadid, 0, thread_func, 0);
  // Wait until the printf() in the created thread finished.

  {
    if (s_use_mutex) pthread_mutex_lock(&s_mutex);
    s_d3++;
    if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
  }

  // Wait until the thread finished.
  //printf("Before call to pthread_join()\n");
  //fflush(stdout);
  pthread_join(threadid, 0);
  //printf("After call to pthread_join()\n");
  //fflush(stdout);
  if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2);
  if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3);

  pthread_mutex_destroy(&s_mutex);

  return 0;
}

static void* thread_func(void* thread_arg)
{
  set_thread_name("thread_func");

  if (s_do_printf)
  {
    printf("s_d1 = %g (should be 1)\n", s_d1);
  }
  s_d2 = 2;
  {
    if (s_use_mutex) pthread_mutex_lock(&s_mutex);
    s_d3++;
    if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
  }
  return 0;
}