LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_app_thread.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 108 89 82.4 %
Date: 2014-07-02 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           29420 : void WINAPI NaClAppThreadLauncher(void *state) {
      29           29420 :   struct NaClAppThread *natp = (struct NaClAppThread *) state;
      30                 :   uint32_t thread_idx;
      31           29420 :   NaClLog(4, "NaClAppThreadLauncher: entered\n");
      32                 : 
      33           29420 :   NaClSignalStackRegister(natp->signal_stack);
      34                 : 
      35           29420 :   NaClLog(4, "      natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp);
      36           29420 :   NaClLog(4, " prog_ctr  = 0x%016"NACL_PRIxNACL_REG"\n", natp->user.prog_ctr);
      37           29420 :   NaClLog(4, "stack_ptr  = 0x%016"NACL_PRIxPTR"\n",
      38                 :           NaClGetThreadCtxSp(&natp->user));
      39                 : 
      40           29420 :   thread_idx = NaClGetThreadIdx(natp);
      41           29420 :   CHECK(0 < thread_idx);
      42           29420 :   CHECK(thread_idx < NACL_THREAD_MAX);
      43           29420 :   NaClTlsSetCurrentThread(natp);
      44           29420 :   nacl_user[thread_idx] = &natp->user;
      45                 : #if NACL_WINDOWS
      46                 :   nacl_thread_ids[thread_idx] = GetCurrentThreadId();
      47                 : #elif NACL_OSX
      48                 :   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           29420 :   NaClXMutexLock(&natp->nap->threads_mu);
      58           29420 :   natp->thread_num = NaClAddThreadMu(natp->nap, natp);
      59           29420 :   NaClXMutexUnlock(&natp->nap->threads_mu);
      60                 : 
      61           29420 :   NaClVmHoleThreadStackIsSafe(natp->nap);
      62                 : 
      63           29420 :   NaClStackSafetyNowOnUntrustedStack();
      64                 : 
      65                 :   /*
      66                 :    * Notify the debug stub, that a new thread is availible.
      67                 :    */
      68           29420 :   if (NULL != natp->nap->debug_stub_callbacks) {
      69              23 :     natp->nap->debug_stub_callbacks->thread_create_hook(natp);
      70                 :   }
      71                 : 
      72                 :   /*
      73                 :    * After this NaClAppThreadSetSuspendState() call, we should not
      74                 :    * claim any mutexes, otherwise we risk deadlock.
      75                 :    */
      76           29420 :   NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_TRUSTED,
      77                 :                                NACL_APP_THREAD_UNTRUSTED);
      78                 : 
      79           29420 :   NaClStartThreadInApp(natp, natp->user.prog_ctr);
      80                 : }
      81                 : 
      82                 : 
      83                 : /*
      84                 :  * natp should be thread_self(), called while holding no locks.
      85                 :  */
      86           29365 : void NaClAppThreadTeardown(struct NaClAppThread *natp) {
      87                 :   struct NaClApp  *nap;
      88                 :   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           29365 :   NaClLog(3, "NaClAppThreadTeardown(0x%08"NACL_PRIxPTR")\n",
      95                 :           (uintptr_t) natp);
      96           29365 :   nap = natp->nap;
      97           29365 :   if (NULL != nap->debug_stub_callbacks) {
      98               4 :     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               4 :     nap->debug_stub_callbacks->thread_exit_hook(natp);
     106                 :   }
     107                 : 
     108           29365 :   NaClLog(3, " getting thread table lock\n");
     109           29365 :   NaClXMutexLock(&nap->threads_mu);
     110           29365 :   NaClLog(3, " getting thread lock\n");
     111           29365 :   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           29365 :   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           29365 :   nacl_user[thread_idx] = NULL;
     126                 : #if NACL_WINDOWS
     127                 :   nacl_thread_ids[thread_idx] = 0;
     128                 : #elif NACL_OSX
     129                 :   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           29365 :   NaClTlsSetCurrentThread(NULL);
     137                 : 
     138           29365 :   NaClLog(3, " removing thread from thread table\n");
     139                 :   /* Deallocate the ID natp->thread_num. */
     140           29365 :   NaClRemoveThreadMu(nap, natp->thread_num);
     141           29365 :   NaClLog(3, " unlocking thread\n");
     142           29365 :   NaClXMutexUnlock(&natp->mu);
     143           29365 :   NaClLog(3, " unlocking thread table\n");
     144           29365 :   NaClXMutexUnlock(&nap->threads_mu);
     145           29365 :   NaClLog(3, " unregistering signal stack\n");
     146           29365 :   NaClSignalStackUnregister();
     147           29364 :   NaClLog(3, " freeing thread object\n");
     148           29364 :   NaClAppThreadDelete(natp);
     149           29365 :   NaClLog(3, " NaClThreadExit\n");
     150           29365 :   NaClThreadExit();
     151               0 :   NaClLog(LOG_FATAL,
     152                 :           "NaClAppThreadTeardown: NaClThreadExit() should not return\n");
     153                 :   /* NOTREACHED */
     154               0 : }
     155                 : 
     156                 : 
     157           29420 : struct NaClAppThread *NaClAppThreadMake(struct NaClApp *nap,
     158                 :                                         uintptr_t      usr_entry,
     159                 :                                         uintptr_t      usr_stack_ptr,
     160                 :                                         uint32_t       user_tls1,
     161                 :                                         uint32_t       user_tls2) {
     162                 :   struct NaClAppThread *natp;
     163                 : 
     164           29420 :   natp = NaClAlignedMalloc(sizeof *natp, __alignof(struct NaClAppThread));
     165           29420 :   if (natp == NULL) {
     166               0 :     return NULL;
     167                 :   }
     168                 : 
     169           29420 :   NaClLog(4, "         natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp);
     170           29420 :   NaClLog(4, "          nap = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) nap);
     171           29420 :   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           29420 :   natp->nap = nap;
     177           29420 :   natp->thread_num = -1;  /* illegal index */
     178           29420 :   natp->host_thread_is_defined = 0;
     179           29420 :   memset(&natp->host_thread, 0, sizeof(natp->host_thread));
     180                 : 
     181           29420 :   if (!NaClAppThreadInitArchSpecific(natp, usr_entry, usr_stack_ptr)) {
     182               0 :     goto cleanup_free;
     183                 :   }
     184                 : 
     185           29420 :   NaClTlsSetTlsValue1(natp, user_tls1);
     186           29420 :   NaClTlsSetTlsValue2(natp, user_tls2);
     187                 : 
     188           29420 :   natp->signal_stack = NULL;
     189           29420 :   natp->exception_stack = 0;
     190           29420 :   natp->exception_flag = 0;
     191                 : 
     192           29420 :   if (!NaClMutexCtor(&natp->mu)) {
     193               0 :     goto cleanup_free;
     194                 :   }
     195                 : 
     196           29420 :   if (!NaClSignalStackAllocate(&natp->signal_stack)) {
     197               0 :     goto cleanup_mu;
     198                 :   }
     199                 : 
     200           29420 :   if (!NaClMutexCtor(&natp->suspend_mu)) {
     201               0 :     goto cleanup_mu;
     202                 :   }
     203           29420 :   natp->suspend_state = NACL_APP_THREAD_TRUSTED;
     204           29420 :   natp->suspended_registers = NULL;
     205           29420 :   natp->fault_signal = 0;
     206                 : 
     207           29420 :   natp->dynamic_delete_generation = 0;
     208                 : 
     209           29420 :   if (!NaClCondVarCtor(&natp->futex_condvar)) {
     210               0 :     goto cleanup_suspend_mu;
     211                 :   }
     212           29420 :   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                 :   }
     222                 :  cleanup_free:
     223               0 :   NaClAlignedFree(natp);
     224               0 :   return NULL;
     225                 : }
     226                 : 
     227                 : 
     228           29420 : int NaClAppThreadSpawn(struct NaClApp *nap,
     229                 :                        uintptr_t      usr_entry,
     230                 :                        uintptr_t      usr_stack_ptr,
     231                 :                        uint32_t       user_tls1,
     232                 :                        uint32_t       user_tls2) {
     233           29420 :   struct NaClAppThread *natp = NaClAppThreadMake(nap, usr_entry, usr_stack_ptr,
     234                 :                                                  user_tls1, user_tls2);
     235           29420 :   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           29420 :   natp->host_thread_is_defined = 1;
     243           29420 :   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           29420 :   return 1;
     255                 : }
     256                 : 
     257                 : 
     258           29364 : void NaClAppThreadDelete(struct NaClAppThread *natp) {
     259                 :   /*
     260                 :    * the thread must not be still running, else this crashes the system
     261                 :    */
     262                 : 
     263           29364 :   if (natp->host_thread_is_defined) {
     264           29364 :     NaClThreadDtor(&natp->host_thread);
     265                 :   }
     266           29364 :   free(natp->suspended_registers);
     267           29364 :   NaClMutexDtor(&natp->suspend_mu);
     268           29364 :   NaClSignalStackFree(natp->signal_stack);
     269           29365 :   natp->signal_stack = NULL;
     270           29365 :   NaClCondVarDtor(&natp->futex_condvar);
     271           29365 :   NaClTlsFree(natp);
     272           29365 :   NaClMutexDtor(&natp->mu);
     273           29365 :   NaClAlignedFree(natp);
     274           29365 : }

Generated by: LCOV version 1.7