ROOT logo
// $Id: GThread.cxx 2820 2012-07-14 01:20:02Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "GThread.h"
#include <Gled/Gled.h>
#include <Glasses/ZMirEmittingEntity.h>

#include "TThread.h"
#include "TSystem.h"
#include "TUnixSystem.h"

#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

#ifdef __APPLE__
#define _XOPEN_SOURCE
#endif
#include <ucontext.h>
#include <fenv.h> // requires _GNU_SOURCE to be defined for trap control

//______________________________________________________________________________
//
// POSIX thread wrapper class - Gled specific as it provides
// data members required for authorization and MIR processing.
//

ClassImp(GThread);

GThread*                 GThread::sMainThread   = 0;
int                      GThread::sThreadCount  = 0;
map<pthread_t, GThread*> GThread::sThreadMap;
list<GThread*>           GThread::sThreadList;
GMutex                   GThread::sContainerLock;
GMutex                   GThread::sDetachCtrlLock(GMutex::recursive);
int                      GThread::sMinStackSize = 0;

pthread_key_t  GThread::TSD_Self;
GThread       *GThread::sInvalidPtr = (GThread*) 0x1l;
int            GThread::sSigMap[SigMAX] =
{ -1,
  SIGHUP,  SIGINT,    SIGQUIT, SIGILL,   SIGTRAP, SIGABRT, SIGBUS,  SIGFPE,
  SIGKILL, SIGUSR1,   SIGSEGV, SIGUSR2,  SIGPIPE, SIGALRM, SIGTERM, -1,
  SIGCHLD, SIGCONT,   SIGSTOP, SIGTSTP,  SIGTTIN, SIGTTOU, SIGURG,  SIGXCPU,
  SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO,   -1,      SIGSYS
};

//==============================================================================

GThread::GThread(const Text_t* name) :
  mRunningState (RS_Running),
  mIndex        (-1),
  mThreadListIt (),
  mId           (0),
  mRootTThread  (0),

  mName     (name),
  mStartFoo (0), mStartArg (0),
  bDetached (false), bDetachOnExit (false),
  mNice     (0),
  mStackSize(0),

  mSigHandlerDefault(0), mSigHandlerVector(SigMAX),
  mTerminalContext(new ucontext_t), mTerminalSignal(0),
  mTerminalPolicy(TP_ThreadExit),

  mOwner(0), mMIR(0)
{
  // Private constructor for wrapping of existing threads.
  // Thread is put into 'Running' state, registered into the thread list
  // and assigned an internal thread-index.
  // The owner of the thread is set to 0.

  sContainerLock.Lock();
  mThreadListIt = sThreadList.insert(sThreadList.end(), this);
  mIndex        = ++sThreadCount;
  sContainerLock.Unlock();
}

GThread::GThread(const Text_t* name, GThread_foo foo, void* arg,
		 bool detached, bool detach_on_exit) :
  mRunningState (RS_Incubating),
  mIndex        (-1),
  mThreadListIt (),
  mId           (0),
  mRootTThread  (0),

  mName     (name),
  mStartFoo (foo), mStartArg (arg),
  bDetached (detached), bDetachOnExit (detach_on_exit),
  mNice     (0),
  mStackSize(sMinStackSize),

  mSigHandlerDefault(0), mSigHandlerVector(SigMAX),
  mTerminalContext(new ucontext_t), mTerminalSignal(0),
  mTerminalPolicy(Self()->GetTerminalPolicy()),

  mOwner(Owner()), mMIR(0)
{
  // Normal constructor.
  // Thread is put into 'Incubating' state, registered into the thread list
  // and assigned an internal thread-index.
  // The owner of the thread is set be the same as the owner of the calling thread.
  // Termination policy is also copied.

  static const Exc_t _eh("GThread::GThread ");

  if (! sMainThread)
    throw _eh + "InitMain() not called.";

  sContainerLock.Lock();
  mThreadListIt = sThreadList.insert(sThreadList.end(), this);
  mIndex        = ++sThreadCount;
  sContainerLock.Unlock();
}

GThread::~GThread()
{
  // Destructor.
  // Thread is unregistered from the thread list.

  sContainerLock.Lock();
  sThreadList.erase(mThreadListIt);
  sContainerLock.Unlock();

  delete (ucontext_t*) mTerminalContext;
}

//==============================================================================

void GThread::CleanupPush(GThread_cu_foo foo, void* arg)
{
  mCleanups.push_back(Cleanup(foo, arg));
}

void GThread::CleanupPop(bool execute_p)
{
  if (mCleanups.empty()) return;

  if (execute_p)
  {
    mCleanups.back().Execute();
  }
  mCleanups.pop_back();
}

//==============================================================================

