143b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
243b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn/*--------------------------------------------------------------------*/
3278b3d6ff7b7a311ab49dff993b4aaf42b09ef13njn/*--- Semaphore stuff.                                      sema.c ---*/
443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn/*--------------------------------------------------------------------*/
543b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn/*
743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   This file is part of Valgrind, a dynamic binary instrumentation
843b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   framework.
943b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
10ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2000-2017 Julian Seward
1143b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn      jseward@acm.org
1243b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
1343b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   This program is free software; you can redistribute it and/or
1443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   modify it under the terms of the GNU General Public License as
1543b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   published by the Free Software Foundation; either version 2 of the
1643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   License, or (at your option) any later version.
1743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
1843b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   This program is distributed in the hope that it will be useful, but
1943b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   WITHOUT ANY WARRANTY; without even the implied warranty of
2043b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2143b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   General Public License for more details.
2243b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
2343b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   You should have received a copy of the GNU General Public License
2443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   along with this program; if not, write to the Free Software
2543b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   02111-1307, USA.
2743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
2843b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   The GNU General Public License is contained in the file COPYING.
2943b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn*/
3043b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
31c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_basics.h"
32f54342a26f72fce921d7487e00540562b411dea6sewardj#include "pub_core_debuglog.h"
334cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
34132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_core_libcassert.h"
35eb8896b58301a0a7a34281384d705072994369f0njn#include "pub_core_libcfile.h"
36f4c50164b9a89e3421cd6650f7187bd46b936cbdnjn#include "pub_core_libcproc.h"      // For VG_(gettid)()
37c91f58449e6fc2a4ce0851639a342c4277612fbbflorian#include "pub_core_inner.h"
38277eafff8cbea7292851b4bf4d5b6c18385578a0philippe#if defined(ENABLE_INNER_CLIENT_REQUEST)
39277eafff8cbea7292851b4bf4d5b6c18385578a0philippe#include "helgrind/helgrind.h"
40277eafff8cbea7292851b4bf4d5b6c18385578a0philippe#endif
41278b3d6ff7b7a311ab49dff993b4aaf42b09ef13njn#include "priv_sema.h"
42cbdddcfb32883a37e873907602d34bac523e3eadsewardj
43cbdddcfb32883a37e873907602d34bac523e3eadsewardj/*
44beb7ffa741dca68fd9e94622309d1f4cb232e8aanjn   Slower (than the removed futex-based sema scheme) but more portable
45beb7ffa741dca68fd9e94622309d1f4cb232e8aanjn   pipe-based token passing scheme.
46cbdddcfb32883a37e873907602d34bac523e3eadsewardj */
47cbdddcfb32883a37e873907602d34bac523e3eadsewardj
48f54342a26f72fce921d7487e00540562b411dea6sewardj/* Cycle the char passed through the pipe through 'A' .. 'Z' to make
49f54342a26f72fce921d7487e00540562b411dea6sewardj   it easier to make sense of strace/truss output - makes it possible
50f54342a26f72fce921d7487e00540562b411dea6sewardj   to see more clearly the change of ownership of the lock.  Need to
51f54342a26f72fce921d7487e00540562b411dea6sewardj   be careful to reinitialise it at fork() time. */
52cd19e99a2fc1adf5a142664d9604d18b51b646ecflorianstatic HChar sema_char = '!'; /* will cause assertion failures if used
53cd19e99a2fc1adf5a142664d9604d18b51b646ecflorian                                 before sema_init */
54f54342a26f72fce921d7487e00540562b411dea6sewardj
557eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjvoid ML_(sema_init)(vg_sema_t *sema)
56cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
57cd19e99a2fc1adf5a142664d9604d18b51b646ecflorian   HChar buf[2];
58f54342a26f72fce921d7487e00540562b411dea6sewardj   Int res, r;
59f54342a26f72fce921d7487e00540562b411dea6sewardj   r = VG_(pipe)(sema->pipe);
60f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(r == 0);
61f54342a26f72fce921d7487e00540562b411dea6sewardj
62f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(sema->pipe[0] != sema->pipe[1]);
63f54342a26f72fce921d7487e00540562b411dea6sewardj
64cbdddcfb32883a37e873907602d34bac523e3eadsewardj   sema->pipe[0] = VG_(safe_fd)(sema->pipe[0]);
65cbdddcfb32883a37e873907602d34bac523e3eadsewardj   sema->pipe[1] = VG_(safe_fd)(sema->pipe[1]);
66cbdddcfb32883a37e873907602d34bac523e3eadsewardj
67f54342a26f72fce921d7487e00540562b411dea6sewardj   if (0)
68f54342a26f72fce921d7487e00540562b411dea6sewardj      VG_(debugLog)(0,"zz","sema_init: %d %d\n", sema->pipe[0],
69f54342a26f72fce921d7487e00540562b411dea6sewardj                                                 sema->pipe[1]);
70f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(sema->pipe[0] != sema->pipe[1]);
71f54342a26f72fce921d7487e00540562b411dea6sewardj
72ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   sema->owner_lwpid = -1;
73cbdddcfb32883a37e873907602d34bac523e3eadsewardj
74cbdddcfb32883a37e873907602d34bac523e3eadsewardj   /* create initial token */
75f54342a26f72fce921d7487e00540562b411dea6sewardj   sema_char = 'A';
76f54342a26f72fce921d7487e00540562b411dea6sewardj   buf[0] = sema_char;
77f54342a26f72fce921d7487e00540562b411dea6sewardj   buf[1] = 0;
78f54342a26f72fce921d7487e00540562b411dea6sewardj   sema_char++;
79277eafff8cbea7292851b4bf4d5b6c18385578a0philippe   INNER_REQUEST(ANNOTATE_RWLOCK_CREATE(sema));
809e3a08f6dbec3b98cd2181d2835c63056ffd7495bart   INNER_REQUEST(ANNOTATE_BENIGN_RACE_SIZED(&sema->owner_lwpid,
819e3a08f6dbec3b98cd2181d2835c63056ffd7495bart                                            sizeof(sema->owner_lwpid), ""));
82f54342a26f72fce921d7487e00540562b411dea6sewardj   res = VG_(write)(sema->pipe[1], buf, 1);
8383008d6f1610fdf29639ae31381b26c876b57e9fsewardj   vg_assert(res == 1);
84cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
85cbdddcfb32883a37e873907602d34bac523e3eadsewardj
867eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjvoid ML_(sema_deinit)(vg_sema_t *sema)
87cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
88ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   vg_assert(sema->owner_lwpid != -1); /* must be initialised */
89f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(sema->pipe[0] != sema->pipe[1]);
90277eafff8cbea7292851b4bf4d5b6c18385578a0philippe   INNER_REQUEST(ANNOTATE_RWLOCK_DESTROY(sema));
91cbdddcfb32883a37e873907602d34bac523e3eadsewardj   VG_(close)(sema->pipe[0]);
92cbdddcfb32883a37e873907602d34bac523e3eadsewardj   VG_(close)(sema->pipe[1]);
93cbdddcfb32883a37e873907602d34bac523e3eadsewardj   sema->pipe[0] = sema->pipe[1] = -1;
94ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   sema->owner_lwpid = -1;
95cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
96cbdddcfb32883a37e873907602d34bac523e3eadsewardj
97cbdddcfb32883a37e873907602d34bac523e3eadsewardj/* get a token */
98f76d27a697a7b0bf3b84490baf60623fc96a23afnjnvoid ML_(sema_down)( vg_sema_t *sema, Bool as_LL )
99cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
100cd19e99a2fc1adf5a142664d9604d18b51b646ecflorian   HChar buf[2];
101cbdddcfb32883a37e873907602d34bac523e3eadsewardj   Int ret;
102cbdddcfb32883a37e873907602d34bac523e3eadsewardj   Int lwpid = VG_(gettid)();
103cbdddcfb32883a37e873907602d34bac523e3eadsewardj
104ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   vg_assert(sema->owner_lwpid != lwpid); /* can't have it already */
105f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(sema->pipe[0] != sema->pipe[1]);
106cbdddcfb32883a37e873907602d34bac523e3eadsewardj
107cbdddcfb32883a37e873907602d34bac523e3eadsewardj  again:
108f54342a26f72fce921d7487e00540562b411dea6sewardj   buf[0] = buf[1] = 0;
109f54342a26f72fce921d7487e00540562b411dea6sewardj   ret = VG_(read)(sema->pipe[0], buf, 1);
110277eafff8cbea7292851b4bf4d5b6c18385578a0philippe   INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema, /*is_w*/1));
111f54342a26f72fce921d7487e00540562b411dea6sewardj
112f54342a26f72fce921d7487e00540562b411dea6sewardj   if (ret != 1)
113f54342a26f72fce921d7487e00540562b411dea6sewardj      VG_(debugLog)(0, "scheduler",
114f54342a26f72fce921d7487e00540562b411dea6sewardj                       "VG_(sema_down): read returned %d\n", ret);
115cbdddcfb32883a37e873907602d34bac523e3eadsewardj
116cbdddcfb32883a37e873907602d34bac523e3eadsewardj   if (ret == -VKI_EINTR)
117cbdddcfb32883a37e873907602d34bac523e3eadsewardj      goto again;
118cbdddcfb32883a37e873907602d34bac523e3eadsewardj
119cbdddcfb32883a37e873907602d34bac523e3eadsewardj   vg_assert(ret == 1);		/* should get exactly 1 token */
120f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(buf[0] >= 'A' && buf[0] <= 'Z');
121f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(buf[1] == 0);
122f54342a26f72fce921d7487e00540562b411dea6sewardj
123f54342a26f72fce921d7487e00540562b411dea6sewardj   if (sema_char == 'Z') sema_char = 'A'; else sema_char++;
124cbdddcfb32883a37e873907602d34bac523e3eadsewardj
125ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   sema->owner_lwpid = lwpid;
126f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   sema->held_as_LL = as_LL;
127cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
128cbdddcfb32883a37e873907602d34bac523e3eadsewardj
129cbdddcfb32883a37e873907602d34bac523e3eadsewardj/* put token back */
130f76d27a697a7b0bf3b84490baf60623fc96a23afnjnvoid ML_(sema_up)( vg_sema_t *sema, Bool as_LL )
131cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
132cbdddcfb32883a37e873907602d34bac523e3eadsewardj   Int ret;
133cd19e99a2fc1adf5a142664d9604d18b51b646ecflorian   HChar buf[2];
134f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vg_assert(as_LL == sema->held_as_LL);
135f54342a26f72fce921d7487e00540562b411dea6sewardj   buf[0] = sema_char;
136f54342a26f72fce921d7487e00540562b411dea6sewardj   buf[1] = 0;
137ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   vg_assert(sema->owner_lwpid != -1); /* must be initialised */
138f54342a26f72fce921d7487e00540562b411dea6sewardj   vg_assert(sema->pipe[0] != sema->pipe[1]);
139ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   vg_assert(sema->owner_lwpid == VG_(gettid)()); /* must have it */
140cbdddcfb32883a37e873907602d34bac523e3eadsewardj
141ad0a3a8a33eafabba37e7f8e4dd016b06d377a5dsewardj   sema->owner_lwpid = 0;
142cbdddcfb32883a37e873907602d34bac523e3eadsewardj
143277eafff8cbea7292851b4bf4d5b6c18385578a0philippe   INNER_REQUEST(ANNOTATE_RWLOCK_RELEASED(sema, /*is_w*/1));
144f54342a26f72fce921d7487e00540562b411dea6sewardj   ret = VG_(write)(sema->pipe[1], buf, 1);
145f54342a26f72fce921d7487e00540562b411dea6sewardj
146f54342a26f72fce921d7487e00540562b411dea6sewardj   if (ret != 1)
147f54342a26f72fce921d7487e00540562b411dea6sewardj      VG_(debugLog)(0, "scheduler",
148f54342a26f72fce921d7487e00540562b411dea6sewardj                       "VG_(sema_up):write returned %d\n", ret);
149f54342a26f72fce921d7487e00540562b411dea6sewardj
150cbdddcfb32883a37e873907602d34bac523e3eadsewardj   vg_assert(ret == 1);
151cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
152cbdddcfb32883a37e873907602d34bac523e3eadsewardj
15343b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn/*--------------------------------------------------------------------*/
15443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn/*--- end                                                          ---*/
15543b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn/*--------------------------------------------------------------------*/
15643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
15743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn
158