1 
2 /*--------------------------------------------------------------------*/
3 /*--- Definitions for Locks and Threads.                           ---*/
4 /*---                                           hg_lock_n_thread.h ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Helgrind, a Valgrind tool for detecting errors
9    in threaded programs.
10 
11    Copyright (C) 2007-2013 OpenWorks Ltd
12       info@open-works.co.uk
13 
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of the
17    License, or (at your option) any later version.
18 
19    This program is distributed in the hope that it will be useful, but
20    WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    General Public License for more details.
23 
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27    02111-1307, USA.
28 
29    The GNU General Public License is contained in the file COPYING.
30 */
31 
32 #ifndef __HG_LOCK_N_THREAD_H
33 #define __HG_LOCK_N_THREAD_H
34 
35 
36 /*----------------------------------------------------------------*/
37 /*--- Primary data definitions                                 ---*/
38 /*----------------------------------------------------------------*/
39 
40 /* Magic numbers, for doing assertions that structures really are of
41    the right type.  Useful as some of the code can get a bit
42    complex. */
43 #define Thread_MAGIC   0x504fc5e5
44 #define LockN_MAGIC    0x6545b557 /* normal nonpersistent locks */
45 #define LockP_MAGIC    0x755b5456 /* persistent (copied) locks */
46 
47 
48 /* These are handles for Word sets.  CONSTRAINTS: must be small ints
49    numbered from zero, since 32-bit versions of them are used to
50    encode lock-sets in libhb's history records (Thr_n_RCEC). */
51 typedef  WordSet  WordSetID;
52 
53 
54 /* Synchronisation Objects, exported abstractly by libhb. */
55 typedef  struct _SO  SO;
56 
57 /* Thr, libhb's private thread record, exported abstractly.  Thr's are
58    allocated and never deallocated (simply leaked).  Also ThrID, which
59    is a small integer which uniquely identifies a Thr and which is
60    used in ScalarTS because it is smaller than a Thr*.  There is a 1-1
61    mapping between Thr's and ThrIDs. */
62 typedef  struct _Thr  Thr;
63 typedef  UInt         ThrID;
64 
65 
66 /* Stores information about a thread.  Addresses of these also serve
67    as unique thread identifiers and so are never freed, so they should
68    be as small as possible.  Freeing Thread structures makes the
69    storage management just too complex, and most programs don't create
70    many threads, so tolerating this leak seems like a not-bad
71    tradeoff.
72 
73    Since these are never freed, the .coretid field only indicates the
74    core's ThreadId associated with this Thread whilst it is alive.
75    Once the thread finishes, the ThreadId is set to
76    VG_INVALID_THREADID.
77 
78    The core may later re-use the same ThreadId for what is a logically
79    completely different thread, which of course must have a different
80    Thread structure. */
81 typedef
82    struct _Thread {
83       /* ADMIN */
84       struct _Thread* admin;
85       UInt            magic;
86       Thr*            hbthr; /* which in turn points back here .. */
87       ThreadId        coretid;  /* .. via its hgthread field */
88       /* USEFUL */
89       WordSetID locksetA; /* WordSet of Lock* currently held by thread */
90       WordSetID locksetW; /* subset of locksetA held in w-mode */
91       /* EXPOSITION */
92       /* Place where parent was when this thread was created. */
93       ExeContext* created_at;
94       Bool        announced;
95       /* Index for generating references in error messages. */
96       Int         errmsg_index;
97    }
98    Thread;
99 
100 /* Get hg's admin_threads value, so libhb can visit all of them. */
101 Thread* get_admin_threads ( void );
102 
103 /* Stores information about a lock's current state.  These are
104    allocated and later freed (when the containing memory becomes
105    NoAccess).  This gives a problem for the XError type, which
106    contains Lock*s.  Solution is to copy any Lock which is to be
107    incorporated into an XErrors, so as to make it independent from the
108    'normal' collection of Locks, which can come and go.  When the lock
109    is copied, its .magic is changed from LockN_Magic to
110    LockP_Magic. */
111 
112 /* Lock kinds. */
113 typedef
114    enum {
115       LK_mbRec=1001, /* normal mutex, possibly recursive */
116       LK_nonRec,     /* normal mutex, definitely non recursive */
117       LK_rdwr        /* reader-writer lock */
118    }
119    LockKind;
120 
121 typedef
122    struct _Lock {
123       /* ADMIN */
124       struct _Lock* admin_next; /* fields for a double linked */
125       struct _Lock* admin_prev; /* list of these locks */
126       ULong         unique; /* used for persistence-hashing */
127       UInt          magic;  /* LockN_MAGIC or LockP_MAGIC */
128       /* EXPOSITION */
129       /* Place where lock first came to the attention of Helgrind. */
130       ExeContext*   appeared_at;
131       /* If the lock is held, place where the lock most recently made
132          an unlocked->locked transition.  Must be sync'd with .heldBy:
133          either both NULL or both non-NULL. */
134       ExeContext*   acquired_at;
135       /* USEFUL-STATIC */
136       SO*           hbso;      /* associated SO */
137       Addr          guestaddr; /* Guest address of lock */
138       LockKind      kind;      /* what kind of lock this is */
139       /* USEFUL-DYNAMIC */
140       Bool          heldW;
141       WordBag*      heldBy; /* bag of threads that hold this lock */
142       /* .heldBy is NULL: lock is unheld, and .heldW is meaningless
143                           but arbitrarily set to False
144          .heldBy is non-NULL:
145             .heldW is True:  lock is w-held by threads in heldBy
146             .heldW is False: lock is r-held by threads in heldBy
147             Either way, heldBy may not validly be an empty Bag.
148 
149          for LK_nonRec, r-holdings are not allowed, and w-holdings may
150          only have sizeTotal(heldBy) == 1
151 
152          for LK_mbRec, r-holdings are not allowed, and w-holdings may
153          only have sizeUnique(heldBy) == 1
154 
155          for LK_rdwr, w-holdings may only have sizeTotal(heldBy) == 1 */
156    }
157    Lock;
158 
159 #define Lock_INVALID  ((Lock*)1UL)
160 
161 /*----------------------------------------------------------------*/
162 /*--- Sanity checking                                          ---*/
163 /*----------------------------------------------------------------*/
164 
165 Bool HG_(is_sane_Thread)   ( Thread* thr );
166 Bool HG_(is_sane_LockP)    ( Lock* lock );
167 Bool HG_(is_sane_LockN)    ( Lock* lock );
168 Bool HG_(is_sane_LockNorP) ( Lock* lock );
169 
170 
171 #endif /* ! __HG_LOCK_N_THREAD_H */
172 
173 /*--------------------------------------------------------------------*/
174 /*--- end                                       hg_lock_n_thread.h ---*/
175 /*--------------------------------------------------------------------*/
176