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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_debuglog.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_libcassert.h"
35 #include "pub_core_libcfile.h"
36 #include "pub_core_libcproc.h" // For VG_(gettid)()
37 #include "pub_core_inner.h"
38 #if defined(ENABLE_INNER_CLIENT_REQUEST)
39 #include "helgrind/helgrind.h"
41 #include "priv_sema.h"
44 Slower (than the removed futex-based sema scheme) but more portable
45 pipe-based token passing scheme.
48 /* Cycle the char passed through the pipe through 'A' .. 'Z' to make
49 it easier to make sense of strace/truss output - makes it possible
50 to see more clearly the change of ownership of the lock. Need to
51 be careful to reinitialise it at fork() time. */
52 static HChar sema_char
= '!'; /* will cause assertion failures if used
55 void ML_(sema_init
)(vg_sema_t
*sema
)
59 r
= VG_(pipe
)(sema
->pipe
);
62 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
64 sema
->pipe
[0] = VG_(safe_fd
)(sema
->pipe
[0]);
65 sema
->pipe
[1] = VG_(safe_fd
)(sema
->pipe
[1]);
68 VG_(debugLog
)(0,"zz","sema_init: %d %d\n", sema
->pipe
[0],
70 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
72 sema
->owner_lwpid
= -1;
74 /* create initial token */
79 INNER_REQUEST(ANNOTATE_RWLOCK_CREATE(sema
));
80 INNER_REQUEST(ANNOTATE_BENIGN_RACE_SIZED(&sema
->owner_lwpid
,
81 sizeof(sema
->owner_lwpid
), ""));
82 res
= VG_(write
)(sema
->pipe
[1], buf
, 1);
86 void ML_(sema_deinit
)(vg_sema_t
*sema
)
88 vg_assert(sema
->owner_lwpid
!= -1); /* must be initialised */
89 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
90 INNER_REQUEST(ANNOTATE_RWLOCK_DESTROY(sema
));
91 VG_(close
)(sema
->pipe
[0]);
92 VG_(close
)(sema
->pipe
[1]);
93 sema
->pipe
[0] = sema
->pipe
[1] = -1;
94 sema
->owner_lwpid
= -1;
98 void ML_(sema_down
)( vg_sema_t
*sema
, Bool as_LL
)
102 Int lwpid
= VG_(gettid
)();
104 vg_assert(sema
->owner_lwpid
!= lwpid
); /* can't have it already */
105 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
109 ret
= VG_(read
)(sema
->pipe
[0], buf
, 1);
110 INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema
, /*is_w*/1));
113 VG_(debugLog
)(0, "scheduler",
114 "VG_(sema_down): read returned %d\n", ret
);
116 if (ret
== -VKI_EINTR
)
119 vg_assert(ret
== 1); /* should get exactly 1 token */
120 vg_assert(buf
[0] >= 'A' && buf
[0] <= 'Z');
121 vg_assert(buf
[1] == 0);
123 if (sema_char
== 'Z') sema_char
= 'A'; else sema_char
++;
125 sema
->owner_lwpid
= lwpid
;
126 sema
->held_as_LL
= as_LL
;
130 void ML_(sema_up
)( vg_sema_t
*sema
, Bool as_LL
)
134 vg_assert(as_LL
== sema
->held_as_LL
);
137 vg_assert(sema
->owner_lwpid
!= -1); /* must be initialised */
138 vg_assert(sema
->pipe
[0] != sema
->pipe
[1]);
139 vg_assert(sema
->owner_lwpid
== VG_(gettid
)()); /* must have it */
141 sema
->owner_lwpid
= 0;
143 INNER_REQUEST(ANNOTATE_RWLOCK_RELEASED(sema
, /*is_w*/1));
144 ret
= VG_(write
)(sema
->pipe
[1], buf
, 1);
147 VG_(debugLog
)(0, "scheduler",
148 "VG_(sema_up):write returned %d\n", ret
);
153 /*--------------------------------------------------------------------*/
155 /*--------------------------------------------------------------------*/