void* GThread::thread_spawner(void* arg)
{
  static const Exc_t _eh("GThread::thread_spawner ");

  GThread* self = (GThread*) arg;

  pthread_setspecific(TSD_Self, self);

  if (self->mNice)
  {
    nice(self->mNice);
  }

  self->mId = pthread_self();

  sContainerLock.Lock();
  sThreadMap[self->mId] = self;
  self->mRunningState   = RS_Running;
  self->mRootTThread    = new TThread();
  self->mRootTThread->SetName(GForm("TThread gled idx=%d", self->mIndex));
  sContainerLock.Unlock();

  void* ret = 0;

  pthread_cleanup_push(thread_reaper, self);

  try
  {
    // getcontext causes uber crap on mac.
#ifndef __APPLE__
    if (getcontext((ucontext_t*) self->mTerminalContext))
    {
      perror("getcontext failed:");
      ret = (void*) 1;
    }
    else
    {
      if (self->mTerminalSignal)
      {
        ret = reinterpret_cast<void*>(self->mTerminalSignal);
        switch (self->mTerminalPolicy)
        {
          case TP_ThreadExit:
            break;
          case TP_GledExit:
            Gled::theOne->Exit(self->mTerminalSignal);
            break;
          case TP_SysExit:
            gSystem->Exit(self->mTerminalSignal);
            break;
        }
      }
      else
      {
        ret = (self->mStartFoo)(self->mStartArg);
      }
    }
#else
    ret = (self->mStartFoo)(self->mStartArg);
#endif
  }
  catch (Exc_t& e)
  {
    ISerr(_eh + "Terminating thread '" + self->mName + "' on Exc_t: " + e);
  }
  catch (std::exception& e)
  {
    ISerr(_eh + "Terminating thread '" + self->mName + "' on std::exception: " + e.what());
  }
  // This is faulty ... apparently unnamed exceptions can be used for thread cancellation.
  // catch (...)
  // {
  //   ISerr(_eh + "Unknown exception in thread '" + self->mName + "'. This will not end well.");
  //   throw;
  // }

  {
    GMutexHolder _lck(sDetachCtrlLock);
    if (self->bDetachOnExit && ! self->bDetached)
    {
      self->Detach();
    }
  }

  pthread_cleanup_pop(1);

  return ret;
}

void GThread::thread_reaper(void* arg)
{
  GThread* self = (GThread*) arg;

  sContainerLock.Lock();
  self->mRunningState = RS_Terminating;
  sContainerLock.Unlock();

  while ( ! self->mCleanups.empty())
  {
    self->mCleanups.back().Execute();
    self->mCleanups.pop_back();
  }

  sContainerLock.Lock();
  self->ClearRootTThreadRepresentation();
  sThreadMap.erase(self->mId);
  self->mRunningState = RS_Finished;
  sContainerLock.Unlock();

  if (self->bDetached)
    delete self;
}

int GThread::Spawn()
{
  static const Exc_t _eh("GThread::Spawn ");

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  if (bDetached)
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  size_t stacksize;
  pthread_attr_getstacksize(&attr, &stacksize);
  if (mStackSize && (Int_t) stacksize < mStackSize)
  {
    ISmess(_eh + "increasing stack size for thread '" + mName +"' to " +
	   GForm("%dkB (was %dkB).", mStackSize/1024, (Int_t)stacksize/1024));
    pthread_attr_setstacksize(&attr, mStackSize);
  }

  sContainerLock.Lock();
  mRunningState = RS_Spawning;
  sContainerLock.Unlock();

  int ret = pthread_create(&mId, &attr, thread_spawner, this);
  if (ret)
  {
    sContainerLock.Lock();
    mRunningState = RS_ErrorSpawning;
    sContainerLock.Unlock();
    perror("GThread::Spawn");
  }

  return ret;
}

int GThread::Join(void** tret)
{
  int ret = pthread_join(mId, tret);
  if (ret) perror("GThread::Join");
  return ret;
}

int GThread::Kill(Signal signal)
{
  int ret = pthread_kill(mId, sSigMap[signal]);
  if(ret) perror("GThread::Kill");
  return ret;
}

int GThread::Cancel()
{
  int ret = pthread_cancel(mId);
  if(ret) perror("GThread::Cancel");
  return ret;
}

int GThread::Detach()
{
  GMutexHolder _lck(sDetachCtrlLock);

  int ret = pthread_detach(mId);
  if(ret) perror("GThread::Detach");
  else    bDetached = true;
  return ret;
}

bool GThread::IsDetached() const
{
  GMutexHolder _lck(sDetachCtrlLock);

  return bDetached;
}

bool GThread::ClearDetachOnExit()
{
  GMutexHolder _lck(sDetachCtrlLock);

  if ( ! bDetached)
  {
    bDetachOnExit = false;
    return true;
  }
  else
  {
    return false;
  }
}

void GThread::ClearRootTThreadRepresentation()
{
  // Wipe root's TThread representation of the calling thread.
  // This is needed as root's TSD schema expects TThread representation
  // does not exist for whatever it calls the main thread.
  // So we wipe it from the Root application thread.

  delete mRootTThread;
  mRootTThread = 0;
}


/**************************************************************************/
// Static functions; to be called from within thread.
/**************************************************************************/

GThread::CState GThread::SetCancelState(CState s)
{
  int ex_val;
  if(s == CS_Enable)
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,  &ex_val);
  else
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ex_val);
  return ex_val == PTHREAD_CANCEL_ENABLE ? CS_Enable : CS_Disable;
}

//==============================================================================

GThread::CType GThread::SetCancelType(CType t)
{
  int ex_val;
  if(t == CT_Async)
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &ex_val);
  else
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,     &ex_val);
  return ex_val == PTHREAD_CANCEL_DEFERRED ? CT_Deferred : CT_Async;
}

//==============================================================================

int GThread::Yield()
{
  int ret = sched_yield();
  if (ret) perror("GThread::Yield");
  return ret;
}

void GThread::TestCancel()
{
  pthread_testcancel();
}

void GThread::Exit(void* ret)
{
  pthread_exit(ret);
}

//==============================================================================

GThread* GThread::Self()
{
  // Static - returns current thread.

  return (GThread*) pthread_getspecific(TSD_Self);
}

ZMirEmittingEntity* GThread::Owner()
{
  // Static - returns owner of current thread.

  return Self()->mOwner;
}

