1/* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */ 2/* 3 This file is part of drd, a thread error detector. 4 5 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>. 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the 10 License, or (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20 02111-1307, USA. 21 22 The GNU General Public License is contained in the file COPYING. 23*/ 24 25 26#ifndef __THREAD_H 27#define __THREAD_H 28 29 30/* Include directives. */ 31 32#include "drd_basics.h" 33#include "drd_segment.h" 34#include "pub_drd_bitmap.h" 35#include "pub_tool_libcassert.h" /* tl_assert() */ 36#include "pub_tool_stacktrace.h" /* typedef StackTrace */ 37#include "pub_tool_threadstate.h" /* VG_N_THREADS */ 38 39 40/* Defines. */ 41 42/** Maximum number of threads DRD keeps information about. */ 43#define DRD_N_THREADS VG_N_THREADS 44 45/** A number different from any valid DRD thread ID. */ 46#define DRD_INVALID_THREADID 0 47 48/** 49 * A number different from any valid POSIX thread ID. 50 * 51 * @note The PThreadId typedef and the INVALID_POSIX_THREADID depend on the 52 * operating system and threading library in use. PThreadId must contain at 53 * least as many bits as pthread_t, and INVALID_POSIX_THREADID 54 * must be a value that will never be returned by pthread_self(). 55 */ 56#define INVALID_POSIX_THREADID ((PThreadId)0) 57 58 59/* Type definitions. */ 60 61/** 62 * POSIX thread ID. The type PThreadId must be at least as wide as 63 * pthread_t. 64 */ 65typedef UWord PThreadId; 66 67/** Per-thread information managed by DRD. */ 68typedef struct 69{ 70 Segment* first; /**< Pointer to first segment. */ 71 Segment* last; /**< Pointer to last segment. */ 72 ThreadId vg_threadid; /**< Valgrind thread ID. */ 73 PThreadId pt_threadid; /**< POSIX thread ID. */ 74 Addr stack_min_min; /**< Lowest value stack pointer ever had. */ 75 Addr stack_min; /**< Current stack pointer. */ 76 Addr stack_startup; /**<Stack pointer after pthread_create() finished.*/ 77 Addr stack_max; /**< Top of stack. */ 78 SizeT stack_size; /**< Maximum size of stack. */ 79 char name[64]; /**< User-assigned thread name. */ 80 Bool on_alt_stack; 81 /** Whether this structure contains valid information. */ 82 Bool valid; 83 /** Indicates whether the Valgrind core knows about this thread. */ 84 Bool vg_thread_exists; 85 /** Indicates whether there is an associated POSIX thread ID. */ 86 Bool posix_thread_exists; 87 /** 88 * If true, indicates that there is a corresponding POSIX thread ID and 89 * a corresponding OS thread that is detached. 90 */ 91 Bool detached_posix_thread; 92 /** Wether recording of memory load accesses is currently enabled. */ 93 Bool is_recording_loads; 94 /** Wether recording of memory load accesses is currently enabled. */ 95 Bool is_recording_stores; 96 /** pthread_create() nesting level. */ 97 Int pthread_create_nesting_level; 98 /** Nesting level of synchronization functions called by the client. */ 99 Int synchr_nesting; 100 /** Delayed thread deletion sequence number. */ 101 unsigned deletion_seq; 102} ThreadInfo; 103 104 105/* 106 * Local variables of drd_thread.c that are declared here such that these 107 * can be accessed by inline functions. 108 */ 109 110/** 111 * DRD thread ID of the currently running thread. It is crucial for correct 112 * operation of DRD that this number is always in sync with 113 * VG_(get_running_tid)(). 114 */ 115extern DrdThreadId DRD_(g_drd_running_tid); 116/** Per-thread information managed by DRD. */ 117extern ThreadInfo DRD_(g_threadinfo)[DRD_N_THREADS]; 118/** Conflict set for the currently running thread. */ 119extern struct bitmap* DRD_(g_conflict_set); 120 121 122/* Function declarations. */ 123 124void DRD_(thread_trace_context_switches)(const Bool t); 125void DRD_(thread_trace_conflict_set)(const Bool t); 126void DRD_(thread_trace_conflict_set_bm)(const Bool t); 127Bool DRD_(thread_get_trace_fork_join)(void); 128void DRD_(thread_set_trace_fork_join)(const Bool t); 129void DRD_(thread_set_segment_merging)(const Bool m); 130int DRD_(thread_get_segment_merge_interval)(void); 131void DRD_(thread_set_segment_merge_interval)(const int i); 132void DRD_(thread_set_join_list_vol)(const int jlv); 133 134DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid); 135DrdThreadId DRD_(NewVgThreadIdToDrdThreadId)(const ThreadId tid); 136DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid); 137ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid); 138DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator, 139 const ThreadId vg_created); 140DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created); 141void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee); 142void DRD_(thread_delete)(const DrdThreadId tid, Bool detached); 143void DRD_(thread_finished)(const DrdThreadId tid); 144void DRD_(drd_thread_atfork_child)(const DrdThreadId tid); 145void DRD_(thread_pre_cancel)(const DrdThreadId tid); 146void DRD_(thread_set_stack_startup)(const DrdThreadId tid, 147 const Addr stack_startup); 148Addr DRD_(thread_get_stack_min)(const DrdThreadId tid); 149Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid); 150Addr DRD_(thread_get_stack_max)(const DrdThreadId tid); 151SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid); 152Bool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid); 153void DRD_(thread_set_on_alt_stack)(const DrdThreadId tid, 154 const Bool on_alt_stack); 155Int DRD_(thread_get_threads_on_alt_stack)(void); 156void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid); 157Bool DRD_(thread_get_joinable)(const DrdThreadId tid); 158void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable); 159void DRD_(thread_entering_pthread_create)(const DrdThreadId tid); 160void DRD_(thread_left_pthread_create)(const DrdThreadId tid); 161const char* DRD_(thread_get_name)(const DrdThreadId tid); 162void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name); 163void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid); 164void DRD_(thread_set_running_tid)(const ThreadId vg_tid, 165 const DrdThreadId drd_tid); 166int DRD_(thread_enter_synchr)(const DrdThreadId tid); 167int DRD_(thread_leave_synchr)(const DrdThreadId tid); 168int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid); 169void DRD_(thread_new_segment)(const DrdThreadId tid); 170VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid); 171void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid); 172void DRD_(thread_combine_vc_join)(const DrdThreadId joiner, 173 const DrdThreadId joinee); 174void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, 175 const Segment* sg); 176void DRD_(thread_update_conflict_set)(const DrdThreadId tid, 177 const VectorClock* const old_vc); 178 179void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2); 180void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled); 181void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled); 182void DRD_(thread_print_all)(void); 183void DRD_(thread_report_races)(const DrdThreadId tid); 184void DRD_(thread_report_races_segment)(const DrdThreadId tid, 185 const Segment* const p); 186void DRD_(thread_report_all_races)(void); 187void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid, 188 const Addr addr, 189 const SizeT size, 190 const BmAccessTypeT access_type); 191ULong DRD_(thread_get_context_switch_count)(void); 192ULong DRD_(thread_get_report_races_count)(void); 193ULong DRD_(thread_get_discard_ordered_segments_count)(void); 194ULong DRD_(thread_get_compute_conflict_set_count)(void); 195ULong DRD_(thread_get_update_conflict_set_count)(void); 196ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void); 197ULong DRD_(thread_get_update_conflict_set_sync_count)(void); 198ULong DRD_(thread_get_update_conflict_set_join_count)(void); 199ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void); 200ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void); 201 202 203/* Inline function definitions. */ 204 205/** 206 * Whether or not the specified DRD thread ID is valid. 207 * 208 * A DRD thread ID is valid if and only if the following conditions are met: 209 * - The ID is a valid index of the DRD_(g_threadinfo)[] array. 210 * - The ID is not equal to DRD_INVALID_THREADID. 211 * - The ID refers either to a thread known by the Valgrind core, a joinable 212 * thread that has not yet been joined or a detached thread. 213 */ 214static __inline__ 215Bool DRD_(IsValidDrdThreadId)(const DrdThreadId tid) 216{ 217 return (0 <= (int)tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID 218 && (DRD_(g_threadinfo)[tid].valid)); 219} 220 221/** Returns the DRD thread ID of the currently running thread. */ 222static __inline__ 223DrdThreadId DRD_(thread_get_running_tid)(void) 224{ 225#ifdef ENABLE_DRD_CONSISTENCY_CHECKS 226 tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); 227#endif 228 return DRD_(g_drd_running_tid); 229} 230 231/** Returns a pointer to the conflict set for the currently running thread. */ 232static __inline__ 233struct bitmap* DRD_(thread_get_conflict_set)(void) 234{ 235 return DRD_(g_conflict_set); 236} 237 238/** 239 * Reports whether or not the currently running client thread is executing code 240 * inside the pthread_create() function. 241 */ 242static __inline__ 243Bool DRD_(running_thread_inside_pthread_create)(void) 244{ 245 return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)] 246 .pthread_create_nesting_level > 0); 247} 248 249/** 250 * Reports whether or not recording of memory loads is enabled for the 251 * currently running client thread. 252 */ 253static __inline__ 254Bool DRD_(running_thread_is_recording_loads)(void) 255{ 256#ifdef ENABLE_DRD_CONSISTENCY_CHECKS 257 tl_assert(0 <= (int)DRD_(g_drd_running_tid) 258 && DRD_(g_drd_running_tid) < DRD_N_THREADS 259 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); 260#endif 261 return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].synchr_nesting == 0 262 && DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].is_recording_loads); 263} 264 265/** 266 * Reports whether or not recording memory stores is enabled for the 267 * currently running client thread. 268 */ 269static __inline__ 270Bool DRD_(running_thread_is_recording_stores)(void) 271{ 272#ifdef ENABLE_DRD_CONSISTENCY_CHECKS 273 tl_assert(0 <= (int)DRD_(g_drd_running_tid) 274 && DRD_(g_drd_running_tid) < DRD_N_THREADS 275 && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID); 276#endif 277 return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].synchr_nesting == 0 278 && DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].is_recording_stores); 279} 280 281/** 282 * Update the information about the lowest stack address that has ever been 283 * accessed by a thread. 284 */ 285static __inline__ 286void DRD_(thread_set_stack_min)(const DrdThreadId tid, const Addr stack_min) 287{ 288#ifdef ENABLE_DRD_CONSISTENCY_CHECKS 289 tl_assert(0 <= (int)tid 290 && tid < DRD_N_THREADS 291 && tid != DRD_INVALID_THREADID); 292#endif 293 DRD_(g_threadinfo)[tid].stack_min = stack_min; 294#ifdef ENABLE_DRD_CONSISTENCY_CHECKS 295 /* This function can be called after the thread has been created but */ 296 /* before drd_post_thread_create() has filled in stack_max. */ 297 tl_assert(DRD_(g_threadinfo)[tid].stack_min 298 < DRD_(g_threadinfo)[tid].stack_max 299 || DRD_(g_threadinfo)[tid].stack_max == 0); 300#endif 301 if (UNLIKELY(stack_min < DRD_(g_threadinfo)[tid].stack_min_min)) 302 { 303 DRD_(g_threadinfo)[tid].stack_min_min = stack_min; 304 } 305} 306 307/** 308 * Return true if and only if the specified address is on the stack of the 309 * currently scheduled thread. 310 */ 311static __inline__ 312Bool DRD_(thread_address_on_stack)(const Addr a) 313{ 314 return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].stack_min <= a 315 && a < DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].stack_max); 316} 317 318/** 319 * Return true if and only if the specified address is on the stack of any 320 * thread. 321 */ 322static __inline__ 323Bool DRD_(thread_address_on_any_stack)(const Addr a) 324{ 325 int i; 326 327 for (i = 1; i < DRD_N_THREADS; i++) 328 { 329 if (DRD_(g_threadinfo)[i].vg_thread_exists 330 && DRD_(g_threadinfo)[i].stack_min <= a 331 && a < DRD_(g_threadinfo)[i].stack_max) 332 { 333 return True; 334 } 335 } 336 return False; 337} 338 339/** Return a pointer to the latest segment for the specified thread. */ 340static __inline__ 341Segment* DRD_(thread_get_segment)(const DrdThreadId tid) 342{ 343#ifdef ENABLE_DRD_CONSISTENCY_CHECKS 344 tl_assert(0 <= (int)tid && tid < DRD_N_THREADS 345 && tid != DRD_INVALID_THREADID); 346 tl_assert(DRD_(g_threadinfo)[tid].last); 347#endif 348 return DRD_(g_threadinfo)[tid].last; 349} 350 351/** Return a pointer to the latest segment for the running thread. */ 352static __inline__ 353Segment* DRD_(running_thread_get_segment)(void) 354{ 355 return DRD_(thread_get_segment)(DRD_(g_drd_running_tid)); 356} 357 358#endif /* __THREAD_H */ 359