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