ZMIR* GThread::MIR()
{
  // Static - returns MIR processed in current thread.

  return Self()->mMIR;
}

//==============================================================================

void GThread::BlockAllSignals()
{
  // Block all signals but the unblockable ones - KILL, STOP.

  sigset_t set;
  sigfillset(&set);
  pthread_sigmask(SIG_BLOCK, &set, 0);
}

void GThread::UnblockCpuExceptionSignals(bool unblock_fpe)
{
  // Unblock CPU exception signals SIGILL, SIGSEGV, SIGBUS
  // and, if unblock_fpe is true, also SIGFPE.

  UnblockSignal(SigILL);
  UnblockSignal(SigSEGV);
  UnblockSignal(SigBUS);
  if (unblock_fpe)
    UnblockSignal(SigFPE);
}

void GThread::BlockSignal(Signal sig)
{
  sigset_t set;
  sigemptyset(&set);
  sigaddset(&set, sSigMap[sig]);
  pthread_sigmask(SIG_UNBLOCK, &set, 0);
}

void GThread::UnblockSignal(Signal sig)
{
  sigset_t set;
  sigemptyset(&set);
  sigaddset(&set, sSigMap[sig]);
  pthread_sigmask(SIG_UNBLOCK, &set, 0);
}

GThread_sh_foo GThread::SetDefaultSignalHandler(GThread_sh_foo foo)
{
  GThread *self = Self();
  GThread_sh_foo old = self->mSigHandlerDefault;
  self->mSigHandlerDefault = foo;
  return old;
}

GThread_sh_foo GThread::SetSignalHandler(Signal sig, GThread_sh_foo foo, bool unblock)
{
  GThread *self = Self();
  GThread_sh_foo old = self->mSigHandlerVector[sig];
  self->mSigHandlerVector[sig] = foo;

  if (unblock) UnblockSignal(sig);

  return old;
}

void GThread::TheSignalHandler(GSignal* sig)
{
  static const Exc_t _eh("GThread::TheSignalHandler ");

  GThread *self = Self();

  ISdebug(1, _eh + GForm("sys_signal %d, gled_signal %d, sig_name %s in thread '%s'.",
			 sig->fSysSignal, sig->fSignal, SignalName(sig->fSignal), self->mName.Data()));

  if (sig->fSignal == SigUNDEF) return;

  if (self->mSigHandlerVector[sig->fSignal])
  {
    (self->mSigHandlerVector[sig->fSignal])(sig);
  }
  else if (self->mSigHandlerDefault != 0)
  {
    (self->mSigHandlerDefault)(sig);
  }
  else if (sig->fSignal == SigILL  ||  sig->fSignal == SigSEGV ||
	   sig->fSignal == SigBUS  ||  sig->fSignal == SigFPE)
  {
    ISerr(_eh + GForm("Fatal exception %s in thread '%s'.",
		      SignalName(sig->fSignal), self->mName.Data()));
    gSystem->StackTrace();
    self->mTerminalSignal = sig->fSignal;
    if (setcontext((ucontext_t*) self->mTerminalContext))
    {
      perror(_eh + "setcontext failed (will exit):");
      gSystem->Exit(self->mTerminalSignal);
    }
  }
}

void GThread::ToRootsSignalHandler(GSignal* sig)
{
  // Root remaps signals in an even funnier way, see TUnixSystem.cxx.

  static const int root_sig_map[kMAXSIGNALS] =
  {
    SIGBUS,  SIGSEGV, SIGSYS, SIGPIPE, SIGILL,  SIGQUIT, SIGINT,  SIGWINCH,
    SIGALRM, SIGCHLD, SIGURG, SIGFPE,  SIGTERM, SIGUSR1, SIGUSR2
  };

  for (int i = 0; i < kMAXSIGNALS; ++i)
  {
    if (root_sig_map[i] == sig->fSysSignal)
    {
      ((TUnixSystem*)gSystem)->DispatchSignals((ESignals) i);
      break;
    }
  }
}


//==============================================================================

void GThread::ListThreads()
{
  if (sMainThread == 0)
  {
    printf("Threads not initialized.");
    return;
  }

  printf("+------------------------------------------------------------------------+\n");
  sContainerLock.Lock();
  Int_t count = 0;
  for (lpGThread_i i = sThreadList.begin(); i != sThreadList.end(); ++i)
  {
    const GThread& t = **i;
    printf("| %2d | %4d | %-24s | %-14s | %-14s |\n", ++count,
           t.mIndex, t.mName.Data(), RunningStateName(t.mRunningState),
           t.get_owner() ? t.get_owner()->GetName() : "<null>");
  }
  sContainerLock.Unlock();
  printf("+------------------------------------------------------------------------+\n");
}

void GThread::ListSignalState()
{
  sigset_t set;
  sigfillset(&set);
  pthread_sigmask(0, 0, &set);

  printf("Signal block state of thread '%s':\n", Self()->mName.Data());
  for (int i = SigMIN + 1; i < SigMAX; ++i)
  {
    printf("  %6s %d", SignalName((Signal)i), sigismember(&set, sSigMap[i]));
    if (i % 8 == 0)
      printf("\n");
  }
  printf("\n");
}

//==============================================================================

