njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
njn | 278b3d6 | 2005-05-30 23:20:51 +0000 | [diff] [blame] | 3 | /*--- Semaphore stuff. sema.c ---*/ |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 4 | /*--------------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
| 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
| 9 | |
sewardj | 0f157dd | 2013-10-18 14:27:36 +0000 | [diff] [blame] | 10 | Copyright (C) 2000-2013 Julian Seward |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 11 | jseward@acm.org |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 12 | |
| 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. |
| 17 | |
| 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. |
| 22 | |
| 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 |
| 26 | 02111-1307, USA. |
| 27 | |
| 28 | The GNU General Public License is contained in the file COPYING. |
| 29 | */ |
| 30 | |
njn | c7561b9 | 2005-06-19 01:24:32 +0000 | [diff] [blame] | 31 | #include "pub_core_basics.h" |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 32 | #include "pub_core_debuglog.h" |
sewardj | 4cfea4f | 2006-10-14 19:26:10 +0000 | [diff] [blame] | 33 | #include "pub_core_vki.h" |
njn | 132bfcc | 2005-06-04 19:16:06 +0000 | [diff] [blame] | 34 | #include "pub_core_libcassert.h" |
njn | eb8896b | 2005-06-04 20:03:55 +0000 | [diff] [blame] | 35 | #include "pub_core_libcfile.h" |
njn | f4c5016 | 2005-06-20 14:18:12 +0000 | [diff] [blame] | 36 | #include "pub_core_libcproc.h" // For VG_(gettid)() |
florian | c91f584 | 2013-09-15 10:42:26 +0000 | [diff] [blame] | 37 | #include "pub_core_inner.h" |
philippe | 277eaff | 2012-03-03 12:01:48 +0000 | [diff] [blame] | 38 | #if defined(ENABLE_INNER_CLIENT_REQUEST) |
| 39 | #include "helgrind/helgrind.h" |
| 40 | #endif |
njn | 278b3d6 | 2005-05-30 23:20:51 +0000 | [diff] [blame] | 41 | #include "priv_sema.h" |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 42 | |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 43 | /* |
njn | beb7ffa | 2005-05-29 16:05:37 +0000 | [diff] [blame] | 44 | Slower (than the removed futex-based sema scheme) but more portable |
| 45 | pipe-based token passing scheme. |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 46 | */ |
| 47 | |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 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. */ |
florian | cd19e99 | 2012-11-03 19:32:28 +0000 | [diff] [blame] | 52 | static HChar sema_char = '!'; /* will cause assertion failures if used |
| 53 | before sema_init */ |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 54 | |
sewardj | 7eb7c58 | 2005-06-23 01:02:53 +0000 | [diff] [blame] | 55 | void ML_(sema_init)(vg_sema_t *sema) |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 56 | { |
florian | cd19e99 | 2012-11-03 19:32:28 +0000 | [diff] [blame] | 57 | HChar buf[2]; |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 58 | Int res, r; |
| 59 | r = VG_(pipe)(sema->pipe); |
| 60 | vg_assert(r == 0); |
| 61 | |
| 62 | vg_assert(sema->pipe[0] != sema->pipe[1]); |
| 63 | |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 64 | sema->pipe[0] = VG_(safe_fd)(sema->pipe[0]); |
| 65 | sema->pipe[1] = VG_(safe_fd)(sema->pipe[1]); |
| 66 | |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 67 | if (0) |
| 68 | VG_(debugLog)(0,"zz","sema_init: %d %d\n", sema->pipe[0], |
| 69 | sema->pipe[1]); |
| 70 | vg_assert(sema->pipe[0] != sema->pipe[1]); |
| 71 | |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 72 | sema->owner_lwpid = -1; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 73 | |
| 74 | /* create initial token */ |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 75 | sema_char = 'A'; |
| 76 | buf[0] = sema_char; |
| 77 | buf[1] = 0; |
| 78 | sema_char++; |
philippe | 277eaff | 2012-03-03 12:01:48 +0000 | [diff] [blame] | 79 | INNER_REQUEST(ANNOTATE_RWLOCK_CREATE(sema)); |
bart | 9e3a08f | 2012-03-08 19:02:39 +0000 | [diff] [blame] | 80 | INNER_REQUEST(ANNOTATE_BENIGN_RACE_SIZED(&sema->owner_lwpid, |
| 81 | sizeof(sema->owner_lwpid), "")); |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 82 | res = VG_(write)(sema->pipe[1], buf, 1); |
sewardj | 83008d6 | 2006-01-02 16:23:29 +0000 | [diff] [blame] | 83 | vg_assert(res == 1); |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 84 | } |
| 85 | |
sewardj | 7eb7c58 | 2005-06-23 01:02:53 +0000 | [diff] [blame] | 86 | void ML_(sema_deinit)(vg_sema_t *sema) |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 87 | { |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 88 | vg_assert(sema->owner_lwpid != -1); /* must be initialised */ |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 89 | vg_assert(sema->pipe[0] != sema->pipe[1]); |
philippe | 277eaff | 2012-03-03 12:01:48 +0000 | [diff] [blame] | 90 | INNER_REQUEST(ANNOTATE_RWLOCK_DESTROY(sema)); |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 91 | VG_(close)(sema->pipe[0]); |
| 92 | VG_(close)(sema->pipe[1]); |
| 93 | sema->pipe[0] = sema->pipe[1] = -1; |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 94 | sema->owner_lwpid = -1; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | /* get a token */ |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 98 | void ML_(sema_down)( vg_sema_t *sema, Bool as_LL ) |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 99 | { |
florian | cd19e99 | 2012-11-03 19:32:28 +0000 | [diff] [blame] | 100 | HChar buf[2]; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 101 | Int ret; |
| 102 | Int lwpid = VG_(gettid)(); |
| 103 | |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 104 | vg_assert(sema->owner_lwpid != lwpid); /* can't have it already */ |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 105 | vg_assert(sema->pipe[0] != sema->pipe[1]); |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 106 | |
| 107 | again: |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 108 | buf[0] = buf[1] = 0; |
| 109 | ret = VG_(read)(sema->pipe[0], buf, 1); |
philippe | 277eaff | 2012-03-03 12:01:48 +0000 | [diff] [blame] | 110 | INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema, /*is_w*/1)); |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 111 | |
| 112 | if (ret != 1) |
| 113 | VG_(debugLog)(0, "scheduler", |
| 114 | "VG_(sema_down): read returned %d\n", ret); |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 115 | |
| 116 | if (ret == -VKI_EINTR) |
| 117 | goto again; |
| 118 | |
| 119 | vg_assert(ret == 1); /* should get exactly 1 token */ |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 120 | vg_assert(buf[0] >= 'A' && buf[0] <= 'Z'); |
| 121 | vg_assert(buf[1] == 0); |
| 122 | |
| 123 | if (sema_char == 'Z') sema_char = 'A'; else sema_char++; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 124 | |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 125 | sema->owner_lwpid = lwpid; |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 126 | sema->held_as_LL = as_LL; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | /* put token back */ |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 130 | void ML_(sema_up)( vg_sema_t *sema, Bool as_LL ) |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 131 | { |
| 132 | Int ret; |
florian | cd19e99 | 2012-11-03 19:32:28 +0000 | [diff] [blame] | 133 | HChar buf[2]; |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 134 | vg_assert(as_LL == sema->held_as_LL); |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 135 | buf[0] = sema_char; |
| 136 | buf[1] = 0; |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 137 | vg_assert(sema->owner_lwpid != -1); /* must be initialised */ |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 138 | vg_assert(sema->pipe[0] != sema->pipe[1]); |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 139 | vg_assert(sema->owner_lwpid == VG_(gettid)()); /* must have it */ |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 140 | |
sewardj | ad0a3a8 | 2006-12-17 18:58:55 +0000 | [diff] [blame] | 141 | sema->owner_lwpid = 0; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 142 | |
philippe | 277eaff | 2012-03-03 12:01:48 +0000 | [diff] [blame] | 143 | INNER_REQUEST(ANNOTATE_RWLOCK_RELEASED(sema, /*is_w*/1)); |
sewardj | f54342a | 2006-10-17 01:51:24 +0000 | [diff] [blame] | 144 | ret = VG_(write)(sema->pipe[1], buf, 1); |
| 145 | |
| 146 | if (ret != 1) |
| 147 | VG_(debugLog)(0, "scheduler", |
| 148 | "VG_(sema_up):write returned %d\n", ret); |
| 149 | |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 150 | vg_assert(ret == 1); |
| 151 | } |
| 152 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 153 | /*--------------------------------------------------------------------*/ |
| 154 | /*--- end ---*/ |
| 155 | /*--------------------------------------------------------------------*/ |
| 156 | |
| 157 | |