LCOV - code coverage report
Current view: directory - src/trusted/debug_stub/posix - thread_impl.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 73 0 0.0 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright 2010 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can
       4                 :  * be found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <stdexcept>
       8                 : #include <string.h>
       9                 : 
      10                 : #include "native_client/src/shared/platform/nacl_log.h"
      11                 : #include "native_client/src/trusted/gdb_rsp/abi.h"
      12                 : #include "native_client/src/trusted/port/mutex.h"
      13                 : #include "native_client/src/trusted/port/platform.h"
      14                 : #include "native_client/src/trusted/port/thread.h"
      15                 : #include "native_client/src/trusted/service_runtime/nacl_signal.h"
      16                 : 
      17                 : /*
      18                 :  * Define the OS specific portions of gdb_utils IThread interface.
      19                 :  */
      20                 : 
      21                 : namespace {
      22                 : 
      23                 : const int kX86TrapFlag = 1 << 8;
      24                 : 
      25                 : }  // namespace
      26                 : 
      27                 : namespace port {
      28                 : 
      29                 : static IThread::CatchFunc_t s_CatchFunc = NULL;
      30                 : static void* s_CatchCookie = NULL;
      31                 : 
      32               0 : static IMutex* ThreadGetLock() {
      33               0 :   static IMutex* mutex_ = IMutex::Allocate();
      34               0 :   return mutex_;
      35                 : }
      36                 : 
      37               0 : static IThread::ThreadMap_t *ThreadGetMap() {
      38               0 :   static IThread::ThreadMap_t* map_ = new IThread::ThreadMap_t;
      39               0 :   return map_;
      40                 : }
      41                 : 
      42                 : class Thread : public IThread {
      43                 :  public:
      44               0 :   explicit Thread(uint32_t id) : ref_(1), id_(id), state_(DEAD) {}
      45               0 :   ~Thread() {}
      46                 : 
      47               0 :   uint32_t GetId() {
      48               0 :     return id_;
      49                 :   }
      50                 : 
      51               0 :   State GetState() {
      52               0 :     return state_;
      53                 :   }
      54                 : 
      55               0 :   virtual bool Suspend() {
      56                 :     // TODO(mseaborn): Implement this.  Unlike with Windows'
      57                 :     // SuspendThread(), a thread cannot be suspended from another
      58                 :     // thread in Unix.  We would have to send the thread a signal to
      59                 :     // ask it to suspend.
      60               0 :     return false;
      61                 :   }
      62                 : 
      63               0 :   virtual bool Resume() {
      64                 :     // TODO(mseaborn): Implement this.
      65               0 :     return false;
      66                 :   }
      67                 : 
      68                 :   // TODO(mseaborn): Similar logic is duplicated in the Windows version.
      69               0 :   virtual bool SetStep(bool on) {
      70                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
      71               0 :     if (on) {
      72               0 :       context_.flags |= kX86TrapFlag;
      73                 :     } else {
      74               0 :       context_.flags &= ~kX86TrapFlag;
      75                 :     }
      76               0 :     return true;
      77                 : #else
      78                 :     // TODO(mseaborn): Implement for ARM.
      79                 :     UNREFERENCED_PARAMETER(on);
      80                 :     return false;
      81                 : #endif
      82                 :   }
      83                 : 
      84               0 :   virtual bool GetRegister(uint32_t index, void *dst, uint32_t len) {
      85               0 :     const gdb_rsp::Abi *abi = gdb_rsp::Abi::Get();
      86               0 :     const gdb_rsp::Abi::RegDef *reg = abi->GetRegisterDef(index);
      87               0 :     memcpy(dst, (char *) &context_ + reg->offset_, len);
      88               0 :     return false;
      89                 :   }
      90                 : 
      91               0 :   virtual bool SetRegister(uint32_t index, void* src, uint32_t len) {
      92               0 :     const gdb_rsp::Abi *abi = gdb_rsp::Abi::Get();
      93               0 :     const gdb_rsp::Abi::RegDef *reg = abi->GetRegisterDef(index);
      94               0 :     memcpy((char *) &context_ + reg->offset_, src, len);
      95               0 :     return false;
      96                 :   }
      97                 : 
      98                 :   // This is not used and could be removed.
      99               0 :   virtual void* GetContext() { return NULL; }
     100                 : 
     101               0 :   static enum NaClSignalResult SignalHandler(int signal, void *ucontext) {
     102                 :     struct NaClSignalContext context;
     103               0 :     NaClSignalContextFromHandler(&context, ucontext);
     104               0 :     if (NaClSignalContextIsUntrusted(&context)) {
     105               0 :       uint32_t thread_id = IPlatform::GetCurrentThread();
     106               0 :       Thread* thread = static_cast<Thread*>(Acquire(thread_id));
     107               0 :       State old_state = thread->state_;
     108               0 :       thread->state_ = SIGNALED;
     109               0 :       thread->context_ = context;
     110                 : 
     111               0 :       if (s_CatchFunc != NULL)
     112               0 :         s_CatchFunc(thread_id, signal, s_CatchCookie);
     113                 : 
     114               0 :       NaClSignalContextToHandler(ucontext, &thread->context_);
     115               0 :       thread->state_ = old_state;
     116               0 :       Release(thread);
     117               0 :       return NACL_SIGNAL_RETURN;
     118                 :     } else {
     119                 :       // Do not attempt to debug crashes in trusted code.
     120               0 :       return NACL_SIGNAL_SEARCH;
     121                 :     }
     122                 :   }
     123                 : 
     124                 :  private:
     125                 :   uint32_t ref_;
     126                 :   uint32_t id_;
     127                 :   State  state_;
     128                 :   struct NaClSignalContext context_;
     129                 : 
     130                 :   friend class IThread;
     131                 : };
     132                 : 
     133                 : // TODO(mseaborn): This is duplicated in the Windows version.
     134               0 : IThread* IThread::Acquire(uint32_t id, bool create) {
     135               0 :   MutexLock lock(ThreadGetLock());
     136                 :   Thread* thread;
     137               0 :   ThreadMap_t &map = *ThreadGetMap();
     138                 : 
     139                 :   // Check if we have that thread
     140               0 :   if (map.count(id)) {
     141               0 :     thread = static_cast<Thread*>(map[id]);
     142               0 :     thread->ref_++;
     143               0 :     return thread;
     144                 :   }
     145                 : 
     146                 :   // If not, can we create it?
     147               0 :   if (create) {
     148                 :     // If not add it to the map
     149               0 :     thread = new Thread(id);
     150               0 :     map[id] = thread;
     151               0 :     return thread;
     152                 :   }
     153                 : 
     154               0 :   return NULL;
     155                 : }
     156                 : 
     157                 : // TODO(mseaborn): This is duplicated in the Windows version.
     158               0 : void IThread::Release(IThread *ithread) {
     159               0 :   MutexLock lock(ThreadGetLock());
     160               0 :   Thread* thread = static_cast<Thread*>(ithread);
     161               0 :   thread->ref_--;
     162                 : 
     163               0 :   if (thread->ref_ == 0) {
     164               0 :     ThreadGetMap()->erase(thread->id_);
     165               0 :     delete static_cast<IThread*>(thread);
     166               0 :   }
     167               0 : }
     168                 : 
     169               0 : void IThread::SetExceptionCatch(IThread::CatchFunc_t func, void *cookie) {
     170               0 :   NaClSignalHandlerAdd(Thread::SignalHandler);
     171               0 :   s_CatchFunc = func;
     172               0 :   s_CatchCookie = cookie;
     173               0 : }
     174                 : 
     175                 : 
     176                 : }  // End of port namespace
     177                 : 

Generated by: LCOV version 1.7