void GThread::CancelAllThreads(bool join_p)
{
  if (sMainThread == 0)
  {
    printf("Threads not initialized.");
    return;
  }

  lpGThread_t clist;

  printf("+------------------------------------------------------------------------+\n");
  printf("+- Cancel All Threads ---------------------------------------------------+\n");
  printf("+------------------------------------------------------------------------+\n");
  sContainerLock.Lock();
  Int_t count = 0;
  for (lpGThread_i i = sThreadList.begin(); i != sThreadList.end(); ++i)
  {
    ++count;
    if (*i == sMainThread || (*i)->mRunningState > RS_Running)
      continue;
    GThread& t = **i;
    printf("| %2d | %4d | %-24s | %-14s | %-14s |\n", count,
           t.mIndex, t.mName.Data(), RunningStateName(t.mRunningState),
           t.get_owner() ? t.get_owner()->GetName() : "<null>");
    clist.push_back(&t);
    t.Cancel();
  }
  sContainerLock.Unlock();
  printf("+------------------------------------------------------------------------+\n");
  if (join_p)
  {
    for (lpGThread_i i = clist.begin(); i != clist.end(); ++i)
    {
      GThread& t = **i;
      void *tret;
      int   ret;
      ret = t.Join(&tret);
      printf("%d %p\n", ret, tret);
    }
    printf("+------------------------------------------------------------------------+\n");
  }
}

//==============================================================================

namespace
{
  void signal_handler_wrapper(int sid, siginfo_t* sinfo, void* sctx)
  {
    GSignal sig(sid, sinfo, sctx);
    GThread::TheSignalHandler(&sig);
  }
}

GThread* GThread::InitMain()
{
  // This will create a GThread wrapper around the calling thread.
  // To be called from ::main thread, somewhere early during the
  // system initialization.
  //
  // Blocks all signals but CPU exception ones.
  // GThread signal handler is installed for USR1, USR2 and CPU exceptions.

  static const Exc_t _eh("GThread::InitMain ");

  if (sMainThread)
  {
    throw _eh + " already called.";
  }

  pthread_key_create(&TSD_Self, 0);

  sMainThread = new GThread("main");

  pthread_setspecific(TSD_Self, sMainThread);

  sMainThread->mId = pthread_self();

  sContainerLock.Lock();
  sThreadMap[sMainThread->mId] = sMainThread;
  sContainerLock.Unlock();

  GThread::BlockAllSignals();
  GThread::UnblockCpuExceptionSignals(true);

  struct sigaction sac;
  sac.sa_sigaction = signal_handler_wrapper;
  sigemptyset(&sac.sa_mask);
  sac.sa_flags = SA_SIGINFO;
  sigaction(sSigMap[SigUSR1], &sac, 0);
  sigaction(sSigMap[SigUSR2], &sac, 0);
  sigaction(sSigMap[SigILL],  &sac, 0);
  sigaction(sSigMap[SigSEGV], &sac, 0);
  sigaction(sSigMap[SigBUS],  &sac, 0);
  sigaction(sSigMap[SigFPE],  &sac, 0);

  return sMainThread;
}

void GThread::FiniMain()
{
  static const Exc_t _eh("GThread::FiniMain ");

  if (! sMainThread)
  {
    throw _eh + "InitMain() not called.";
  }
  if (Self() != sMainThread)
  {
    throw _eh + "not called from main thread.";
  }

  sContainerLock.Lock();

  sThreadMap.erase(sMainThread->mId);

  sMainThread->mId = 0;
  sMainThread->mRunningState = RS_Finished;
  pthread_setspecific(TSD_Self, 0);

  sContainerLock.Unlock();

  delete sMainThread;
  sMainThread = 0;
}

//==============================================================================

int GThread::GetMinStackSize()
{
  return sMinStackSize;
}

void GThread::SetMinStackSize(int ss)
{
  sMinStackSize = ss;
}

//==============================================================================

const char* GThread::RunningStateName(RState state)
{
  switch (state)
  {
    case RS_Incubating:    return "Incubating";
    case RS_Spawning:      return "Spawning";
    case RS_Running:       return "Running";
    case RS_Terminating:   return "Terminating";
    case RS_Finished:      return "Finished";
    case RS_ErrorSpawning: return "ErrorSpawning";
    default:               return "<unknown>";
  }
}

const char* GThread::SignalName(Signal sig)
{
  switch (sig)
  {
    case SigHUP:  return "HUP";
    case SigINT:  return "INT";
    case SigQUIT: return "QUIT";
    case SigILL:  return "ILL";
    case SigTRAP: return "TRAP";
    case SigABRT: return "ABRT";
    case SigBUS:  return "BUS";
    case SigFPE:  return "FPE";
    case SigKILL: return "KILL";
    case SigUSR1: return "USR1";
    case SigSEGV: return "SEGV";
    case SigUSR2: return "USR2";
    case SigPIPE: return "PIPE";
    case SigALRM: return "ALRM";
    case SigTERM: return "TERM";
    case SigCHLD: return "CHLD";
    case SigCONT: return "CONT";
    case SigSTOP: return "STOP";
    case SigTSTP: return "TSTP";
    case SigTTIN: return "TTIN";
    case SigTTOU: return "TTOU";
    case SigURG:  return "URG";
    case SigXCPU: return "XCPU";
    case SigXFSZ: return "XFSZ";
    case SigVTALRM: return "VTALRM";
    case SigPROF: return "PROF";
    case SigWINCH:return "WINCH";
    case SigIO:   return "IO";
    case SigSYS:  return "SYS";
    default:      return "<unknown>";
  }
}

GThread::Signal GThread::SysToGledSignal(Int_t sys_sig)
{
  if (sys_sig <= SigMIN || sys_sig >= SigMAX) return SigUNDEF;
  for (Int_t i = SigMIN + 1; i < SigMAX; ++i)
  {
    if (sSigMap[i] == sys_sig)
      return (Signal)i;
  }
  return SigUNDEF;
}


