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-2015 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 
     58    VG_(threads) = VG_(arena_memalign) (VG_AR_CORE, "init_Threads",
     59                                        LibVEX_GUEST_STATE_ALIGN,
     60                                        VG_N_THREADS * sizeof VG_(threads)[0]);
     61 
     62    for (tid = 1; tid < VG_N_THREADS; tid++) {
     63       INNER_REQUEST(
     64          ANNOTATE_BENIGN_RACE_SIZED(&VG_(threads)[tid].status,
     65                                     sizeof(VG_(threads)[tid].status), ""));
     66       INNER_REQUEST(
     67          ANNOTATE_BENIGN_RACE_SIZED(&VG_(threads)[tid].os_state.exitcode,
     68                                     sizeof(VG_(threads)[tid].os_state.exitcode),
     69                                     ""));
     70    }
     71 }
     72 
     73 const HChar* VG_(name_of_ThreadStatus) ( ThreadStatus status )
     74 {
     75    switch (status) {
     76    case VgTs_Empty:     return "VgTs_Empty";
     77    case VgTs_Init:      return "VgTs_Init";
     78    case VgTs_Runnable:  return "VgTs_Runnable";
     79    case VgTs_WaitSys:   return "VgTs_WaitSys";
     80    case VgTs_Yielding:  return "VgTs_Yielding";
     81    case VgTs_Zombie:    return "VgTs_Zombie";
     82    default:             return "VgTs_???";
     83   }
     84 }
     85 
     86 const HChar* VG_(name_of_VgSchedReturnCode) ( VgSchedReturnCode retcode )
     87 {
     88    switch (retcode) {
     89    case VgSrc_None:        return "VgSrc_None";
     90    case VgSrc_ExitThread:  return "VgSrc_ExitThread";
     91    case VgSrc_ExitProcess: return "VgSrc_ExitProcess";
     92    case VgSrc_FatalSig:    return "VgSrc_FatalSig";
     93    default:                return "VgSrc_???";
     94   }
     95 }
     96 
     97 ThreadState *VG_(get_ThreadState)(ThreadId tid)
     98 {
     99    vg_assert(tid >= 0 && tid < VG_N_THREADS);
    100    vg_assert(VG_(threads)[tid].tid == tid);
    101    return &VG_(threads)[tid];
    102 }
    103 
    104 Bool VG_(is_valid_tid) ( ThreadId tid )
    105 {
    106    /* tid is unsigned, hence no < 0 test. */
    107    if (tid == 0) return False;
    108    if (tid >= VG_N_THREADS) return False;
    109    if (VG_(threads)[tid].status == VgTs_Empty) return False;
    110    return True;
    111 }
    112 
    113 // This function is for tools to call.
    114 ThreadId VG_(get_running_tid)(void)
    115 {
    116    return VG_(running_tid);
    117 }
    118 
    119 Bool VG_(is_running_thread)(ThreadId tid)
    120 {
    121    ThreadState *tst = VG_(get_ThreadState)(tid);
    122 
    123    return
    124 //      tst->os_state.lwpid == VG_(gettid)() &&	// check we're this tid
    125       VG_(running_tid) == tid	           &&	// and that we've got the lock
    126       tst->status == VgTs_Runnable;		// and we're runnable
    127 }
    128 
    129 /* Return true if the thread is still alive but in the process of exiting. */
    130 inline Bool VG_(is_exiting)(ThreadId tid)
    131 {
    132    vg_assert(VG_(is_valid_tid)(tid));
    133    return VG_(threads)[tid].exitreason != VgSrc_None;
    134 }
    135 
    136 /* Return the number of non-dead Threads */
    137 Int VG_(count_living_threads)(void)
    138 {
    139    Int count = 0;
    140    ThreadId tid;
    141 
    142    for(tid = 1; tid < VG_N_THREADS; tid++)
    143       if (VG_(threads)[tid].status != VgTs_Empty &&
    144 	  VG_(threads)[tid].status != VgTs_Zombie)
    145 	 count++;
    146 
    147    return count;
    148 }
    149 
    150 /* Return the number of threads in VgTs_Runnable state */
    151 Int VG_(count_runnable_threads)(void)
    152 {
    153    Int count = 0;
    154    ThreadId tid;
    155 
    156    for(tid = 1; tid < VG_N_THREADS; tid++)
    157       if (VG_(threads)[tid].status == VgTs_Runnable)
    158 	 count++;
    159 
    160    return count;
    161 }
    162 
    163 /* Given an LWP id (ie, real kernel thread id), find the corresponding
    164    ThreadId */
    165 ThreadId VG_(lwpid_to_vgtid)(Int lwp)
    166 {
    167    ThreadId tid;
    168 
    169    for(tid = 1; tid < VG_N_THREADS; tid++)
    170       if (VG_(threads)[tid].status != VgTs_Empty
    171           && VG_(threads)[tid].os_state.lwpid == lwp)
    172 	 return tid;
    173 
    174    return VG_INVALID_THREADID;
    175 }
    176 
    177 /*--------------------------------------------------------------------*/
    178 /*--- end                                                          ---*/
    179 /*--------------------------------------------------------------------*/
    180