| |
| /*--------------------------------------------------------------------*/ |
| /*--- Definitions for Locks and Threads. ---*/ |
| /*--- hg_lock_n_thread.c ---*/ |
| /*--------------------------------------------------------------------*/ |
| |
| /* |
| This file is part of Helgrind, a Valgrind tool for detecting errors |
| in threaded programs. |
| |
| Copyright (C) 2007-2013 OpenWorks Ltd |
| info@open-works.co.uk |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License as |
| published by the Free Software Foundation; either version 2 of the |
| License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| The GNU General Public License is contained in the file COPYING. |
| */ |
| |
| #include "pub_tool_basics.h" |
| #include "pub_tool_libcbase.h" |
| #include "pub_tool_libcassert.h" |
| #include "pub_tool_execontext.h" |
| #include "pub_tool_threadstate.h" |
| #include "pub_tool_wordfm.h" |
| |
| #include "hg_basics.h" |
| #include "hg_wordset.h" |
| #include "hg_lock_n_thread.h" /* self */ |
| |
| |
| /*----------------------------------------------------------------*/ |
| /*--- Sanity checking ---*/ |
| /*----------------------------------------------------------------*/ |
| |
| inline Bool HG_(is_sane_Thread) ( Thread* thr ) { |
| return thr != NULL && thr->magic == Thread_MAGIC; |
| } |
| |
| static Bool is_sane_Bag_of_Threads ( WordBag* bag ) |
| { |
| Thread* thr; |
| UWord count; |
| VG_(initIterBag)( bag ); |
| while (VG_(nextIterBag)( bag, (UWord*)&thr, &count )) { |
| if (count < 1) return False; |
| if (!HG_(is_sane_Thread)(thr)) return False; |
| } |
| VG_(doneIterBag)( bag ); |
| return True; |
| } |
| |
| static Bool is_sane_Lock_BASE ( Lock* lock ) |
| { |
| if (lock == NULL |
| || (lock->magic != LockN_MAGIC && lock->magic != LockP_MAGIC)) |
| return False; |
| switch (lock->kind) { |
| case LK_mbRec: case LK_nonRec: case LK_rdwr: break; |
| default: return False; |
| } |
| if (lock->heldBy == NULL) { |
| if (lock->acquired_at != NULL) return False; |
| /* Unheld. We arbitrarily require heldW to be False. */ |
| return !lock->heldW; |
| } else { |
| if (lock->acquired_at == NULL) return False; |
| } |
| |
| /* If heldBy is non-NULL, we require it to contain at least one |
| thread. */ |
| if (VG_(isEmptyBag)(lock->heldBy)) |
| return False; |
| |
| /* Lock is either r- or w-held. */ |
| if (!is_sane_Bag_of_Threads(lock->heldBy)) |
| return False; |
| if (lock->heldW) { |
| /* Held in write-mode */ |
| if ((lock->kind == LK_nonRec || lock->kind == LK_rdwr) |
| && !VG_(isSingletonTotalBag)(lock->heldBy)) |
| return False; |
| } else { |
| /* Held in read-mode */ |
| if (lock->kind != LK_rdwr) return False; |
| } |
| return True; |
| } |
| |
| Bool HG_(is_sane_LockP) ( Lock* lock ) { |
| return lock != NULL |
| && lock->magic == LockP_MAGIC |
| && lock->hbso == NULL |
| && is_sane_Lock_BASE(lock); |
| } |
| |
| Bool HG_(is_sane_LockN) ( Lock* lock ) { |
| return lock != NULL |
| && lock->magic == LockN_MAGIC |
| && lock->hbso != NULL |
| && is_sane_Lock_BASE(lock); |
| } |
| |
| Bool HG_(is_sane_LockNorP) ( Lock* lock ) { |
| return is_sane_Lock_BASE(lock); |
| } |
| |
| |
| /*--------------------------------------------------------------------*/ |
| /*--- end hg_lock_n_thread.c ---*/ |
| /*--------------------------------------------------------------------*/ |