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-2011 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 "priv_sema.h"
     38 
     39 /*
     40    Slower (than the removed futex-based sema scheme) but more portable
     41    pipe-based token passing scheme.
     42  */
     43 
     44 /* Cycle the char passed through the pipe through 'A' .. 'Z' to make
     45    it easier to make sense of strace/truss output - makes it possible
     46    to see more clearly the change of ownership of the lock.  Need to
     47    be careful to reinitialise it at fork() time. */
     48 static Char sema_char = '!'; /* will cause assertion failures if used
     49                                 before sema_init */
     50 
     51 void ML_(sema_init)(vg_sema_t *sema)
     52 {
     53    Char buf[2];
     54    Int res, r;
     55    r = VG_(pipe)(sema->pipe);
     56    vg_assert(r == 0);
     57 
     58    vg_assert(sema->pipe[0] != sema->pipe[1]);
     59 
     60    sema->pipe[0] = VG_(safe_fd)(sema->pipe[0]);
     61    sema->pipe[1] = VG_(safe_fd)(sema->pipe[1]);
     62 
     63    if (0)
     64       VG_(debugLog)(0,"zz","sema_init: %d %d\n", sema->pipe[0],
     65                                                  sema->pipe[1]);
     66    vg_assert(sema->pipe[0] != sema->pipe[1]);
     67 
     68    sema->owner_lwpid = -1;
     69 
     70    /* create initial token */
     71    sema_char = 'A';
     72    buf[0] = sema_char;
     73    buf[1] = 0;
     74    sema_char++;
     75    res = VG_(write)(sema->pipe[1], buf, 1);
     76    vg_assert(res == 1);
     77 }
     78 
     79 void ML_(sema_deinit)(vg_sema_t *sema)
     80 {
     81    vg_assert(sema->owner_lwpid != -1); /* must be initialised */
     82    vg_assert(sema->pipe[0] != sema->pipe[1]);
     83    VG_(close)(sema->pipe[0]);
     84    VG_(close)(sema->pipe[1]);
     85    sema->pipe[0] = sema->pipe[1] = -1;
     86    sema->owner_lwpid = -1;
     87 }
     88 
     89 /* get a token */
     90 void ML_(sema_down)( vg_sema_t *sema, Bool as_LL )
     91 {
     92    Char buf[2];
     93    Int ret;
     94    Int lwpid = VG_(gettid)();
     95 
     96    vg_assert(sema->owner_lwpid != lwpid); /* can't have it already */
     97    vg_assert(sema->pipe[0] != sema->pipe[1]);
     98 
     99   again:
    100    buf[0] = buf[1] = 0;
    101    ret = VG_(read)(sema->pipe[0], buf, 1);
    102 
    103    if (ret != 1)
    104       VG_(debugLog)(0, "scheduler",
    105                        "VG_(sema_down): read returned %d\n", ret);
    106 
    107    if (ret == -VKI_EINTR)
    108       goto again;
    109 
    110    vg_assert(ret == 1);		/* should get exactly 1 token */
    111    vg_assert(buf[0] >= 'A' && buf[0] <= 'Z');
    112    vg_assert(buf[1] == 0);
    113 
    114    if (sema_char == 'Z') sema_char = 'A'; else sema_char++;
    115 
    116    sema->owner_lwpid = lwpid;
    117    sema->held_as_LL = as_LL;
    118 }
    119 
    120 /* put token back */
    121 void ML_(sema_up)( vg_sema_t *sema, Bool as_LL )
    122 {
    123    Int ret;
    124    Char buf[2];
    125    vg_assert(as_LL == sema->held_as_LL);
    126    buf[0] = sema_char;
    127    buf[1] = 0;
    128    vg_assert(sema->owner_lwpid != -1); /* must be initialised */
    129    vg_assert(sema->pipe[0] != sema->pipe[1]);
    130    vg_assert(sema->owner_lwpid == VG_(gettid)()); /* must have it */
    131 
    132    sema->owner_lwpid = 0;
    133 
    134    ret = VG_(write)(sema->pipe[1], buf, 1);
    135 
    136    if (ret != 1)
    137       VG_(debugLog)(0, "scheduler",
    138                        "VG_(sema_up):write returned %d\n", ret);
    139 
    140    vg_assert(ret == 1);
    141 }
    142 
    143 /*--------------------------------------------------------------------*/
    144 /*--- end                                                          ---*/
    145 /*--------------------------------------------------------------------*/
    146 
    147 
    148