2 /*--------------------------------------------------------------------*/
3 /*--- Semaphore stuff. sema.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2017 Julian Seward
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #include "pub_core_basics.h"
30 #include "pub_core_debuglog.h"
31 #include "pub_core_vki.h"
32 #include "pub_core_libcassert.h"
33 #include "pub_core_libcfile.h"
34 #include "pub_core_libcproc.h" // For VG_(gettid)()
35 #include "pub_core_inner.h"
36 #if defined(ENABLE_INNER_CLIENT_REQUEST)
37 #include "helgrind/helgrind.h"
39 #include "priv_sema.h"
42 Slower (than the removed futex-based sema scheme) but more portable
43 pipe-based token passing scheme.
46 /* Cycle the char passed through the pipe through 'A' .. 'Z' to make
47 it easier to make sense of strace/truss output - makes it possible
48 to see more clearly the change of ownership of the lock. Need to
49 be careful to reinitialise it at fork() time. */
50 static HChar sema_char
= '!'; /* will cause assertion failures if used
53 void ML_(sema_init
)(vg_sema_t
*sema
)
57 r
= VG_(pipe
)(sema
->pipe
);
60 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
62 sema
->pipe
[0] = VG_(safe_fd
)(sema
->pipe
[0]);
63 sema
->pipe
[1] = VG_(safe_fd
)(sema
->pipe
[1]);
66 VG_(debugLog
)(0,"zz","sema_init: %d %d\n", sema
->pipe
[0],
68 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
70 sema
->owner_lwpid
= -1;
72 /* create initial token */
77 INNER_REQUEST(ANNOTATE_RWLOCK_CREATE(sema
));
78 INNER_REQUEST(ANNOTATE_BENIGN_RACE_SIZED(&sema
->owner_lwpid
,
79 sizeof(sema
->owner_lwpid
), ""));
80 res
= VG_(write
)(sema
->pipe
[1], buf
, 1);
84 void ML_(sema_deinit
)(vg_sema_t
*sema
)
86 vg_assert(sema
->owner_lwpid
!= -1); /* must be initialised */
87 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
88 INNER_REQUEST(ANNOTATE_RWLOCK_DESTROY(sema
));
89 VG_(close
)(sema
->pipe
[0]);
90 VG_(close
)(sema
->pipe
[1]);
91 sema
->pipe
[0] = sema
->pipe
[1] = -1;
92 sema
->owner_lwpid
= -1;
96 void ML_(sema_down
)( vg_sema_t
*sema
, Bool as_LL
)
100 Int lwpid
= VG_(gettid
)();
102 vg_assert(sema
->owner_lwpid
!= lwpid
); /* can't have it already */
103 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
107 ret
= VG_(read
)(sema
->pipe
[0], buf
, 1);
108 INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema
, /*is_w*/1));
111 VG_(debugLog
)(0, "scheduler",
112 "VG_(sema_down): read returned %d\n", ret
);
114 if (ret
== -VKI_EINTR
)
117 vg_assert(ret
== 1); /* should get exactly 1 token */
118 vg_assert(buf
[0] >= 'A' && buf
[0] <= 'Z');
119 vg_assert(buf
[1] == 0);
121 if (sema_char
== 'Z') sema_char
= 'A'; else sema_char
++;
123 sema
->owner_lwpid
= lwpid
;
124 sema
->held_as_LL
= as_LL
;
128 void ML_(sema_up
)( vg_sema_t
*sema
, Bool as_LL
)
132 vg_assert(as_LL
== sema
->held_as_LL
);
135 vg_assert(sema
->owner_lwpid
!= -1); /* must be initialised */
136 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
137 vg_assert(sema
->owner_lwpid
== VG_(gettid
)()); /* must have it */
139 sema
->owner_lwpid
= 0;
141 INNER_REQUEST(ANNOTATE_RWLOCK_RELEASED(sema
, /*is_w*/1));
142 ret
= VG_(write
)(sema
->pipe
[1], buf
, 1);
145 VG_(debugLog
)(0, "scheduler",
146 "VG_(sema_up):write returned %d\n", ret
);
151 /*--------------------------------------------------------------------*/
153 /*--------------------------------------------------------------------*/