blob: b0842f5fff8d238a56e6dd65e01de4c54e75626a [file] [log] [blame]
sewardj85642922008-01-14 11:54:56 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj4d474d02008-02-11 11:34:59 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardj85642922008-01-14 11:54:56 +00005 bart.vanassche@gmail.com
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25// Use a semaphore to implement mutual exclusion.
26
27#include <assert.h>
28#include <stdio.h> // printf()
29#include <pthread.h>
30#include <semaphore.h>
31#include <unistd.h> // usleep()
32#include "../drd_clientreq.h"
33
34
35// Local functions declarations.
36
37static void* thread_func(void*);
38
39// Local variables.
40
41// s_sem protects s_d3.
42static sem_t s_sem;
43
44static double s_d1; // accessed before thread creation and in the created
45 // thread (not a race).
46static double s_d2; // accessed in the created thread and after the join
47 // (not a race).
48static double s_d3; // accessed simultaneously from both threads (race).
49static int s_debug = 0;
50static int s_do_printf = 0;
51static int s_do_mutual_exclusion = 0;
52
53
54// Function definitions.
55
56static void set_thread_name(const char* const name)
57{
58 int res;
59 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_THREAD_NAME,
60 name, 0, 0, 0, 0);
61}
62
63int main(int argc, char** argv)
64{
65 int optchar;
66 pthread_t threadid;
67
68 set_thread_name("main");
69
70 while ((optchar = getopt(argc, argv, "dmp")) != EOF)
71 {
72 switch (optchar)
73 {
74 case 'd':
75 s_debug = 1;
76 break;
77 case 'm':
78 s_do_mutual_exclusion = 1;
79 break;
80 case 'p':
81 s_do_printf = 1;
82 break;
83 default:
84 assert(0);
85 }
86 }
87
88 sem_init(&s_sem, 0, 1);
89
90 // Switch to line-buffered mode, such that timing information can be
91 // obtained for each printf() call with strace.
92 setlinebuf(stdout);
93
94 if (s_debug)
95 {
96 printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3);
97 }
98
99 s_d1 = 1;
100 s_d3 = 3;
101
102 pthread_create(&threadid, 0, thread_func, 0);
103 // Wait until the printf() in the created thread finished.
104
105 {
106 if (s_do_mutual_exclusion) sem_wait(&s_sem);
107 s_d3++;
108 if (s_do_mutual_exclusion) sem_post(&s_sem);
109 }
110
111 // Wait until the thread finished.
112 //printf("Before call to pthread_join()\n");
113 //fflush(stdout);
114 pthread_join(threadid, 0);
115 //printf("After call to pthread_join()\n");
116 //fflush(stdout);
117 if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2);
118 if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3);
119
120 sem_destroy(&s_sem);
121
122 return 0;
123}
124
125static void* thread_func(void* thread_arg)
126{
127 set_thread_name("thread_func");
128
129 if (s_do_printf)
130 {
131 printf("s_d1 = %g (should be 1)\n", s_d1);
132 }
133 s_d2 = 2;
134 {
135 if (s_do_mutual_exclusion) sem_wait(&s_sem);
136 s_d3++;
137 if (s_do_mutual_exclusion) sem_post(&s_sem);
138 }
139 return 0;
140}