blob: c5771964c3dd842a22e3986dc6258d6f790dccf6 [file] [log] [blame]
sewardj85642922008-01-14 11:54:56 +00001/*
2 This file is part of drd, a data race detector.
3
4 Copyright (C) 2006-2008 Bart Van Assche
5 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
26#include "drd_error.h"
27#include "drd_semaphore.h"
28#include "drd_suppression.h"
29#include "priv_drd_clientreq.h"
30#include "pub_tool_errormgr.h" // VG_(maybe_record_error)()
31#include "pub_tool_libcassert.h" // tl_assert()
32#include "pub_tool_libcprint.h" // VG_(printf)()
33#include "pub_tool_machine.h" // VG_(get_IP)()
34#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
35
36
37// Type definitions.
38
39struct semaphore_info
40{
41 Addr semaphore; // Pointer to client semaphore.
42 SizeT size; // Size in bytes of client-side object.
43 UWord value; // Semaphore value.
44 DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
45 VectorClock vc; // Vector clock of last sem_post() call.
46};
47
48
49// Local variables.
50
51static Bool s_trace_semaphore;
52struct semaphore_info s_semaphore[256];
53
54
55// Function definitions.
56
57void semaphore_set_trace(const Bool trace_semaphore)
58{
59 s_trace_semaphore = trace_semaphore;
60}
61
62static
63void semaphore_initialize(struct semaphore_info* const p,
64 const Addr semaphore,
65 const SizeT size,
66 const UWord value)
67{
68 tl_assert(semaphore != 0);
69 tl_assert(size > 0);
70
71 p->semaphore = semaphore;
72 p->size = size;
73 p->value = value;
74 p->last_sem_post_tid = DRD_INVALID_THREADID;
75 vc_init(&p->vc, 0, 0);
76}
77
78static
79struct semaphore_info*
80semaphore_get_or_allocate(const Addr semaphore, const SizeT size)
81{
82 int i;
83
84 for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
85 {
86 if (s_semaphore[i].semaphore == semaphore)
87 {
88 tl_assert(s_semaphore[i].size == size);
89 return &s_semaphore[i];
90 }
91 }
92 for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
93 {
94 if (s_semaphore[i].semaphore == 0)
95 {
96 semaphore_initialize(&s_semaphore[i], semaphore, size, 0);
97 drd_start_suppression(semaphore, semaphore + size, "semaphore");
98 return &s_semaphore[i];
99 }
100 }
101 tl_assert(0);
102 return 0;
103}
104
105struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size,
106 const Word pshared, const UWord value)
107{
108 struct semaphore_info* p;
109
110 tl_assert(semaphore_get(semaphore) == 0);
111 p = semaphore_get_or_allocate(semaphore, size);
112 p->value = value;
113 return p;
114}
115
116void semaphore_destroy(struct semaphore_info* const p)
117{
118 drd_finish_suppression(p->semaphore, p->semaphore + p->size);
119
120 vc_cleanup(&p->vc);
121 p->semaphore = 0;
122}
123
124struct semaphore_info* semaphore_get(const Addr semaphore)
125{
126 int i;
127 for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
128 if (s_semaphore[i].semaphore == semaphore)
129 return &s_semaphore[i];
130 return 0;
131}
132
133/** Called after sem_wait() finished successfully. */
134void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
135 const SizeT size)
136{
137 struct semaphore_info* p;
138
139 p = semaphore_get_or_allocate(semaphore, size);
140 tl_assert(p->value >= 0);
141 p->value--;
142 tl_assert(p->value >= 0);
143 if (p->last_sem_post_tid != tid)
144 thread_combine_vc2(tid, &p->vc);
145 thread_new_segment(tid);
146}
147
148/** Called before sem_post(). */
149void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
150 const SizeT size)
151{
152 struct semaphore_info* p;
153
154 p = semaphore_get_or_allocate(semaphore, size);
155 p->value++;
156 if (p->value == 1)
157 {
158 p->last_sem_post_tid = tid;
159 }
160}
161
162/** Called after sem_post() finished successfully. */
163void semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
164 const SizeT size)
165{
166 struct semaphore_info* p;
167
168 p = semaphore_get_or_allocate(semaphore, size);
169 thread_new_segment(tid);
170 vc_copy(&p->vc, thread_get_vc(tid));
171}
172
173void semaphore_thread_delete(const DrdThreadId threadid)
174{ }
175
176void semaphore_stop_using_mem(const Addr a1, const Addr a2)
177{
178 unsigned i;
179 for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
180 {
181 if (a1 <= s_semaphore[i].semaphore && s_semaphore[i].semaphore < a2)
182 {
183 tl_assert(s_semaphore[i].semaphore + s_semaphore[i].size <= a2);
184 semaphore_destroy(&s_semaphore[i]);
185 }
186 }
187}