LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_app_thread.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 130 109 83.8 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * NaCl Server Runtime user thread state.
       9                 :  */
      10                 : 
      11                 : #include <string.h>
      12                 : 
      13                 : #include "native_client/src/shared/platform/aligned_malloc.h"
      14                 : #include "native_client/src/shared/platform/nacl_check.h"
      15                 : #include "native_client/src/shared/platform/nacl_exit.h"
      16                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      17                 : 
      18                 : #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
      19                 : #include "native_client/src/trusted/service_runtime/nacl_desc_effector_ldr.h"
      20                 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
      21                 : #include "native_client/src/trusted/service_runtime/nacl_tls.h"
      22                 : #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
      23                 : #include "native_client/src/trusted/service_runtime/nacl_stack_safety.h"
      24                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
      25                 : #include "native_client/src/trusted/service_runtime/osx/mach_thread_map.h"
      26                 : 
      27                 : 
      28           20880 : void WINAPI NaClAppThreadLauncher(void *state) {
      29           20880 :   struct NaClAppThread *natp = (struct NaClAppThread *) state;
      30           20880 :   uint32_t thread_idx;
      31           20880 :   NaClLog(4, "NaClAppThreadLauncher: entered\n");
      32                 : 
      33           20880 :   NaClSignalStackRegister(natp->signal_stack);
      34                 : 
      35           20880 :   NaClLog(4, "      natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp);
      36           20880 :   NaClLog(4, " prog_ctr  = 0x%016"NACL_PRIxNACL_REG"\n", natp->user.prog_ctr);
      37           20880 :   NaClLog(4, "stack_ptr  = 0x%016"NACL_PRIxPTR"\n",
      38           20880 :           NaClGetThreadCtxSp(&natp->user));
      39                 : 
      40           20880 :   thread_idx = NaClGetThreadIdx(natp);
      41           62642 :   CHECK(0 < thread_idx);
      42           62640 :   CHECK(thread_idx < NACL_THREAD_MAX);
      43           20881 :   NaClTlsSetCurrentThread(natp);
      44           20881 :   nacl_user[thread_idx] = &natp->user;
      45                 : #if NACL_WINDOWS
      46                 :   nacl_thread_ids[thread_idx] = GetCurrentThreadId();
      47                 : #elif NACL_OSX
      48           20881 :   NaClSetCurrentMachThreadForThreadIndex(thread_idx);
      49                 : #endif
      50                 : 
      51                 :   /*
      52                 :    * We have to hold the threads_mu lock until after thread_num field
      53                 :    * in this thread has been initialized.  All other threads can only
      54                 :    * find and examine this natp through the threads table, so the fact
      55                 :    * that natp is not consistent (no thread_num) will not be visible.
      56                 :    */
      57           20881 :   NaClXMutexLock(&natp->nap->threads_mu);
      58           20881 :   natp->thread_num = NaClAddThreadMu(natp->nap, natp);
      59           20881 :   NaClXMutexUnlock(&natp->nap->threads_mu);
      60                 : 
      61           20881 :   NaClVmHoleThreadStackIsSafe(natp->nap);
      62                 : 
      63           20881 :   NaClStackSafetyNowOnUntrustedStack();
      64                 : 
      65                 :   /*
      66                 :    * Notify the debug stub, that a new thread is availible.
      67                 :    */
      68           20881 :   if (NULL != natp->nap->debug_stub_callbacks) {
      69              20 :     natp->nap->debug_stub_callbacks->thread_create_hook(natp);
      70              20 :   }
      71                 : 
      72                 :   /*
      73                 :    * After this NaClAppThreadSetSuspendState() call, we should not
      74                 :    * claim any mutexes, otherwise we risk deadlock.
      75                 :    */
      76               0 :   NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_TRUSTED,
      77                 :                                NACL_APP_THREAD_UNTRUSTED);
      78                 : 
      79               0 :   NaClStartThreadInApp(natp, natp->user.prog_ctr);
      80               0 : }
      81                 : 
      82                 : 
      83                 : /*
      84                 :  * natp should be thread_self(), called while holding no locks.
      85                 :  */
      86           20845 : void NaClAppThreadTeardown(struct NaClAppThread *natp) {
      87           20845 :   struct NaClApp  *nap;
      88           20845 :   size_t          thread_idx;
      89                 : 
      90                 :   /*
      91                 :    * mark this thread as dead; doesn't matter if some other thread is
      92                 :    * asking us to commit suicide.
      93                 :    */
      94           20845 :   NaClLog(3, "NaClAppThreadTeardown(0x%08"NACL_PRIxPTR")\n",
      95                 :           (uintptr_t) natp);
      96           20845 :   nap = natp->nap;
      97           20845 :   if (NULL != nap->debug_stub_callbacks) {
      98               3 :     NaClLog(3, " notifying the debug stub of the thread exit\n");
      99                 :     /*
     100                 :      * This must happen before deallocating the ID natp->thread_num.
     101                 :      * We have the invariant that debug stub lock should be acquired before
     102                 :      * nap->threads_mu lock. Hence we must not hold threads_mu lock while
     103                 :      * calling debug stub hooks.
     104                 :      */
     105               3 :     nap->debug_stub_callbacks->thread_exit_hook(natp);
     106               3 :   }
     107                 : 
     108           20845 :   NaClLog(3, " getting thread table lock\n");
     109           20845 :   NaClXMutexLock(&nap->threads_mu);
     110           20845 :   NaClLog(3, " getting thread lock\n");
     111           20845 :   NaClXMutexLock(&natp->mu);
     112                 :   /*
     113                 :    * Remove ourselves from the ldt-indexed global tables.  The ldt
     114                 :    * entry is released as part of NaClAppThreadDelete(), and if
     115                 :    * another thread is immediately created (from some other running
     116                 :    * thread) we want to be sure that any ldt-based lookups will not
     117                 :    * reach this dying thread's data.
     118                 :    */
     119           20845 :   thread_idx = NaClGetThreadIdx(natp);
     120                 :   /*
     121                 :    * On x86-64 and ARM, clearing nacl_user entry ensures that we will
     122                 :    * fault if another syscall is made with this thread_idx.  In
     123                 :    * particular, thread_idx 0 is never used.
     124                 :    */
     125           20845 :   nacl_user[thread_idx] = NULL;
     126                 : #if NACL_WINDOWS
     127                 :   nacl_thread_ids[thread_idx] = 0;
     128                 : #elif NACL_OSX
     129           20845 :   NaClClearMachThreadForThreadIndex(thread_idx);
     130                 : #endif
     131                 :   /*
     132                 :    * Unset the TLS variable so that if a crash occurs during thread
     133                 :    * teardown, the signal handler does not dereference a dangling
     134                 :    * NaClAppThread pointer.
     135                 :    */
     136           20845 :   NaClTlsSetCurrentThread(NULL);
     137                 : 
     138           20845 :   NaClLog(3, " removing thread from thread table\n");
     139                 :   /* Deallocate the ID natp->thread_num. */
     140           20845 :   NaClRemoveThreadMu(nap, natp->thread_num);
     141           20845 :   NaClLog(3, " unlocking thread\n");
     142           20845 :   NaClXMutexUnlock(&natp->mu);
     143           20845 :   NaClLog(3, " unlocking thread table\n");
     144           20845 :   NaClXMutexUnlock(&nap->threads_mu);
     145           20845 :   NaClLog(3, " unregistering signal stack\n");
     146           20845 :   NaClSignalStackUnregister();
     147           20845 :   NaClLog(3, " freeing thread object\n");
     148           20845 :   NaClAppThreadDelete(natp);
     149           20845 :   NaClLog(3, " NaClThreadExit\n");
     150           20845 :   NaClThreadExit();
     151           20845 :   NaClLog(LOG_FATAL,
     152                 :           "NaClAppThreadTeardown: NaClThreadExit() should not return\n");
     153                 :   /* NOTREACHED */
     154           20845 : }
     155                 : 
     156                 : 
     157           20881 : struct NaClAppThread *NaClAppThreadMake(struct NaClApp *nap,
     158           20881 :                                         uintptr_t      usr_entry,
     159           20881 :                                         uintptr_t      usr_stack_ptr,
     160           20881 :                                         uint32_t       user_tls1,
     161           20881 :                                         uint32_t       user_tls2) {
     162           20881 :   struct NaClAppThread *natp;
     163                 : 
     164           20881 :   natp = NaClAlignedMalloc(sizeof *natp, __alignof(struct NaClAppThread));
     165           20881 :   if (natp == NULL) {
     166               0 :     return NULL;
     167                 :   }
     168                 : 
     169           20881 :   NaClLog(4, "         natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp);
     170           20881 :   NaClLog(4, "          nap = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) nap);
     171           20881 :   NaClLog(4, "usr_stack_ptr = 0x%016"NACL_PRIxPTR"\n", usr_stack_ptr);
     172                 : 
     173                 :   /*
     174                 :    * Set these early, in case NaClTlsAllocate() wants to examine them.
     175                 :    */
     176           20881 :   natp->nap = nap;
     177           20881 :   natp->thread_num = -1;  /* illegal index */
     178           20881 :   natp->host_thread_is_defined = 0;
     179           62643 :   memset(&natp->host_thread, 0, sizeof(natp->host_thread));
     180                 : 
     181           20881 :   if (!NaClAppThreadInitArchSpecific(natp, usr_entry, usr_stack_ptr)) {
     182               0 :     goto cleanup_free;
     183                 :   }
     184                 : 
     185           20881 :   NaClTlsSetTlsValue1(natp, user_tls1);
     186           20881 :   NaClTlsSetTlsValue2(natp, user_tls2);
     187                 : 
     188           20881 :   natp->signal_stack = NULL;
     189           20881 :   natp->exception_stack = 0;
     190           20881 :   natp->exception_flag = 0;
     191                 : 
     192           20881 :   if (!NaClMutexCtor(&natp->mu)) {
     193               0 :     goto cleanup_free;
     194                 :   }
     195                 : 
     196           20881 :   if (!NaClSignalStackAllocate(&natp->signal_stack)) {
     197               0 :     goto cleanup_mu;
     198                 :   }
     199                 : 
     200           20881 :   if (!NaClMutexCtor(&natp->suspend_mu)) {
     201               0 :     goto cleanup_mu;
     202                 :   }
     203           20881 :   natp->suspend_state = NACL_APP_THREAD_TRUSTED;
     204           20881 :   natp->suspended_registers = NULL;
     205           20881 :   natp->fault_signal = 0;
     206                 : 
     207           20881 :   natp->dynamic_delete_generation = 0;
     208                 : 
     209           20881 :   if (!NaClCondVarCtor(&natp->futex_condvar)) {
     210               0 :     goto cleanup_suspend_mu;
     211                 :   }
     212           20881 :   return natp;
     213                 : 
     214                 :  cleanup_suspend_mu:
     215               0 :   NaClMutexDtor(&natp->suspend_mu);
     216                 :  cleanup_mu:
     217               0 :   NaClMutexDtor(&natp->mu);
     218               0 :   if (NULL != natp->signal_stack) {
     219               0 :     NaClSignalStackFree(&natp->signal_stack);
     220               0 :     natp->signal_stack = NULL;
     221               0 :   }
     222                 :  cleanup_free:
     223               0 :   NaClAlignedFree(natp);
     224               0 :   return NULL;
     225           20881 : }
     226                 : 
     227                 : 
     228           20881 : int NaClAppThreadSpawn(struct NaClApp *nap,
     229           20881 :                        uintptr_t      usr_entry,
     230           20881 :                        uintptr_t      usr_stack_ptr,
     231           20881 :                        uint32_t       user_tls1,
     232           20881 :                        uint32_t       user_tls2) {
     233           20881 :   struct NaClAppThread *natp = NaClAppThreadMake(nap, usr_entry, usr_stack_ptr,
     234                 :                                                  user_tls1, user_tls2);
     235           20881 :   if (natp == NULL) {
     236               0 :     return 0;
     237                 :   }
     238                 :   /*
     239                 :    * We set host_thread_is_defined assuming, for now, that
     240                 :    * NaClThreadCtor() will succeed.
     241                 :    */
     242           20881 :   natp->host_thread_is_defined = 1;
     243           20881 :   if (!NaClThreadCtor(&natp->host_thread, NaClAppThreadLauncher, (void *) natp,
     244                 :                       NACL_KERN_STACK_SIZE)) {
     245                 :     /*
     246                 :      * No other thread saw the NaClAppThread, so it is OK that
     247                 :      * host_thread was not initialized despite host_thread_is_defined
     248                 :      * being set.
     249                 :      */
     250               0 :     natp->host_thread_is_defined = 0;
     251               0 :     NaClAppThreadDelete(natp);
     252               0 :     return 0;
     253                 :   }
     254           20881 :   return 1;
     255           20881 : }
     256                 : 
     257                 : 
     258           20291 : void NaClAppThreadDelete(struct NaClAppThread *natp) {
     259                 :   /*
     260                 :    * the thread must not be still running, else this crashes the system
     261                 :    */
     262                 : 
     263           20291 :   if (natp->host_thread_is_defined) {
     264           20291 :     NaClThreadDtor(&natp->host_thread);
     265           20291 :   }
     266           20291 :   free(natp->suspended_registers);
     267           20291 :   NaClMutexDtor(&natp->suspend_mu);
     268           20291 :   NaClSignalStackFree(natp->signal_stack);
     269           20291 :   natp->signal_stack = NULL;
     270           20291 :   NaClCondVarDtor(&natp->futex_condvar);
     271           20291 :   NaClTlsFree(natp);
     272           20291 :   NaClMutexDtor(&natp->mu);
     273           20291 :   NaClAlignedFree(natp);
     274           20291 : }

Generated by: LCOV version 1.7