//==============================================================================
// GSignal
//==============================================================================

GSignal::GSignal(int sid, siginfo_t* sinfo, void* sctx) :
  fSignal(GThread::SysToGledSignal(sid)),
  fSysSignal(sid), fSigInfo(sinfo), fContext(sctx)
{}
 GThread.cxx:1
 GThread.cxx:2
 GThread.cxx:3
 GThread.cxx:4
 GThread.cxx:5
 GThread.cxx:6
 GThread.cxx:7
 GThread.cxx:8
 GThread.cxx:9
 GThread.cxx:10
 GThread.cxx:11
 GThread.cxx:12
 GThread.cxx:13
 GThread.cxx:14
 GThread.cxx:15
 GThread.cxx:16
 GThread.cxx:17
 GThread.cxx:18
 GThread.cxx:19
 GThread.cxx:20
 GThread.cxx:21
 GThread.cxx:22
 GThread.cxx:23
 GThread.cxx:24
 GThread.cxx:25
 GThread.cxx:26
 GThread.cxx:27
 GThread.cxx:28
 GThread.cxx:29
 GThread.cxx:30
 GThread.cxx:31
 GThread.cxx:32
 GThread.cxx:33
 GThread.cxx:34
 GThread.cxx:35
 GThread.cxx:36
 GThread.cxx:37
 GThread.cxx:38
 GThread.cxx:39
 GThread.cxx:40
 GThread.cxx:41
 GThread.cxx:42
 GThread.cxx:43
 GThread.cxx:44
 GThread.cxx:45
 GThread.cxx:46
 GThread.cxx:47
 GThread.cxx:48
 GThread.cxx:49
 GThread.cxx:50
 GThread.cxx:51
 GThread.cxx:52
 GThread.cxx:53
 GThread.cxx:54
 GThread.cxx:55
 GThread.cxx:56
 GThread.cxx:57
 GThread.cxx:58
 GThread.cxx:59
 GThread.cxx:60
 GThread.cxx:61
 GThread.cxx:62
 GThread.cxx:63
 GThread.cxx:64
 GThread.cxx:65
 GThread.cxx:66
 GThread.cxx:67
 GThread.cxx:68
 GThread.cxx:69
 GThread.cxx:70
 GThread.cxx:71
 GThread.cxx:72
 GThread.cxx:73
 GThread.cxx:74
 GThread.cxx:75
 GThread.cxx:76
 GThread.cxx:77
 GThread.cxx:78
 GThread.cxx:79
 GThread.cxx:80
 GThread.cxx:81
 GThread.cxx:82
 GThread.cxx:83
 GThread.cxx:84
 GThread.cxx:85
 GThread.cxx:86
 GThread.cxx:87
 GThread.cxx:88
 GThread.cxx:89
 GThread.cxx:90
 GThread.cxx:91
 GThread.cxx:92
 GThread.cxx:93
 GThread.cxx:94
 GThread.cxx:95
 GThread.cxx:96
 GThread.cxx:97
 GThread.cxx:98
 GThread.cxx:99
 GThread.cxx:100
 GThread.cxx:101
 GThread.cxx:102
 GThread.cxx:103
 GThread.cxx:104
 GThread.cxx:105
 GThread.cxx:106
 GThread.cxx:107
 GThread.cxx:108
 GThread.cxx:109
 GThread.cxx:110
 GThread.cxx:111
 GThread.cxx:112
 GThread.cxx:113
 GThread.cxx:114
 GThread.cxx:115
 GThread.cxx:116
 GThread.cxx:117
 GThread.cxx:118
 GThread.cxx:119
 GThread.cxx:120
 GThread.cxx:121
 GThread.cxx:122
 GThread.cxx:123
 GThread.cxx:124
 GThread.cxx:125
 GThread.cxx:126
 GThread.cxx:127
 GThread.cxx:128
 GThread.cxx:129
 GThread.cxx:130
 GThread.cxx:131
 GThread.cxx:132
 GThread.cxx:133
 GThread.cxx:134
 GThread.cxx:135
 GThread.cxx:136
 GThread.cxx:137
 GThread.cxx:138
 GThread.cxx:139
 GThread.cxx:140
 GThread.cxx:141
 GThread.cxx:142
 GThread.cxx:143
 GThread.cxx:144
 GThread.cxx:145
 GThread.cxx:146
 GThread.cxx:147
 GThread.cxx:148
 GThread.cxx:149
 GThread.cxx:150
 GThread.cxx:151
 GThread.cxx:152
 GThread.cxx:153
 GThread.cxx:154
 GThread.cxx:155
 GThread.cxx:156
 GThread.cxx:157
 GThread.cxx:158
 GThread.cxx:159
 GThread.cxx:160
 GThread.cxx:161
 GThread.cxx:162
 GThread.cxx:163
 GThread.cxx:164
 GThread.cxx:165
 GThread.cxx:166
 GThread.cxx:167
 GThread.cxx:168
 GThread.cxx:169
 GThread.cxx:170
 GThread.cxx:171
 GThread.cxx:172
 GThread.cxx:173
 GThread.cxx:174
 GThread.cxx:175
 GThread.cxx:176
 GThread.cxx:177
 GThread.cxx:178
 GThread.cxx:179
 GThread.cxx:180
 GThread.cxx:181
 GThread.cxx:182
 GThread.cxx:183
 GThread.cxx:184
 GThread.cxx:185
 GThread.cxx:186
 GThread.cxx:187
 GThread.cxx:188
 GThread.cxx:189
 GThread.cxx:190
 GThread.cxx:191
 GThread.cxx:192
 GThread.cxx:193
 GThread.cxx:194
 GThread.cxx:195
 GThread.cxx:196
 GThread.cxx:197
 GThread.cxx:198
 GThread.cxx:199
 GThread.cxx:200
 GThread.cxx:201
 GThread.cxx:202
 GThread.cxx:203
 GThread.cxx:204
 GThread.cxx:205
 GThread.cxx:206
 GThread.cxx:207
 GThread.cxx:208
 GThread.cxx:209
 GThread.cxx:210
 GThread.cxx:211
 GThread.cxx:212
 GThread.cxx:213
 GThread.cxx:214
 GThread.cxx:215
 GThread.cxx:216
 GThread.cxx:217
 GThread.cxx:218
 GThread.cxx:219
 GThread.cxx:220
 GThread.cxx:221
 GThread.cxx:222
 GThread.cxx:223
 GThread.cxx:224
 GThread.cxx:225
 GThread.cxx:226
 GThread.cxx:227
 GThread.cxx:228
 GThread.cxx:229
 GThread.cxx:230
 GThread.cxx:231
 GThread.cxx:232
 GThread.cxx:233
 GThread.cxx:234
 GThread.cxx:235
 GThread.cxx:236
 GThread.cxx:237
 GThread.cxx:238
 GThread.cxx:239
 GThread.cxx:240
 GThread.cxx:241
 GThread.cxx:242
 GThread.cxx:243
 GThread.cxx:244
 GThread.cxx:245
 GThread.cxx:246
 GThread.cxx:247
 GThread.cxx:248
 GThread.cxx:249
 GThread.cxx:250
 GThread.cxx:251
 GThread.cxx:252
 GThread.cxx:253
 GThread.cxx:254
 GThread.cxx:255
 GThread.cxx:256
 GThread.cxx:257
 GThread.cxx:258
 GThread.cxx:259
 GThread.cxx:260
 GThread.cxx:261
 GThread.cxx:262
 GThread.cxx:263
 GThread.cxx:264
 GThread.cxx:265
 GThread.cxx:266
 GThread.cxx:267
 GThread.cxx:268
 GThread.cxx:269
 GThread.cxx:270
 GThread.cxx:271
 GThread.cxx:272
 GThread.cxx:273
 GThread.cxx:274
 GThread.cxx:275
 GThread.cxx:276
 GThread.cxx:277
 GThread.cxx:278
 GThread.cxx:279
 GThread.cxx:280
 GThread.cxx:281
 GThread.cxx:282
 GThread.cxx:283
 GThread.cxx:284
 GThread.cxx:285
 GThread.cxx:286
 GThread.cxx:287
 GThread.cxx:288
 GThread.cxx:289
 GThread.cxx:290
 GThread.cxx:291
 GThread.cxx:292
 GThread.cxx:293
 GThread.cxx:294
 GThread.cxx:295
 GThread.cxx:296
 GThread.cxx:297
 GThread.cxx:298
 GThread.cxx:299
 GThread.cxx:300
 GThread.cxx:301
 GThread.cxx:302
 GThread.cxx:303
 GThread.cxx:304
 GThread.cxx:305
 GThread.cxx:306
 GThread.cxx:307
 GThread.cxx:308
 GThread.cxx:309
 GThread.cxx:310
 GThread.cxx:311
 GThread.cxx:312
 GThread.cxx:313
 GThread.cxx:314
 GThread.cxx:315
 GThread.cxx:316
 GThread.cxx:317
 GThread.cxx:318
 GThread.cxx:319
 GThread.cxx:320
 GThread.cxx:321
 GThread.cxx:322
 GThread.cxx:323
 GThread.cxx:324
 GThread.cxx:325
 GThread.cxx:326
 GThread.cxx:327
 GThread.cxx:328
 GThread.cxx:329
 GThread.cxx:330
 GThread.cxx:331
 GThread.cxx:332
 GThread.cxx:333
 GThread.cxx:334
 GThread.cxx:335
 GThread.cxx:336
 GThread.cxx:337
 GThread.cxx:338
 GThread.cxx:339
 GThread.cxx:340
 GThread.cxx:341
 GThread.cxx:342
 GThread.cxx:343
 GThread.cxx:344
 GThread.cxx:345
 GThread.cxx:346
 GThread.cxx:347
 GThread.cxx:348
 GThread.cxx:349
 GThread.cxx:350
 GThread.cxx:351
 GThread.cxx:352
 GThread.cxx:353
 GThread.cxx:354
 GThread.cxx:355
 GThread.cxx:356
 GThread.cxx:357
 GThread.cxx:358
 GThread.cxx:359
 GThread.cxx:360
 GThread.cxx:361
 GThread.cxx:362
 GThread.cxx:363
 GThread.cxx:364
 GThread.cxx:365
 GThread.cxx:366
 GThread.cxx:367
 GThread.cxx:368
 GThread.cxx:369
 GThread.cxx:370
 GThread.cxx:371
 GThread.cxx:372
 GThread.cxx:373
 GThread.cxx:374
 GThread.cxx:375
 GThread.cxx:376
 GThread.cxx:377
 GThread.cxx:378
 GThread.cxx:379
 GThread.cxx:380
 GThread.cxx:381
 GThread.cxx:382
 GThread.cxx:383
 GThread.cxx:384
 GThread.cxx:385
 GThread.cxx:386
 GThread.cxx:387
 GThread.cxx:388
 GThread.cxx:389
 GThread.cxx:390
 GThread.cxx:391
 GThread.cxx:392
 GThread.cxx:393
 GThread.cxx:394
 GThread.cxx:395
 GThread.cxx:396
 GThread.cxx:397
 GThread.cxx:398
 GThread.cxx:399
 GThread.cxx:400
 GThread.cxx:401
 GThread.cxx:402
 GThread.cxx:403
 GThread.cxx:404
 GThread.cxx:405
 GThread.cxx:406
 GThread.cxx:407
 GThread.cxx:408
 GThread.cxx:409
 GThread.cxx:410
 GThread.cxx:411
 GThread.cxx:412
 GThread.cxx:413
 GThread.cxx:414
 GThread.cxx:415
 GThread.cxx:416
 GThread.cxx:417
 GThread.cxx:418
 GThread.cxx:419
 GThread.cxx:420
 GThread.cxx:421
 GThread.cxx:422
 GThread.cxx:423
 GThread.cxx:424
 GThread.cxx:425
 GThread.cxx:426
 GThread.cxx:427
 GThread.cxx:428
 GThread.cxx:429
 GThread.cxx:430
 GThread.cxx:431
 GThread.cxx:432
 GThread.cxx:433
 GThread.cxx:434
 GThread.cxx:435
 GThread.cxx:436
 GThread.cxx:437
 GThread.cxx:438
 GThread.cxx:439
 GThread.cxx:440
 GThread.cxx:441
 GThread.cxx:442
 GThread.cxx:443
 GThread.cxx:444
 GThread.cxx:445
 GThread.cxx:446
 GThread.cxx:447
 GThread.cxx:448
 GThread.cxx:449
 GThread.cxx:450
 GThread.cxx:451
 GThread.cxx:452
 GThread.cxx:453
 GThread.cxx:454
 GThread.cxx:455
 GThread.cxx:456
 GThread.cxx:457
 GThread.cxx:458
 GThread.cxx:459
 GThread.cxx:460
 GThread.cxx:461
 GThread.cxx:462
 GThread.cxx:463
 GThread.cxx:464
 GThread.cxx:465
 GThread.cxx:466
 GThread.cxx:467
 GThread.cxx:468
 GThread.cxx:469
 GThread.cxx:470
 GThread.cxx:471
 GThread.cxx:472
 GThread.cxx:473
 GThread.cxx:474
 GThread.cxx:475
 GThread.cxx:476
 GThread.cxx:477
 GThread.cxx:478
 GThread.cxx:479
 GThread.cxx:480
 GThread.cxx:481
 GThread.cxx:482
 GThread.cxx:483
 GThread.cxx:484
 GThread.cxx:485
 GThread.cxx:486
 GThread.cxx:487
 GThread.cxx:488
 GThread.cxx:489
 GThread.cxx:490
 GThread.cxx:491
 GThread.cxx:492
 GThread.cxx:493
 GThread.cxx:494
 GThread.cxx:495
 GThread.cxx:496
 GThread.cxx:497
 GThread.cxx:498
 GThread.cxx:499
 GThread.cxx:500
 GThread.cxx:501
 GThread.cxx:502
 GThread.cxx:503
 GThread.cxx:504
 GThread.cxx:505
 GThread.cxx:506
 GThread.cxx:507
 GThread.cxx:508
 GThread.cxx:509
 GThread.cxx:510
 GThread.cxx:511
 GThread.cxx:512
 GThread.cxx:513
 GThread.cxx:514
 GThread.cxx:515
 GThread.cxx:516
 GThread.cxx:517
 GThread.cxx:518
 GThread.cxx:519
 GThread.cxx:520
 GThread.cxx:521
 GThread.cxx:522
 GThread.cxx:523
 GThread.cxx:524
 GThread.cxx:525
 GThread.cxx:526
 GThread.cxx:527
 GThread.cxx:528
 GThread.cxx:529
 GThread.cxx:530
 GThread.cxx:531
 GThread.cxx:532
 GThread.cxx:533
 GThread.cxx:534
 GThread.cxx:535
 GThread.cxx:536
 GThread.cxx:537
 GThread.cxx:538
 GThread.cxx:539
 GThread.cxx:540
 GThread.cxx:541
 GThread.cxx:542
 GThread.cxx:543
 GThread.cxx:544
 GThread.cxx:545
 GThread.cxx:546
 GThread.cxx:547
 GThread.cxx:548
 GThread.cxx:549
 GThread.cxx:550
 GThread.cxx:551
 GThread.cxx:552
 GThread.cxx:553
 GThread.cxx:554
 GThread.cxx:555
 GThread.cxx:556
 GThread.cxx:557
 GThread.cxx:558
 GThread.cxx:559
 GThread.cxx:560
 GThread.cxx:561
 GThread.cxx:562
 GThread.cxx:563
 GThread.cxx:564
 GThread.cxx:565
 GThread.cxx:566
 GThread.cxx:567
 GThread.cxx:568
 GThread.cxx:569
 GThread.cxx:570
 GThread.cxx:571
 GThread.cxx:572
 GThread.cxx:573
 GThread.cxx:574
 GThread.cxx:575
 GThread.cxx:576
 GThread.cxx:577
 GThread.cxx:578
 GThread.cxx:579
 GThread.cxx:580
 GThread.cxx:581
 GThread.cxx:582
 GThread.cxx:583
 GThread.cxx:584
 GThread.cxx:585
 GThread.cxx:586
 GThread.cxx:587
 GThread.cxx:588
 GThread.cxx:589
 GThread.cxx:590
 GThread.cxx:591
 GThread.cxx:592
 GThread.cxx:593
 GThread.cxx:594
 GThread.cxx:595
 GThread.cxx:596
 GThread.cxx:597
 GThread.cxx:598
 GThread.cxx:599
 GThread.cxx:600
 GThread.cxx:601
 GThread.cxx:602
 GThread.cxx:603
 GThread.cxx:604
 GThread.cxx:605
 GThread.cxx:606
 GThread.cxx:607
 GThread.cxx:608
 GThread.cxx:609
 GThread.cxx:610
 GThread.cxx:611
 GThread.cxx:612
 GThread.cxx:613
 GThread.cxx:614
 GThread.cxx:615
 GThread.cxx:616
 GThread.cxx:617
 GThread.cxx:618
 GThread.cxx:619
 GThread.cxx:620
 GThread.cxx:621
 GThread.cxx:622
 GThread.cxx:623
 GThread.cxx:624
 GThread.cxx:625
 GThread.cxx:626
 GThread.cxx:627
 GThread.cxx:628
 GThread.cxx:629
 GThread.cxx:630
 GThread.cxx:631
 GThread.cxx:632
 GThread.cxx:633
 GThread.cxx:634
 GThread.cxx:635
 GThread.cxx:636
 GThread.cxx:637
 GThread.cxx:638
 GThread.cxx:639
 GThread.cxx:640
 GThread.cxx:641
 GThread.cxx:642
 GThread.cxx:643
 GThread.cxx:644
 GThread.cxx:645
 GThread.cxx:646
 GThread.cxx:647
 GThread.cxx:648
 GThread.cxx:649
 GThread.cxx:650
 GThread.cxx:651
 GThread.cxx:652
 GThread.cxx:653
 GThread.cxx:654
 GThread.cxx:655
 GThread.cxx:656
 GThread.cxx:657
 GThread.cxx:658
 GThread.cxx:659
 GThread.cxx:660
 GThread.cxx:661
 GThread.cxx:662
 GThread.cxx:663
 GThread.cxx:664
 GThread.cxx:665
 GThread.cxx:666
 GThread.cxx:667
 GThread.cxx:668
 GThread.cxx:669
 GThread.cxx:670
 GThread.cxx:671
 GThread.cxx:672
 GThread.cxx:673
 GThread.cxx:674
 GThread.cxx:675
 GThread.cxx:676
 GThread.cxx:677
 GThread.cxx:678
 GThread.cxx:679
 GThread.cxx:680
 GThread.cxx:681
 GThread.cxx:682
 GThread.cxx:683
 GThread.cxx:684
 GThread.cxx:685
 GThread.cxx:686
 GThread.cxx:687
 GThread.cxx:688
 GThread.cxx:689
 GThread.cxx:690
 GThread.cxx:691
 GThread.cxx:692
 GThread.cxx:693
 GThread.cxx:694
 GThread.cxx:695
 GThread.cxx:696
 GThread.cxx:697
 GThread.cxx:698
 GThread.cxx:699
 GThread.cxx:700
 GThread.cxx:701
 GThread.cxx:702
 GThread.cxx:703
 GThread.cxx:704
 GThread.cxx:705
 GThread.cxx:706
 GThread.cxx:707
 GThread.cxx:708
 GThread.cxx:709
 GThread.cxx:710
 GThread.cxx:711
 GThread.cxx:712
 GThread.cxx:713
 GThread.cxx:714
 GThread.cxx:715
 GThread.cxx:716
 GThread.cxx:717
 GThread.cxx:718
 GThread.cxx:719
 GThread.cxx:720
 GThread.cxx:721
 GThread.cxx:722
 GThread.cxx:723
 GThread.cxx:724
 GThread.cxx:725
 GThread.cxx:726
 GThread.cxx:727
 GThread.cxx:728
 GThread.cxx:729
 GThread.cxx:730
 GThread.cxx:731
 GThread.cxx:732
 GThread.cxx:733
 GThread.cxx:734
 GThread.cxx:735
 GThread.cxx:736
 GThread.cxx:737
 GThread.cxx:738
 GThread.cxx:739
 GThread.cxx:740
 GThread.cxx:741
 GThread.cxx:742
 GThread.cxx:743
 GThread.cxx:744
 GThread.cxx:745
 GThread.cxx:746
 GThread.cxx:747
 GThread.cxx:748
 GThread.cxx:749
 GThread.cxx:750
 GThread.cxx:751
 GThread.cxx:752
 GThread.cxx:753
 GThread.cxx:754
 GThread.cxx:755
 GThread.cxx:756
 GThread.cxx:757
 GThread.cxx:758
 GThread.cxx:759
 GThread.cxx:760
 GThread.cxx:761
 GThread.cxx:762
 GThread.cxx:763
 GThread.cxx:764
 GThread.cxx:765
 GThread.cxx:766
 GThread.cxx:767
 GThread.cxx:768
 GThread.cxx:769
 GThread.cxx:770
 GThread.cxx:771
 GThread.cxx:772
 GThread.cxx:773
 GThread.cxx:774
 GThread.cxx:775
 GThread.cxx:776
 GThread.cxx:777
 GThread.cxx:778
 GThread.cxx:779
 GThread.cxx:780
 GThread.cxx:781
 GThread.cxx:782
 GThread.cxx:783
 GThread.cxx:784
 GThread.cxx:785
 GThread.cxx:786
 GThread.cxx:787
 GThread.cxx:788
 GThread.cxx:789
 GThread.cxx:790
 GThread.cxx:791
 GThread.cxx:792
 GThread.cxx:793
 GThread.cxx:794
 GThread.cxx:795
 GThread.cxx:796
 GThread.cxx:797
 GThread.cxx:798