blob: 44f27f2423aadeeb33987db9a8d8be1536043489 [file] [log] [blame]
njn43b9a8a2005-05-10 04:37:01 +00001
2/*--------------------------------------------------------------------*/
njn278b3d62005-05-30 23:20:51 +00003/*--- Semaphore stuff. sema.c ---*/
njn43b9a8a2005-05-10 04:37:01 +00004/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2000-2013 Julian Seward
njn43b9a8a2005-05-10 04:37:01 +000011 jseward@acm.org
njn43b9a8a2005-05-10 04:37:01 +000012
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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardjf54342a2006-10-17 01:51:24 +000032#include "pub_core_debuglog.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
njn132bfcc2005-06-04 19:16:06 +000034#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000035#include "pub_core_libcfile.h"
njnf4c50162005-06-20 14:18:12 +000036#include "pub_core_libcproc.h" // For VG_(gettid)()
florianc91f5842013-09-15 10:42:26 +000037#include "pub_core_inner.h"
philippe277eaff2012-03-03 12:01:48 +000038#if defined(ENABLE_INNER_CLIENT_REQUEST)
39#include "helgrind/helgrind.h"
40#endif
njn278b3d62005-05-30 23:20:51 +000041#include "priv_sema.h"
sewardjcbdddcf2005-03-10 23:23:45 +000042
sewardjcbdddcf2005-03-10 23:23:45 +000043/*
njnbeb7ffa2005-05-29 16:05:37 +000044 Slower (than the removed futex-based sema scheme) but more portable
45 pipe-based token passing scheme.
sewardjcbdddcf2005-03-10 23:23:45 +000046 */
47
sewardjf54342a2006-10-17 01:51:24 +000048/* 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. */
floriancd19e992012-11-03 19:32:28 +000052static HChar sema_char = '!'; /* will cause assertion failures if used
53 before sema_init */
sewardjf54342a2006-10-17 01:51:24 +000054
sewardj7eb7c582005-06-23 01:02:53 +000055void ML_(sema_init)(vg_sema_t *sema)
sewardjcbdddcf2005-03-10 23:23:45 +000056{
floriancd19e992012-11-03 19:32:28 +000057 HChar buf[2];
sewardjf54342a2006-10-17 01:51:24 +000058 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
sewardjcbdddcf2005-03-10 23:23:45 +000064 sema->pipe[0] = VG_(safe_fd)(sema->pipe[0]);
65 sema->pipe[1] = VG_(safe_fd)(sema->pipe[1]);
66
sewardjf54342a2006-10-17 01:51:24 +000067 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
sewardjad0a3a82006-12-17 18:58:55 +000072 sema->owner_lwpid = -1;
sewardjcbdddcf2005-03-10 23:23:45 +000073
74 /* create initial token */
sewardjf54342a2006-10-17 01:51:24 +000075 sema_char = 'A';
76 buf[0] = sema_char;
77 buf[1] = 0;
78 sema_char++;
philippe277eaff2012-03-03 12:01:48 +000079 INNER_REQUEST(ANNOTATE_RWLOCK_CREATE(sema));
bart9e3a08f2012-03-08 19:02:39 +000080 INNER_REQUEST(ANNOTATE_BENIGN_RACE_SIZED(&sema->owner_lwpid,
81 sizeof(sema->owner_lwpid), ""));
sewardjf54342a2006-10-17 01:51:24 +000082 res = VG_(write)(sema->pipe[1], buf, 1);
sewardj83008d62006-01-02 16:23:29 +000083 vg_assert(res == 1);
sewardjcbdddcf2005-03-10 23:23:45 +000084}
85
sewardj7eb7c582005-06-23 01:02:53 +000086void ML_(sema_deinit)(vg_sema_t *sema)
sewardjcbdddcf2005-03-10 23:23:45 +000087{
sewardjad0a3a82006-12-17 18:58:55 +000088 vg_assert(sema->owner_lwpid != -1); /* must be initialised */
sewardjf54342a2006-10-17 01:51:24 +000089 vg_assert(sema->pipe[0] != sema->pipe[1]);
philippe277eaff2012-03-03 12:01:48 +000090 INNER_REQUEST(ANNOTATE_RWLOCK_DESTROY(sema));
sewardjcbdddcf2005-03-10 23:23:45 +000091 VG_(close)(sema->pipe[0]);
92 VG_(close)(sema->pipe[1]);
93 sema->pipe[0] = sema->pipe[1] = -1;
sewardjad0a3a82006-12-17 18:58:55 +000094 sema->owner_lwpid = -1;
sewardjcbdddcf2005-03-10 23:23:45 +000095}
96
97/* get a token */
njnf76d27a2009-05-28 01:53:07 +000098void ML_(sema_down)( vg_sema_t *sema, Bool as_LL )
sewardjcbdddcf2005-03-10 23:23:45 +000099{
floriancd19e992012-11-03 19:32:28 +0000100 HChar buf[2];
sewardjcbdddcf2005-03-10 23:23:45 +0000101 Int ret;
102 Int lwpid = VG_(gettid)();
103
sewardjad0a3a82006-12-17 18:58:55 +0000104 vg_assert(sema->owner_lwpid != lwpid); /* can't have it already */
sewardjf54342a2006-10-17 01:51:24 +0000105 vg_assert(sema->pipe[0] != sema->pipe[1]);
sewardjcbdddcf2005-03-10 23:23:45 +0000106
107 again:
sewardjf54342a2006-10-17 01:51:24 +0000108 buf[0] = buf[1] = 0;
109 ret = VG_(read)(sema->pipe[0], buf, 1);
philippe277eaff2012-03-03 12:01:48 +0000110 INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema, /*is_w*/1));
sewardjf54342a2006-10-17 01:51:24 +0000111
112 if (ret != 1)
113 VG_(debugLog)(0, "scheduler",
114 "VG_(sema_down): read returned %d\n", ret);
sewardjcbdddcf2005-03-10 23:23:45 +0000115
116 if (ret == -VKI_EINTR)
117 goto again;
118
119 vg_assert(ret == 1); /* should get exactly 1 token */
sewardjf54342a2006-10-17 01:51:24 +0000120 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++;
sewardjcbdddcf2005-03-10 23:23:45 +0000124
sewardjad0a3a82006-12-17 18:58:55 +0000125 sema->owner_lwpid = lwpid;
njnf76d27a2009-05-28 01:53:07 +0000126 sema->held_as_LL = as_LL;
sewardjcbdddcf2005-03-10 23:23:45 +0000127}
128
129/* put token back */
njnf76d27a2009-05-28 01:53:07 +0000130void ML_(sema_up)( vg_sema_t *sema, Bool as_LL )
sewardjcbdddcf2005-03-10 23:23:45 +0000131{
132 Int ret;
floriancd19e992012-11-03 19:32:28 +0000133 HChar buf[2];
njnf76d27a2009-05-28 01:53:07 +0000134 vg_assert(as_LL == sema->held_as_LL);
sewardjf54342a2006-10-17 01:51:24 +0000135 buf[0] = sema_char;
136 buf[1] = 0;
sewardjad0a3a82006-12-17 18:58:55 +0000137 vg_assert(sema->owner_lwpid != -1); /* must be initialised */
sewardjf54342a2006-10-17 01:51:24 +0000138 vg_assert(sema->pipe[0] != sema->pipe[1]);
sewardjad0a3a82006-12-17 18:58:55 +0000139 vg_assert(sema->owner_lwpid == VG_(gettid)()); /* must have it */
sewardjcbdddcf2005-03-10 23:23:45 +0000140
sewardjad0a3a82006-12-17 18:58:55 +0000141 sema->owner_lwpid = 0;
sewardjcbdddcf2005-03-10 23:23:45 +0000142
philippe277eaff2012-03-03 12:01:48 +0000143 INNER_REQUEST(ANNOTATE_RWLOCK_RELEASED(sema, /*is_w*/1));
sewardjf54342a2006-10-17 01:51:24 +0000144 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
sewardjcbdddcf2005-03-10 23:23:45 +0000150 vg_assert(ret == 1);
151}
152
njn43b9a8a2005-05-10 04:37:01 +0000153/*--------------------------------------------------------------------*/
154/*--- end ---*/
155/*--------------------------------------------------------------------*/
156
157