Home | History | Annotate | Download | only in m_scheduler
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Semaphore stuff.                                      sema.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2000-2012 Julian Seward
     11       jseward (at) acm.org
     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 
     31 #include "pub_core_basics.h"
     32 #include "pub_core_debuglog.h"
     33 #include "pub_core_vki.h"
     34 #include "pub_core_libcassert.h"
     35 #include "pub_core_libcfile.h"
     36 #include "pub_core_libcproc.h"      // For VG_(gettid)()
     37 #include "pub_tool_inner.h"
     38 #if defined(ENABLE_INNER_CLIENT_REQUEST)
     39 #include "helgrind/helgrind.h"
     40 #endif
     41 #include "priv_sema.h"
     42 
     43 /*
     44    Slower (than the removed futex-based sema scheme) but more portable
     45    pipe-based token passing scheme.
     46  */
     47 
     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. */
     52 static Char sema_char = '!'; /* will cause assertion failures if used
     53                                 before sema_init */
     54 
     55 void ML_(sema_init)(vg_sema_t *sema)
     56 {
     57    Char buf[2];
     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 
     64    sema->pipe[0] = VG_(safe_fd)(sema->pipe[0]);
     65    sema->pipe[1] = VG_(safe_fd)(sema->pipe[1]);
     66 
     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 
     72    sema->owner_lwpid = -1;
     73 
     74    /* create initial token */
     75    sema_char = 'A';
     76    buf[0] = sema_char;
     77    buf[1] = 0;
     78    sema_char++;
     79    INNER_REQUEST(ANNOTATE_RWLOCK_CREATE(sema));
     80    INNER_REQUEST(ANNOTATE_BENIGN_RACE_SIZED(&sema->owner_lwpid,
     81                                             sizeof(sema->owner_lwpid), ""));
     82    res = VG_(write)(sema->pipe[1], buf, 1);
     83    vg_assert(res == 1);
     84 }
     85 
     86 void ML_(sema_deinit)(vg_sema_t *sema)
     87 {
     88    vg_assert(sema->owner_lwpid != -1); /* must be initialised */
     89    vg_assert(sema->pipe[0] != sema->pipe[1]);
     90    INNER_REQUEST(ANNOTATE_RWLOCK_DESTROY(sema));
     91    VG_(close)(sema->pipe[0]);
     92    VG_(close)(sema->pipe[1]);
     93    sema->pipe[0] = sema->pipe[1] = -1;
     94    sema->owner_lwpid = -1;
     95 }
     96 
     97 /* get a token */
     98 void ML_(sema_down)( vg_sema_t *sema, Bool as_LL )
     99 {
    100    Char buf[2];
    101    Int ret;
    102    Int lwpid = VG_(gettid)();
    103 
    104    vg_assert(sema->owner_lwpid != lwpid); /* can't have it already */
    105    vg_assert(sema->pipe[0] != sema->pipe[1]);
    106 
    107   again:
    108    buf[0] = buf[1] = 0;
    109    ret = VG_(read)(sema->pipe[0], buf, 1);
    110    INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema, /*is_w*/1));
    111 
    112    if (ret != 1)
    113       VG_(debugLog)(0, "scheduler",
    114                        "VG_(sema_down): read returned %d\n", ret);
    115 
    116    if (ret == -VKI_EINTR)
    117       goto again;
    118 
    119    vg_assert(ret == 1);		/* should get exactly 1 token */
    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++;
    124 
    125    sema->owner_lwpid = lwpid;
    126    sema->held_as_LL = as_LL;
    127 }
    128 
    129 /* put token back */
    130 void ML_(sema_up)( vg_sema_t *sema, Bool as_LL )
    131 {
    132    Int ret;
    133    Char buf[2];
    134    vg_assert(as_LL == sema->held_as_LL);
    135    buf[0] = sema_char;
    136    buf[1] = 0;
    137    vg_assert(sema->owner_lwpid != -1); /* must be initialised */
    138    vg_assert(sema->pipe[0] != sema->pipe[1]);
    139    vg_assert(sema->owner_lwpid == VG_(gettid)()); /* must have it */
    140 
    141    sema->owner_lwpid = 0;
    142 
    143    INNER_REQUEST(ANNOTATE_RWLOCK_RELEASED(sema, /*is_w*/1));
    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 
    150    vg_assert(ret == 1);
    151 }
    152 
    153 /*--------------------------------------------------------------------*/
    154 /*--- end                                                          ---*/
    155 /*--------------------------------------------------------------------*/
    156 
    157 
    158