Home | History | Annotate | Download | only in nonsfi
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <errno.h>
      6 #include <pthread.h>
      7 #include <stdlib.h>
      8 
      9 #include "base/macros.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "components/nacl/loader/nonsfi/irt_interfaces.h"
     12 
     13 namespace nacl {
     14 namespace nonsfi {
     15 namespace {
     16 
     17 // We heuristically chose 1M for the stack size per thread.
     18 const int kStackSize = 1024 * 1024;
     19 
     20 // For RAII of pthread_attr_t.
     21 class ScopedPthreadAttrPtr {
     22  public:
     23   ScopedPthreadAttrPtr(pthread_attr_t* attr) : attr_(attr) {
     24   }
     25   ~ScopedPthreadAttrPtr() {
     26     pthread_attr_destroy(attr_);
     27   }
     28 
     29  private:
     30   pthread_attr_t* attr_;
     31 };
     32 
     33 struct ThreadContext {
     34   void (*start_func)();
     35   void* thread_ptr;
     36 };
     37 
     38 // A thread local pointer to support nacl_irt_tls.
     39 // This should be initialized at the beginning of ThreadMain, which is a thin
     40 // wrapper of a user function called on a newly created thread, and may be
     41 // reset via IrtTlsInit(). The pointer can be obtained via IrtTlsGet().
     42 __thread void* g_thread_ptr;
     43 
     44 void* ThreadMain(void *arg) {
     45   ::scoped_ptr<ThreadContext> context(static_cast<ThreadContext*>(arg));
     46   g_thread_ptr = context->thread_ptr;
     47 
     48   // Release the memory of context before running start_func.
     49   void (*start_func)() = context->start_func;
     50   context.reset();
     51 
     52   start_func();
     53   abort();
     54 }
     55 
     56 int IrtThreadCreate(void (*start_func)(), void* stack, void* thread_ptr) {
     57   pthread_attr_t attr;
     58   int error = pthread_attr_init(&attr);
     59   if (error != 0)
     60     return error;
     61   ScopedPthreadAttrPtr scoped_attr_ptr(&attr);
     62 
     63   // Note: Currently we ignore the argument stack.
     64   error = pthread_attr_setstacksize(&attr, kStackSize);
     65   if (error != 0)
     66     return error;
     67 
     68   error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     69   if (error != 0)
     70     return error;
     71 
     72   ::scoped_ptr<ThreadContext> context(new ThreadContext);
     73   context->start_func = start_func;
     74   context->thread_ptr = thread_ptr;
     75 
     76   pthread_t tid;
     77   error = pthread_create(&tid, &attr, ThreadMain, context.get());
     78   if (error != 0)
     79     return error;
     80 
     81   // The ownership of the context is taken by the created thread. So, here we
     82   // just manually release it.
     83   ignore_result(context.release());
     84   return 0;
     85 }
     86 
     87 void IrtThreadExit(int32_t* stack_flag) {
     88   // As we actually don't use stack given to thread_create, it means that the
     89   // memory can be released whenever.
     90   if (stack_flag)
     91     *stack_flag = 0;
     92   pthread_exit(NULL);
     93 }
     94 
     95 int IrtThreadNice(const int nice) {
     96   // TODO(https://code.google.com/p/nativeclient/issues/detail?id=3734):
     97   // Implement this method.
     98   // Note that this is just a hint, so here we just return success without
     99   // do anything.
    100   return 0;
    101 }
    102 
    103 int IrtTlsInit(void* thread_ptr) {
    104   g_thread_ptr = thread_ptr;
    105   return 0;
    106 }
    107 
    108 void* IrtTlsGet() {
    109   return g_thread_ptr;
    110 }
    111 
    112 }  // namespace
    113 
    114 const nacl_irt_thread kIrtThread = {
    115   IrtThreadCreate,
    116   IrtThreadExit,
    117   IrtThreadNice,
    118 };
    119 
    120 const nacl_irt_tls kIrtTls = {
    121   IrtTlsInit,
    122   IrtTlsGet,
    123 };
    124 
    125 }  // namespace nonsfi
    126 }  // namespace nacl
    127