1f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
3f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- Definitions for Locks and Threads.                           ---*/
4f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                           hg_lock_n_thread.c ---*/
5f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
6f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
7f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*
8f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   This file is part of Helgrind, a Valgrind tool for detecting errors
9f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   in threaded programs.
10f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
11ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2007-2017 OpenWorks Ltd
12f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      info@open-works.co.uk
13f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
14f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   This program is free software; you can redistribute it and/or
15f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   modify it under the terms of the GNU General Public License as
16f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   published by the Free Software Foundation; either version 2 of the
17f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   License, or (at your option) any later version.
18f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
19f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   This program is distributed in the hope that it will be useful, but
20f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   General Public License for more details.
23f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   You should have received a copy of the GNU General Public License
25f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   along with this program; if not, write to the Free Software
26f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   02111-1307, USA.
28f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
29f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   The GNU General Public License is contained in the file COPYING.
30f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
31f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
32f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_basics.h"
33f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_libcbase.h"
34f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_libcassert.h"
35f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_execontext.h"
36f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_threadstate.h"
37f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_wordfm.h"
38f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
39f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_basics.h"
40f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_wordset.h"
41f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_lock_n_thread.h"            /* self */
42f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
43f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
44f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*----------------------------------------------------------------*/
45f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- Sanity checking                                          ---*/
46f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*----------------------------------------------------------------*/
47f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
48f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjinline Bool HG_(is_sane_Thread) ( Thread* thr ) {
49f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return thr != NULL && thr->magic == Thread_MAGIC;
50f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
51f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
52f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool is_sane_Bag_of_Threads ( WordBag* bag )
53f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
54f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Thread* thr;
556bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorian   UWord   count;
56f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(initIterBag)( bag );
576bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorian   while (VG_(nextIterBag)( bag, (UWord*)&thr, &count )) {
58f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (count < 1) return False;
59f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (!HG_(is_sane_Thread)(thr)) return False;
60f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
61f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(doneIterBag)( bag );
62f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return True;
63f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
64f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
65f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool is_sane_Lock_BASE ( Lock* lock )
66f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
67f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (lock == NULL
68f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj       || (lock->magic != LockN_MAGIC && lock->magic != LockP_MAGIC))
69f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return False;
70f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   switch (lock->kind) {
71f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case LK_mbRec: case LK_nonRec: case LK_rdwr: break;
72f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      default: return False;
73f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
74f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (lock->heldBy == NULL) {
75f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (lock->acquired_at != NULL) return False;
76f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Unheld.  We arbitrarily require heldW to be False. */
77f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return !lock->heldW;
78f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
79f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (lock->acquired_at == NULL) return False;
80f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
81f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
82f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* If heldBy is non-NULL, we require it to contain at least one
83f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      thread. */
84f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (VG_(isEmptyBag)(lock->heldBy))
85f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return False;
86f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
87f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* Lock is either r- or w-held. */
88f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (!is_sane_Bag_of_Threads(lock->heldBy))
89f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return False;
90f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (lock->heldW) {
91f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Held in write-mode */
92f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((lock->kind == LK_nonRec || lock->kind == LK_rdwr)
93f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && !VG_(isSingletonTotalBag)(lock->heldBy))
94f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return False;
95f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
96f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Held in read-mode */
97f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (lock->kind != LK_rdwr) return False;
98f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
99f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return True;
100f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjBool HG_(is_sane_LockP) ( Lock* lock ) {
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return lock != NULL
104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && lock->magic == LockP_MAGIC
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && lock->hbso  == NULL
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && is_sane_Lock_BASE(lock);
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
109f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjBool HG_(is_sane_LockN) ( Lock* lock ) {
110f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return lock != NULL
111f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && lock->magic == LockN_MAGIC
112f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && lock->hbso  != NULL
113f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          && is_sane_Lock_BASE(lock);
114f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
115f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
116f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjBool HG_(is_sane_LockNorP) ( Lock* lock ) {
117f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return is_sane_Lock_BASE(lock);
118f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
119f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
120f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
121f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
122f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- end                                       hg_lock_n_thread.c ---*/
123f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
124