blob: 56fb65e4bf9b8d054eb6d46a735b67c98b56b8d2 [file] [log] [blame]
barte7d58722008-02-28 19:08:04 +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_clientobj.h"
27#include "drd_suppression.h"
28#include "pub_tool_basics.h"
29#include "pub_tool_libcassert.h"
30#include "pub_tool_libcbase.h"
31#include "pub_tool_libcprint.h" // VG_(message)()
32#include "pub_tool_mallocfree.h"
33#include "pub_tool_oset.h"
34
35
36// Local variables.
37
38static OSet* s_clientobj;
39
40
41// Function definitions.
42
43/** Initialize the client object set. */
44void drd_clientobj_init(void)
45{
46 tl_assert(s_clientobj == 0);
47 s_clientobj = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
48 tl_assert(s_clientobj);
49}
50
51/** Free the memory allocated for the client object set.
52 * @pre Client object set is empty.
53 */
54void drd_clientobj_cleanup(void)
55{
56 tl_assert(s_clientobj);
57 tl_assert(VG_(OSetGen_Size)(s_clientobj) == 0);
58 VG_(OSetGen_Destroy)(s_clientobj);
59 s_clientobj = 0;
60}
61
62/** Return the data associated with the client object at client address addr
63 * and that has object type t. Return 0 if there is no client object in the
64 * set with the specified start address.
65 */
66DrdClientobj* drd_clientobj_get(const Addr addr, const ObjType t)
67{
68 DrdClientobj* p;
69 p = VG_(OSetGen_Lookup)(s_clientobj, &addr);
70 if (p && p->any.type == t)
71 return p;
72 return 0;
73}
74
75/** Return true if and only if the address range of any client object overlaps
76 * with the specified address range.
77 */
78Bool drd_clientobj_present(const Addr a1, const Addr a2)
79{
80 DrdClientobj *p;
81
82 tl_assert(a1 < a2);
83 VG_(OSetGen_ResetIter)(s_clientobj);
84 for ( ; (p = VG_(OSetGen_Next)(s_clientobj)) != 0; )
85 {
86 if ((a1 <= p->any.a1 && p->any.a1 < a2)
87 || (a1 < p->any.a2 && p->any.a2 <= a2))
88 {
89 return True;
90 }
91 }
92 return False;
93}
94
95/** Add state information for the client object at client address addr and
96 * of type t. Suppress data race reports on the address range [addr,addr+size[.
97 * @pre No other client object is present in the address range [addr,addr+size[.
98 */
99DrdClientobj*
100drd_clientobj_add(const Addr a1, const Addr a2, const ObjType t)
101{
102 DrdClientobj* p;
103
104 tl_assert(a1 < a2 && a1 + 4096 > a2);
105 tl_assert(! drd_clientobj_present(a1, a2));
106 tl_assert(VG_(OSetGen_Lookup)(s_clientobj, &a1) == 0);
bartbcbd7482008-02-29 19:19:39 +0000107
barte7d58722008-02-28 19:08:04 +0000108 p = VG_(OSetGen_AllocNode)(s_clientobj, sizeof(*p));
109 VG_(memset)(p, 0, sizeof(*p));
110 p->any.a1 = a1;
111 p->any.a2 = a2;
112 p->any.type = t;
113 VG_(OSetGen_Insert)(s_clientobj, p);
114 tl_assert(VG_(OSetGen_Lookup)(s_clientobj, &a1) == p);
115 drd_start_suppression(p->any.a1, p->any.a2, "client object");
116 return p;
117}
118
bart28230a32008-02-29 17:27:03 +0000119Bool drd_clientobj_remove(const Addr addr, const ObjType t)
barte7d58722008-02-28 19:08:04 +0000120{
121 DrdClientobj* p;
122
bart28230a32008-02-29 17:27:03 +0000123 p = VG_(OSetGen_Lookup)(s_clientobj, &addr);
124 tl_assert(p->any.type == t);
barte7d58722008-02-28 19:08:04 +0000125 p = VG_(OSetGen_Remove)(s_clientobj, &addr);
126 if (p)
127 {
barte7d58722008-02-28 19:08:04 +0000128 tl_assert(VG_(OSetGen_Lookup)(s_clientobj, &addr) == 0);
129 drd_finish_suppression(p->any.a1, p->any.a2);
130 tl_assert(p->any.cleanup);
131 (*p->any.cleanup)(p);
132 VG_(OSetGen_FreeNode)(s_clientobj, p);
133 return True;
134 }
135 return False;
136}
137
138void drd_clientobj_stop_using_mem(const Addr a1, const Addr a2)
139{
bartb78312c2008-02-29 11:00:17 +0000140 Addr removed_at;
barte7d58722008-02-28 19:08:04 +0000141 DrdClientobj* p;
bartb78312c2008-02-29 11:00:17 +0000142
barte7d58722008-02-28 19:08:04 +0000143 tl_assert(s_clientobj);
144 VG_(OSetGen_ResetIter)(s_clientobj);
bartb78312c2008-02-29 11:00:17 +0000145 p = VG_(OSetGen_Next)(s_clientobj);
146 for ( ; p != 0; )
barte7d58722008-02-28 19:08:04 +0000147 {
148 if ((a1 <= p->any.a1 && p->any.a1 < a2)
149 || (a1 < p->any.a2 && p->any.a2 <= a2))
150 {
bartb78312c2008-02-29 11:00:17 +0000151 removed_at = p->any.a1;
bart28230a32008-02-29 17:27:03 +0000152 drd_clientobj_remove(p->any.a1, p->any.type);
bartbcbd7482008-02-29 19:19:39 +0000153 /* The above call removes an element from the oset and hence */
154 /* invalidates the iterator. Set the iterator back. */
bartb78312c2008-02-29 11:00:17 +0000155 VG_(OSetGen_ResetIter)(s_clientobj);
156 while ((p = VG_(OSetGen_Next)(s_clientobj)) != 0
157 && p->any.a1 <= removed_at)
158 { }
159 }
160 else
161 {
162 p = VG_(OSetGen_Next)(s_clientobj);
barte7d58722008-02-28 19:08:04 +0000163 }
164 }
165}
166
167void drd_clientobj_resetiter(void)
168{
169 VG_(OSetGen_ResetIter)(s_clientobj);
170}
171
172DrdClientobj* drd_clientobj_next(const ObjType t)
173{
174 DrdClientobj* p;
175 while ((p = VG_(OSetGen_Next)(s_clientobj)) != 0 && p->any.type != t)
176 ;
177 return p;
178}
179