18564292ac4b9adf51c45517cca2878732feb5bb4sewardj/* 286562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 38564292ac4b9adf51c45517cca2878732feb5bb4sewardj 4d4bab99f83dbc53665c5769c3f6b50ffcd2a9a7dbart Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>. 58564292ac4b9adf51c45517cca2878732feb5bb4sewardj 68564292ac4b9adf51c45517cca2878732feb5bb4sewardj This program is free software; you can redistribute it and/or 78564292ac4b9adf51c45517cca2878732feb5bb4sewardj modify it under the terms of the GNU General Public License as 88564292ac4b9adf51c45517cca2878732feb5bb4sewardj published by the Free Software Foundation; either version 2 of the 98564292ac4b9adf51c45517cca2878732feb5bb4sewardj License, or (at your option) any later version. 108564292ac4b9adf51c45517cca2878732feb5bb4sewardj 118564292ac4b9adf51c45517cca2878732feb5bb4sewardj This program is distributed in the hope that it will be useful, but 128564292ac4b9adf51c45517cca2878732feb5bb4sewardj WITHOUT ANY WARRANTY; without even the implied warranty of 138564292ac4b9adf51c45517cca2878732feb5bb4sewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 148564292ac4b9adf51c45517cca2878732feb5bb4sewardj General Public License for more details. 158564292ac4b9adf51c45517cca2878732feb5bb4sewardj 168564292ac4b9adf51c45517cca2878732feb5bb4sewardj You should have received a copy of the GNU General Public License 178564292ac4b9adf51c45517cca2878732feb5bb4sewardj along with this program; if not, write to the Free Software 188564292ac4b9adf51c45517cca2878732feb5bb4sewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 198564292ac4b9adf51c45517cca2878732feb5bb4sewardj 02111-1307, USA. 208564292ac4b9adf51c45517cca2878732feb5bb4sewardj 218564292ac4b9adf51c45517cca2878732feb5bb4sewardj The GNU General Public License is contained in the file COPYING. 228564292ac4b9adf51c45517cca2878732feb5bb4sewardj*/ 238564292ac4b9adf51c45517cca2878732feb5bb4sewardj 248564292ac4b9adf51c45517cca2878732feb5bb4sewardj 2528230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h" 268564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_error.h" 278564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_semaphore.h" 288564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "drd_suppression.h" 298564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_errormgr.h" // VG_(maybe_record_error)() 308564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcassert.h" // tl_assert() 318564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_libcprint.h" // VG_(printf)() 328564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_machine.h" // VG_(get_IP)() 333e017fa58a7c090cee54809baa4f5be78cb4eef9bart#include "pub_tool_mallocfree.h" // VG_(malloc), VG_(free) 348564292ac4b9adf51c45517cca2878732feb5bb4sewardj#include "pub_tool_threadstate.h" // VG_(get_running_tid)() 358564292ac4b9adf51c45517cca2878732feb5bb4sewardj 368564292ac4b9adf51c45517cca2878732feb5bb4sewardj 37dc1ef03a8d13efe24661a89091e66169bf3f1091bart/* Local functions. */ 388564292ac4b9adf51c45517cca2878732feb5bb4sewardj 39d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void semaphore_cleanup(struct semaphore_info* p); 408564292ac4b9adf51c45517cca2878732feb5bb4sewardj 418564292ac4b9adf51c45517cca2878732feb5bb4sewardj 42dc1ef03a8d13efe24661a89091e66169bf3f1091bart/* Local variables. */ 438564292ac4b9adf51c45517cca2878732feb5bb4sewardj 44d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic Bool s_trace_semaphore; 45d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic ULong s_semaphore_segment_creation_count; 468564292ac4b9adf51c45517cca2878732feb5bb4sewardj 478564292ac4b9adf51c45517cca2878732feb5bb4sewardj 48dc1ef03a8d13efe24661a89091e66169bf3f1091bart/* Function definitions. */ 498564292ac4b9adf51c45517cca2878732feb5bb4sewardj 50dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** Push a segment at the end of the queue 'p->last_sem_post_seg'. */ 5125f9f5411f64046c2ffc0822f727aedc21f07720bartstatic void drd_segment_push(struct semaphore_info* p, Segment* sg) 523e017fa58a7c090cee54809baa4f5be78cb4eef9bart{ 53bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Word n; 543e017fa58a7c090cee54809baa4f5be78cb4eef9bart 55bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sg); 56bedfd237fbdc80d0c917cfcb85a94b5561c92633bart n = VG_(addToXA)(p->last_sem_post_seg, &sg); 573e017fa58a7c090cee54809baa4f5be78cb4eef9bart#if 0 589af04c49df08365aa568b3a27ffa5b2a1274a987florian VG_(message)(Vg_DebugMsg, "0x%lx push: added at position %ld/%ld\n", 59bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->a1, n, VG_(sizeXA)(p->last_sem_post_seg)); 603e017fa58a7c090cee54809baa4f5be78cb4eef9bart#endif 61bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(*(Segment**)VG_(indexXA)(p->last_sem_post_seg, n) == sg); 623e017fa58a7c090cee54809baa4f5be78cb4eef9bart} 633e017fa58a7c090cee54809baa4f5be78cb4eef9bart 64dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** Pop a segment from the beginning of the queue 'p->last_sem_post_seg'. */ 6525f9f5411f64046c2ffc0822f727aedc21f07720bartstatic Segment* drd_segment_pop(struct semaphore_info* p) 663e017fa58a7c090cee54809baa4f5be78cb4eef9bart{ 67bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Word sz; 68bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* sg; 693e017fa58a7c090cee54809baa4f5be78cb4eef9bart 70bedfd237fbdc80d0c917cfcb85a94b5561c92633bart sz = VG_(sizeXA)(p->last_sem_post_seg); 713e017fa58a7c090cee54809baa4f5be78cb4eef9bart#if 0 729af04c49df08365aa568b3a27ffa5b2a1274a987florian VG_(message)(Vg_DebugMsg, "0x%lx pop: removed from position %ld/%ld\n", 73bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->a1, sz - 1, sz); 743e017fa58a7c090cee54809baa4f5be78cb4eef9bart#endif 75bedfd237fbdc80d0c917cfcb85a94b5561c92633bart sg = 0; 76bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (sz > 0) 77bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 78bedfd237fbdc80d0c917cfcb85a94b5561c92633bart sg = *(Segment**)VG_(indexXA)(p->last_sem_post_seg, sz - 1); 79bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sg); 80bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(dropTailXA)(p->last_sem_post_seg, 1); 81bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 82bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return sg; 833e017fa58a7c090cee54809baa4f5be78cb4eef9bart} 843e017fa58a7c090cee54809baa4f5be78cb4eef9bart 85dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** Enable or disable tracing of semaphore actions. */ 86dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(semaphore_set_trace)(const Bool trace_semaphore) 878564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 88bedfd237fbdc80d0c917cfcb85a94b5561c92633bart s_trace_semaphore = trace_semaphore; 898564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 908564292ac4b9adf51c45517cca2878732feb5bb4sewardj 91dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** 92dc1ef03a8d13efe24661a89091e66169bf3f1091bart * Initialize the memory 'p' points at as a semaphore_info structure for the 93dc1ef03a8d13efe24661a89091e66169bf3f1091bart * client semaphore at client addres 'semaphore'. 94dc1ef03a8d13efe24661a89091e66169bf3f1091bart */ 958564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 9625f9f5411f64046c2ffc0822f727aedc21f07720bartvoid drd_semaphore_initialize(struct semaphore_info* const p, 9725f9f5411f64046c2ffc0822f727aedc21f07720bart const Addr semaphore) 988564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 99bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(semaphore != 0); 100bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->a1 == semaphore); 101bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->type == ClientSemaphore); 102bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 103bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup; 104bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->delete_thread = 0; 105bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->waits_to_skip = 0; 106bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->value = 0; 107bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->waiters = 0; 108bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->last_sem_post_tid = DRD_INVALID_THREADID; 109bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->last_sem_post_seg = VG_(newXA)(VG_(malloc), "drd.sg-stack", 110bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(free), sizeof(Segment*)); 1118564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1128564292ac4b9adf51c45517cca2878732feb5bb4sewardj 113195e41fe2b9e02e142a0461113bfa55c89d24c5ebart/** 114195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * Free the memory that was allocated by semaphore_initialize(). Called by 115195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * DRD_(clientobj_remove)(). 11628230a3734e045791173aca660efc7d7aeef78cebart */ 117d2c5eae561040706a7eb45c0f3988dcd538c8d7ebartstatic void semaphore_cleanup(struct semaphore_info* p) 11828230a3734e045791173aca660efc7d7aeef78cebart{ 119bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* sg; 120bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 121bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->waiters > 0) 122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 123d45d99553c15a361bb797d21ec6afb9bad22d2d4bart SemaphoreErrInfo sei = { DRD_(thread_get_running_tid)(), p->a1 }; 124bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 125bedfd237fbdc80d0c917cfcb85a94b5561c92633bart SemaphoreErr, 126bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 127bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destruction of semaphore that is being waited" 128bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " upon", 129bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &sei); 130bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 13125f9f5411f64046c2ffc0822f727aedc21f07720bart while ((sg = drd_segment_pop(p))) 132bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(sg); 133bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(deleteXA)(p->last_sem_post_seg); 13428230a3734e045791173aca660efc7d7aeef78cebart} 13528230a3734e045791173aca660efc7d7aeef78cebart 136dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** 137dc1ef03a8d13efe24661a89091e66169bf3f1091bart * Return a pointer to the structure with information about the specified 138dc1ef03a8d13efe24661a89091e66169bf3f1091bart * client semaphore. Allocate a new structure if such a structure did not 139dc1ef03a8d13efe24661a89091e66169bf3f1091bart * yet exist. 140dc1ef03a8d13efe24661a89091e66169bf3f1091bart */ 1418564292ac4b9adf51c45517cca2878732feb5bb4sewardjstatic 1428564292ac4b9adf51c45517cca2878732feb5bb4sewardjstruct semaphore_info* 14325f9f5411f64046c2ffc0822f727aedc21f07720bartdrd_semaphore_get_or_allocate(const Addr semaphore) 1448564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 145bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct semaphore_info *p; 146bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 147bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, semaphore) == 0); 148bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore); 149bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 150bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 151bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, semaphore) == 0); 152bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_add)(semaphore, ClientSemaphore)->semaphore); 15325f9f5411f64046c2ffc0822f727aedc21f07720bart drd_semaphore_initialize(p, semaphore); 154bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 155bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p; 15628230a3734e045791173aca660efc7d7aeef78cebart} 15728230a3734e045791173aca660efc7d7aeef78cebart 158dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** 159dc1ef03a8d13efe24661a89091e66169bf3f1091bart * Return a pointer to the structure with information about the specified 160dc1ef03a8d13efe24661a89091e66169bf3f1091bart * client semaphore, or null if no such structure was found. 161dc1ef03a8d13efe24661a89091e66169bf3f1091bart */ 162d45d99553c15a361bb797d21ec6afb9bad22d2d4bartstatic struct semaphore_info* semaphore_get(const Addr semaphore) 16328230a3734e045791173aca660efc7d7aeef78cebart{ 164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, semaphore) == 0); 165bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore); 1668564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 1678564292ac4b9adf51c45517cca2878732feb5bb4sewardj 16828230a3734e045791173aca660efc7d7aeef78cebart/** Called before sem_init(). */ 169dc1ef03a8d13efe24661a89091e66169bf3f1091bartstruct semaphore_info* DRD_(semaphore_init)(const Addr semaphore, 170dc1ef03a8d13efe24661a89091e66169bf3f1091bart const Word pshared, 171dc1ef03a8d13efe24661a89091e66169bf3f1091bart const UInt value) 1728564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 173bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct semaphore_info* p; 174bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* sg; 175bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 176bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_semaphore) 177ad994e885caeb5241cbedf4e47e7821cf164f4e7bart DRD_(trace_msg)("[%d] sem_init 0x%lx value %u", 178b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), semaphore, value); 179b92ff0fd192dd05700f7d20db00795965e20b5c5bart 180d45d99553c15a361bb797d21ec6afb9bad22d2d4bart p = semaphore_get(semaphore); 181bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p) 182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const ThreadId vg_tid = VG_(get_running_tid)(); 184d45d99553c15a361bb797d21ec6afb9bad22d2d4bart SemaphoreErrInfo SEI = { DRD_(thread_get_running_tid)(), semaphore }; 185bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(vg_tid, 186bedfd237fbdc80d0c917cfcb85a94b5561c92633bart SemaphoreErr, 187bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(vg_tid), 188bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Semaphore reinitialization", 189bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &SEI); 190bedfd237fbdc80d0c917cfcb85a94b5561c92633bart // Remove all segments from the segment stack. 19125f9f5411f64046c2ffc0822f727aedc21f07720bart while ((sg = drd_segment_pop(p))) 192bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 193bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(sg_put)(sg); 194bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 195bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 198b7037bb42882b1783dbd79823573ad8027ad2978bart#if defined(VGO_darwin) 199b7037bb42882b1783dbd79823573ad8027ad2978bart const ThreadId vg_tid = VG_(get_running_tid)(); 200a9d292ea80e21d5987cab5954771ef02b7890737bart GenericErrInfo GEI = { DRD_(thread_get_running_tid)(), 0 }; 201b7037bb42882b1783dbd79823573ad8027ad2978bart VG_(maybe_record_error)(vg_tid, 202b7037bb42882b1783dbd79823573ad8027ad2978bart GenericErr, 203b7037bb42882b1783dbd79823573ad8027ad2978bart VG_(get_IP)(vg_tid), 204b7037bb42882b1783dbd79823573ad8027ad2978bart "sem_init() is not yet supported on Darwin", 205b7037bb42882b1783dbd79823573ad8027ad2978bart &GEI); 206b7037bb42882b1783dbd79823573ad8027ad2978bart return NULL; 207b7037bb42882b1783dbd79823573ad8027ad2978bart#else 20825f9f5411f64046c2ffc0822f727aedc21f07720bart p = drd_semaphore_get_or_allocate(semaphore); 209b7037bb42882b1783dbd79823573ad8027ad2978bart#endif 210bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 211bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 212bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->waits_to_skip = value; 213bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->value = value; 214bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p; 2158564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 2168564292ac4b9adf51c45517cca2878732feb5bb4sewardj 21728230a3734e045791173aca660efc7d7aeef78cebart/** Called after sem_destroy(). */ 218dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(semaphore_destroy)(const Addr semaphore) 2198564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 220bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct semaphore_info* p; 221bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 222d45d99553c15a361bb797d21ec6afb9bad22d2d4bart p = semaphore_get(semaphore); 223bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 224bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_semaphore) 225ad994e885caeb5241cbedf4e47e7821cf164f4e7bart DRD_(trace_msg)("[%d] sem_destroy 0x%lx value %u", 226b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), semaphore, 227b92ff0fd192dd05700f7d20db00795965e20b5c5bart p ? p->value : 0); 228bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 229bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 230bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 23162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErrInfo GEI = { 23262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .tid = DRD_(thread_get_running_tid)(), 23362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .addr = semaphore, 23462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 235bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 236bedfd237fbdc80d0c917cfcb85a94b5561c92633bart GenericErr, 237bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 238bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Not a semaphore", 239bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &GEI); 240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 242bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(clientobj_remove)(semaphore, ClientSemaphore); 2448564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 2458564292ac4b9adf51c45517cca2878732feb5bb4sewardj 24625f9f5411f64046c2ffc0822f727aedc21f07720bart/** Called after sem_open(). */ 24725f9f5411f64046c2ffc0822f727aedc21f07720bartstruct semaphore_info* DRD_(semaphore_open)(const Addr semaphore, 24819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian const HChar* name, const Word oflag, 24925f9f5411f64046c2ffc0822f727aedc21f07720bart const Word mode, const UInt value) 25025f9f5411f64046c2ffc0822f727aedc21f07720bart{ 25125f9f5411f64046c2ffc0822f727aedc21f07720bart struct semaphore_info* p; 25225f9f5411f64046c2ffc0822f727aedc21f07720bart Segment* sg; 25325f9f5411f64046c2ffc0822f727aedc21f07720bart 25425f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_trace_semaphore) 255b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(trace_msg)("[%d] sem_open 0x%lx name %s" 256ad994e885caeb5241cbedf4e47e7821cf164f4e7bart " oflag %#lx mode %#lo value %u", 257b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 258b92ff0fd192dd05700f7d20db00795965e20b5c5bart semaphore, name, oflag, mode, value); 25925f9f5411f64046c2ffc0822f727aedc21f07720bart 26025f9f5411f64046c2ffc0822f727aedc21f07720bart /* Return if the sem_open() call failed. */ 26125f9f5411f64046c2ffc0822f727aedc21f07720bart if (! semaphore) 26225f9f5411f64046c2ffc0822f727aedc21f07720bart return NULL; 26325f9f5411f64046c2ffc0822f727aedc21f07720bart 26425f9f5411f64046c2ffc0822f727aedc21f07720bart p = semaphore_get(semaphore); 26525f9f5411f64046c2ffc0822f727aedc21f07720bart if (p) 26625f9f5411f64046c2ffc0822f727aedc21f07720bart { 26725f9f5411f64046c2ffc0822f727aedc21f07720bart const ThreadId vg_tid = VG_(get_running_tid)(); 26825f9f5411f64046c2ffc0822f727aedc21f07720bart SemaphoreErrInfo SEI = { DRD_(thread_get_running_tid)(), semaphore }; 26925f9f5411f64046c2ffc0822f727aedc21f07720bart VG_(maybe_record_error)(vg_tid, 27025f9f5411f64046c2ffc0822f727aedc21f07720bart SemaphoreErr, 27125f9f5411f64046c2ffc0822f727aedc21f07720bart VG_(get_IP)(vg_tid), 27225f9f5411f64046c2ffc0822f727aedc21f07720bart "Semaphore reinitialization", 27325f9f5411f64046c2ffc0822f727aedc21f07720bart &SEI); 27425f9f5411f64046c2ffc0822f727aedc21f07720bart // Remove all segments from the segment stack. 27525f9f5411f64046c2ffc0822f727aedc21f07720bart while ((sg = drd_segment_pop(p))) 27625f9f5411f64046c2ffc0822f727aedc21f07720bart { 27725f9f5411f64046c2ffc0822f727aedc21f07720bart DRD_(sg_put)(sg); 27825f9f5411f64046c2ffc0822f727aedc21f07720bart } 27925f9f5411f64046c2ffc0822f727aedc21f07720bart } 28025f9f5411f64046c2ffc0822f727aedc21f07720bart else 28125f9f5411f64046c2ffc0822f727aedc21f07720bart { 28225f9f5411f64046c2ffc0822f727aedc21f07720bart p = drd_semaphore_get_or_allocate(semaphore); 28325f9f5411f64046c2ffc0822f727aedc21f07720bart } 28425f9f5411f64046c2ffc0822f727aedc21f07720bart tl_assert(p); 28525f9f5411f64046c2ffc0822f727aedc21f07720bart p->waits_to_skip = value; 28625f9f5411f64046c2ffc0822f727aedc21f07720bart p->value = value; 28725f9f5411f64046c2ffc0822f727aedc21f07720bart return p; 28825f9f5411f64046c2ffc0822f727aedc21f07720bart} 28925f9f5411f64046c2ffc0822f727aedc21f07720bart 29025f9f5411f64046c2ffc0822f727aedc21f07720bart/** Called before sem_close(). */ 29125f9f5411f64046c2ffc0822f727aedc21f07720bartvoid DRD_(semaphore_close)(const Addr semaphore) 29225f9f5411f64046c2ffc0822f727aedc21f07720bart{ 29325f9f5411f64046c2ffc0822f727aedc21f07720bart struct semaphore_info* p; 29425f9f5411f64046c2ffc0822f727aedc21f07720bart 29525f9f5411f64046c2ffc0822f727aedc21f07720bart p = semaphore_get(semaphore); 29625f9f5411f64046c2ffc0822f727aedc21f07720bart 29725f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_trace_semaphore) 298ad994e885caeb5241cbedf4e47e7821cf164f4e7bart DRD_(trace_msg)("[%d] sem_close 0x%lx value %u", 299b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), semaphore, 300b92ff0fd192dd05700f7d20db00795965e20b5c5bart p ? p->value : 0); 30125f9f5411f64046c2ffc0822f727aedc21f07720bart 30225f9f5411f64046c2ffc0822f727aedc21f07720bart if (p == 0) 30325f9f5411f64046c2ffc0822f727aedc21f07720bart { 30462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErrInfo GEI = { 30562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .tid = DRD_(thread_get_running_tid)(), 30662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .addr = semaphore, 30762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 30825f9f5411f64046c2ffc0822f727aedc21f07720bart VG_(maybe_record_error)(VG_(get_running_tid)(), 30925f9f5411f64046c2ffc0822f727aedc21f07720bart GenericErr, 31025f9f5411f64046c2ffc0822f727aedc21f07720bart VG_(get_IP)(VG_(get_running_tid)()), 31125f9f5411f64046c2ffc0822f727aedc21f07720bart "Not a semaphore", 31225f9f5411f64046c2ffc0822f727aedc21f07720bart &GEI); 31325f9f5411f64046c2ffc0822f727aedc21f07720bart return; 31425f9f5411f64046c2ffc0822f727aedc21f07720bart } 31525f9f5411f64046c2ffc0822f727aedc21f07720bart 31625f9f5411f64046c2ffc0822f727aedc21f07720bart DRD_(clientobj_remove)(semaphore, ClientSemaphore); 31725f9f5411f64046c2ffc0822f727aedc21f07720bart} 31825f9f5411f64046c2ffc0822f727aedc21f07720bart 31928230a3734e045791173aca660efc7d7aeef78cebart/** Called before sem_wait(). */ 320dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(semaphore_pre_wait)(const Addr semaphore) 3218564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 322bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct semaphore_info* p; 32328230a3734e045791173aca660efc7d7aeef78cebart 3247a06e12b210e31acaa960be429f086726a67f6ddbart tl_assert(semaphore < semaphore + 1); 32525f9f5411f64046c2ffc0822f727aedc21f07720bart p = drd_semaphore_get_or_allocate(semaphore); 326bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 327bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->waiters++; 3283eecd9a3377cb6dd7637ea051ef2167023c93a61bart 3299986c99e20f6f0acd5a3ce547a53a5df4f95f70fbart if ((Word)(p->waiters) <= 0) 3303eecd9a3377cb6dd7637ea051ef2167023c93a61bart { 3313eecd9a3377cb6dd7637ea051ef2167023c93a61bart SemaphoreErrInfo sei = { DRD_(thread_get_running_tid)(), semaphore }; 3323eecd9a3377cb6dd7637ea051ef2167023c93a61bart VG_(maybe_record_error)(VG_(get_running_tid)(), 3333eecd9a3377cb6dd7637ea051ef2167023c93a61bart SemaphoreErr, 3343eecd9a3377cb6dd7637ea051ef2167023c93a61bart VG_(get_IP)(VG_(get_running_tid)()), 3353eecd9a3377cb6dd7637ea051ef2167023c93a61bart "Invalid semaphore", 3363eecd9a3377cb6dd7637ea051ef2167023c93a61bart &sei); 3373eecd9a3377cb6dd7637ea051ef2167023c93a61bart } 3388564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 3398564292ac4b9adf51c45517cca2878732feb5bb4sewardj 340dc1ef03a8d13efe24661a89091e66169bf3f1091bart/** 341dc1ef03a8d13efe24661a89091e66169bf3f1091bart * Called after sem_wait() finished. 342333e42bd5e2617c804d336ad6009b0ad13960d46bart * @note Some C libraries do not set the 'waited' value correctly. 34328230a3734e045791173aca660efc7d7aeef78cebart */ 344dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore, 345dc1ef03a8d13efe24661a89091e66169bf3f1091bart const Bool waited) 3468564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 347bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct semaphore_info* p; 348bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* sg; 349bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 350311abd6254c497dcbb2c1ef09d94593fb5524369bart tl_assert(waited == 0 || waited == 1); 351d45d99553c15a361bb797d21ec6afb9bad22d2d4bart p = semaphore_get(semaphore); 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_semaphore) 353311abd6254c497dcbb2c1ef09d94593fb5524369bart DRD_(trace_msg)("[%d] sem_wait 0x%lx value %u -> %u%s", 354b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), semaphore, 355311abd6254c497dcbb2c1ef09d94593fb5524369bart p ? p->value : 0, p ? p->value - waited : 0, 356311abd6254c497dcbb2c1ef09d94593fb5524369bart waited ? "" : " (did not wait)"); 35757ae7ad7e5b468d976ef43001f603bdbc842c53ebart 358333e42bd5e2617c804d336ad6009b0ad13960d46bart if (p) { 35957ae7ad7e5b468d976ef43001f603bdbc842c53ebart p->waiters--; 360311abd6254c497dcbb2c1ef09d94593fb5524369bart p->value -= waited; 36157ae7ad7e5b468d976ef43001f603bdbc842c53ebart } 36257ae7ad7e5b468d976ef43001f603bdbc842c53ebart 36357ae7ad7e5b468d976ef43001f603bdbc842c53ebart /* 36457ae7ad7e5b468d976ef43001f603bdbc842c53ebart * Note: if another thread destroyed and reinitialized a semaphore while 36557ae7ad7e5b468d976ef43001f603bdbc842c53ebart * the current thread was waiting in sem_wait, p->waiters may have been 36625f9f5411f64046c2ffc0822f727aedc21f07720bart * set to zero by drd_semaphore_initialize() after 36757ae7ad7e5b468d976ef43001f603bdbc842c53ebart * DRD_(semaphore_pre_wait)() has finished before 36857ae7ad7e5b468d976ef43001f603bdbc842c53ebart * DRD_(semaphore_post_wait)() has been called. 36957ae7ad7e5b468d976ef43001f603bdbc842c53ebart */ 3709986c99e20f6f0acd5a3ce547a53a5df4f95f70fbart if (p == NULL || (Int)(p->value) < 0 || (Word)(p->waiters) < 0) 371bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 372d45d99553c15a361bb797d21ec6afb9bad22d2d4bart SemaphoreErrInfo sei = { DRD_(thread_get_running_tid)(), semaphore }; 373bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 374bedfd237fbdc80d0c917cfcb85a94b5561c92633bart SemaphoreErr, 375bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 376bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Invalid semaphore", 377bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &sei); 378bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 379bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 38057ae7ad7e5b468d976ef43001f603bdbc842c53ebart 381333e42bd5e2617c804d336ad6009b0ad13960d46bart if (!waited) 382333e42bd5e2617c804d336ad6009b0ad13960d46bart return; 383333e42bd5e2617c804d336ad6009b0ad13960d46bart 384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->waits_to_skip > 0) 385bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->waits_to_skip--; 386bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 387bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 38825f9f5411f64046c2ffc0822f727aedc21f07720bart sg = drd_segment_pop(p); 389bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sg); 3907a2cc3c5be225eb49813c1460d861481ee490d6ebart if (p->last_sem_post_tid != tid 3917a2cc3c5be225eb49813c1460d861481ee490d6ebart && p->last_sem_post_tid != DRD_INVALID_THREADID) 39294866ccb7b8476762d57ab41c61e59c1189a0107bart { 3937a2cc3c5be225eb49813c1460d861481ee490d6ebart DRD_(thread_new_segment_and_combine_vc)(tid, sg); 39494866ccb7b8476762d57ab41c61e59c1189a0107bart } 3957a2cc3c5be225eb49813c1460d861481ee490d6ebart else 3967a2cc3c5be225eb49813c1460d861481ee490d6ebart DRD_(thread_new_segment)(tid); 3977a2cc3c5be225eb49813c1460d861481ee490d6ebart s_semaphore_segment_creation_count++; 3987a2cc3c5be225eb49813c1460d861481ee490d6ebart DRD_(sg_put)(sg); 399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 4008564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4018564292ac4b9adf51c45517cca2878732feb5bb4sewardj 4028564292ac4b9adf51c45517cca2878732feb5bb4sewardj/** Called before sem_post(). */ 403dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(semaphore_pre_post)(const DrdThreadId tid, const Addr semaphore) 4048564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 405bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct semaphore_info* p; 406bedfd237fbdc80d0c917cfcb85a94b5561c92633bart Segment* sg; 407bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 40825f9f5411f64046c2ffc0822f727aedc21f07720bart p = drd_semaphore_get_or_allocate(semaphore); 409bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->value++; 410bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 411bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (s_trace_semaphore) 412ad994e885caeb5241cbedf4e47e7821cf164f4e7bart DRD_(trace_msg)("[%d] sem_post 0x%lx value %u -> %u", 413b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), 414b92ff0fd192dd05700f7d20db00795965e20b5c5bart semaphore, p->value - 1, p->value); 415bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 416bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->last_sem_post_tid = tid; 417bedfd237fbdc80d0c917cfcb85a94b5561c92633bart sg = 0; 418bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_latest_segment)(&sg, tid); 419bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(sg); 42025f9f5411f64046c2ffc0822f727aedc21f07720bart drd_segment_push(p, sg); 421c02dde4a6856703692de465fa621d20c9ec65ca4bart DRD_(thread_new_segment)(tid); 422bedfd237fbdc80d0c917cfcb85a94b5561c92633bart s_semaphore_segment_creation_count++; 4238564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4248564292ac4b9adf51c45517cca2878732feb5bb4sewardj 425d45d99553c15a361bb797d21ec6afb9bad22d2d4bart/** Called after sem_post() finished. */ 426dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(semaphore_post_post)(const DrdThreadId tid, const Addr semaphore, 427d45d99553c15a361bb797d21ec6afb9bad22d2d4bart const Bool succeeded) 4288564292ac4b9adf51c45517cca2878732feb5bb4sewardj{ 429d45d99553c15a361bb797d21ec6afb9bad22d2d4bart /* 43031b983d29affe6c30a2283be8824c6d75c74d848bart * Note: it is hard to implement the sem_post() wrapper correctly in 43131b983d29affe6c30a2283be8824c6d75c74d848bart * case sem_post() returns an error code. This is because handling this 43231b983d29affe6c30a2283be8824c6d75c74d848bart * case correctly requires restoring the vector clock associated with 433d45d99553c15a361bb797d21ec6afb9bad22d2d4bart * the semaphore to its original value here. In order to do that without 43431b983d29affe6c30a2283be8824c6d75c74d848bart * introducing a race condition, extra locking has to be added around 43531b983d29affe6c30a2283be8824c6d75c74d848bart * each semaphore call. Such extra locking would have to be added in 436d45d99553c15a361bb797d21ec6afb9bad22d2d4bart * drd_pthread_intercepts.c. However, it is hard to implement 437d45d99553c15a361bb797d21ec6afb9bad22d2d4bart * synchronization in drd_pthread_intercepts.c in a portable way without 438d45d99553c15a361bb797d21ec6afb9bad22d2d4bart * calling already redirected functions. 439d45d99553c15a361bb797d21ec6afb9bad22d2d4bart */ 4408564292ac4b9adf51c45517cca2878732feb5bb4sewardj} 4418564292ac4b9adf51c45517cca2878732feb5bb4sewardj 442dc1ef03a8d13efe24661a89091e66169bf3f1091bartULong DRD_(get_semaphore_segment_creation_count)(void) 4436bbefaf8418f3e225c4eefcc726b6874bef15d8cbart{ 444bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return s_semaphore_segment_creation_count; 4456bbefaf8418f3e225c4eefcc726b6874bef15d8cbart} 446