Home | History | Annotate | Download | only in coregrind
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- The thread state.                            m_threadstate.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2000-2013 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_vki.h"
     33 #include "pub_core_threadstate.h"
     34 #include "pub_core_mallocfree.h"    // VG_(malloc)
     35 #include "pub_core_libcassert.h"
     36 #include "pub_core_inner.h"
     37 #if defined(ENABLE_INNER_CLIENT_REQUEST)
     38 #include "helgrind/helgrind.h"
     39 #endif
     40 
     41 /*------------------------------------------------------------*/
     42 /*--- Data structures.                                     ---*/
     43 /*------------------------------------------------------------*/
     44 
     45 ThreadId VG_(running_tid) = VG_INVALID_THREADID;
     46 
     47 ThreadState *VG_(threads);
     48 UInt VG_N_THREADS;
     49 
     50 /*------------------------------------------------------------*/
     51 /*--- Operations.                                          ---*/
     52 /*------------------------------------------------------------*/
     53 
     54 void VG_(init_Threads)(void)
     55 {
     56    ThreadId tid;
     57    UChar *addr, *aligned_addr;
     58 
     59    addr = VG_(malloc)("init_Threads",
     60           VG_N_THREADS * sizeof VG_(threads)[0] + LibVEX_GUEST_STATE_ALIGN - 1);
     61 
     62    // Align
     63    aligned_addr = addr + (Addr)addr % LibVEX_GUEST_STATE_ALIGN;
     64    VG_(threads) = (ThreadState *)aligned_addr;
     65 
     66    for (tid = 1; tid < VG_N_THREADS; tid++) {
     67       INNER_REQUEST(
     68          ANNOTATE_BENIGN_RACE_SIZED(&VG_(threads)[tid].status,
     69                                     sizeof(VG_(threads)[tid].status), ""));
     70       INNER_REQUEST(
     71          ANNOTATE_BENIGN_RACE_SIZED(&VG_(threads)[tid].os_state.exitcode,
     72                                     sizeof(VG_(threads)[tid].os_state.exitcode),
     73                                     ""));
     74    }
     75 }
     76 
     77 const HChar* VG_(name_of_ThreadStatus) ( ThreadStatus status )
     78 {
     79    switch (status) {
     80    case VgTs_Empty:     return "VgTs_Empty";
     81    case VgTs_Init:      return "VgTs_Init";
     82    case VgTs_Runnable:  return "VgTs_Runnable";
     83    case VgTs_WaitSys:   return "VgTs_WaitSys";
     84    case VgTs_Yielding:  return "VgTs_Yielding";
     85    case VgTs_Zombie:    return "VgTs_Zombie";
     86    default:             return "VgTs_???";
     87   }
     88 }
     89 
     90 const HChar* VG_(name_of_VgSchedReturnCode) ( VgSchedReturnCode retcode )
     91 {
     92    switch (retcode) {
     93    case VgSrc_None:        return "VgSrc_None";
     94    case VgSrc_ExitThread:  return "VgSrc_ExitThread";
     95    case VgSrc_ExitProcess: return "VgSrc_ExitProcess";
     96    case VgSrc_FatalSig:    return "VgSrc_FatalSig";
     97    default:                return "VgSrc_???";
     98   }
     99 }
    100 
    101 ThreadState *VG_(get_ThreadState)(ThreadId tid)
    102 {
    103    vg_assert(tid >= 0 && tid < VG_N_THREADS);
    104    vg_assert(VG_(threads)[tid].tid == tid);
    105    return &VG_(threads)[tid];
    106 }
    107 
    108 Bool VG_(is_valid_tid) ( ThreadId tid )
    109 {
    110    /* tid is unsigned, hence no < 0 test. */
    111    if (tid == 0) return False;
    112    if (tid >= VG_N_THREADS) return False;
    113    if (VG_(threads)[tid].status == VgTs_Empty) return False;
    114    return True;
    115 }
    116 
    117 // This function is for tools to call.
    118 ThreadId VG_(get_running_tid)(void)
    119 {
    120    return VG_(running_tid);
    121 }
    122 
    123 Bool VG_(is_running_thread)(ThreadId tid)
    124 {
    125    ThreadState *tst = VG_(get_ThreadState)(tid);
    126 
    127    return
    128 //      tst->os_state.lwpid == VG_(gettid)() &&	// check we're this tid
    129       VG_(running_tid) == tid	           &&	// and that we've got the lock
    130       tst->status == VgTs_Runnable;		// and we're runnable
    131 }
    132 
    133 /* Return true if the thread is still alive but in the process of exiting. */
    134 inline Bool VG_(is_exiting)(ThreadId tid)
    135 {
    136    vg_assert(VG_(is_valid_tid)(tid));
    137    return VG_(threads)[tid].exitreason != VgSrc_None;
    138 }
    139 
    140 /* Return the number of non-dead Threads */
    141 Int VG_(count_living_threads)(void)
    142 {
    143    Int count = 0;
    144    ThreadId tid;
    145 
    146    for(tid = 1; tid < VG_N_THREADS; tid++)
    147       if (VG_(threads)[tid].status != VgTs_Empty &&
    148 	  VG_(threads)[tid].status != VgTs_Zombie)
    149 	 count++;
    150 
    151    return count;
    152 }
    153 
    154 /* Return the number of threads in VgTs_Runnable state */
    155 Int VG_(count_runnable_threads)(void)
    156 {
    157    Int count = 0;
    158    ThreadId tid;
    159 
    160    for(tid = 1; tid < VG_N_THREADS; tid++)
    161       if (VG_(threads)[tid].status == VgTs_Runnable)
    162 	 count++;
    163 
    164    return count;
    165 }
    166 
    167 /* Given an LWP id (ie, real kernel thread id), find the corresponding
    168    ThreadId */
    169 ThreadId VG_(lwpid_to_vgtid)(Int lwp)
    170 {
    171    ThreadId tid;
    172 
    173    for(tid = 1; tid < VG_N_THREADS; tid++)
    174       if (VG_(threads)[tid].status != VgTs_Empty
    175           && VG_(threads)[tid].os_state.lwpid == lwp)
    176 	 return tid;
    177 
    178    return VG_INVALID_THREADID;
    179 }
    180 
    181 /*--------------------------------------------------------------------*/
    182 /*--- end                                                          ---*/
    183 /*--------------------------------------------------------------------*/
    184