LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - thread_suspension_common.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 60 58 96.7 %
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                 : #include <string.h>
       8                 : 
       9                 : #include "native_client/src/include/portability_io.h"
      10                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      11                 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
      12                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      13                 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
      14                 : #include "native_client/src/trusted/service_runtime/thread_suspension.h"
      15                 : #include "native_client/src/trusted/service_runtime/thread_suspension_unwind.h"
      16                 : #include "native_client/src/trusted/service_runtime/win/debug_exception_handler.h"
      17                 : 
      18           12386 : void NaClUntrustedThreadsSuspendAll(struct NaClApp *nap, int save_registers) {
      19           12386 :   size_t index;
      20                 : 
      21           12386 :   NaClXMutexLock(&nap->threads_mu);
      22                 : 
      23                 :   /*
      24                 :    * TODO(mseaborn): A possible refinement here would be to use separate loops
      25                 :    * for initiating and waiting for the suspension of the threads.  This might
      26                 :    * be faster, since we would not be waiting for each thread to suspend one by
      27                 :    * one.  It would take advantage of the asynchronous nature of thread
      28                 :    * suspension.
      29                 :    */
      30           49562 :   for (index = 0; index < nap->threads.num_entries; index++) {
      31           12395 :     struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index);
      32           12395 :     if (natp != NULL) {
      33           12393 :       NaClUntrustedThreadSuspend(natp, save_registers);
      34           12393 :     }
      35           12395 :   }
      36           12386 : }
      37                 : 
      38           12370 : void NaClUntrustedThreadsResumeAll(struct NaClApp *nap) {
      39           12370 :   size_t index;
      40           49492 :   for (index = 0; index < nap->threads.num_entries; index++) {
      41           12376 :     struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index);
      42           12376 :     if (natp != NULL) {
      43           12376 :       NaClUntrustedThreadResume(natp);
      44           12376 :     }
      45           12376 :   }
      46                 : 
      47           12370 :   NaClXMutexUnlock(&nap->threads_mu);
      48           12370 : }
      49                 : 
      50           11104 : void NaClAppThreadGetSuspendedRegisters(struct NaClAppThread *natp,
      51           11104 :                                         struct NaClSignalContext *regs) {
      52           11104 :   if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) != 0) {
      53            5847 :     NaClAppThreadGetSuspendedRegistersInternal(natp, regs);
      54            5847 :     if (!NaClSignalContextIsUntrusted(natp, regs)) {
      55            5749 :       enum NaClUnwindCase unwind_case;
      56            5749 :       NaClGetRegistersForContextSwitch(natp, regs, &unwind_case);
      57            5749 :     }
      58            5847 :   } else {
      59            5257 :     NaClThreadContextToSignalContext(&natp->user, regs);
      60                 :   }
      61           11104 : }
      62                 : 
      63           10000 : int NaClAppThreadIsSuspendedInSyscall(struct NaClAppThread *natp) {
      64           10000 :   if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) != 0) {
      65            5728 :     struct NaClSignalContext regs;
      66            5728 :     NaClAppThreadGetSuspendedRegistersInternal(natp, &regs);
      67            5728 :     return !NaClSignalContextIsUntrusted(natp, &regs);
      68                 :   }
      69            4272 :   return 1;
      70           10000 : }
      71                 : 
      72            1081 : void NaClAppThreadSetSuspendedRegisters(struct NaClAppThread *natp,
      73            1081 :                                         const struct NaClSignalContext *regs) {
      74                 :   /*
      75                 :    * We only allow modifying the register state if the thread was
      76                 :    * suspended while executing untrusted code, not if the thread is
      77                 :    * inside a NaCl syscall.
      78                 :    */
      79            1081 :   if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) != 0) {
      80              99 :     struct NaClSignalContext current_regs;
      81              99 :     NaClAppThreadGetSuspendedRegistersInternal(natp, &current_regs);
      82              99 :     if (NaClSignalContextIsUntrusted(natp, &current_regs)) {
      83              78 :       NaClAppThreadSetSuspendedRegistersInternal(natp, regs);
      84              78 :     } else {
      85              21 :       NaClLog(LOG_WARNING,
      86                 :               "NaClAppThreadSetSuspendedRegisters: Registers not modified "
      87                 :               "(thread suspended during trusted/untrusted context switch)\n");
      88                 :     }
      89              99 :   } else {
      90             982 :     NaClLog(LOG_WARNING,
      91                 :             "NaClAppThreadSetSuspendedRegisters: Registers not modified "
      92                 :             "(thread suspended inside syscall)\n");
      93                 :   }
      94            1081 : }
      95                 : 
      96              18 : int NaClFaultedThreadQueueEnable(struct NaClApp *nap) {
      97                 : #if NACL_WINDOWS
      98                 :   nap->faulted_thread_event = CreateEvent(NULL, TRUE, FALSE, NULL);
      99                 :   if (nap->faulted_thread_event == NULL) {
     100                 :     NaClLog(LOG_FATAL,
     101                 :             "NaClFaultedThreadQueueEnable: Failed to create event object for "
     102                 :             "faulted thread events\n");
     103                 :   }
     104                 : #else
     105              18 :   int fds[2];
     106                 : #if NACL_LINUX
     107                 :   int ret = pipe2(fds, O_CLOEXEC);
     108                 : #else
     109              18 :   int ret = pipe(fds);
     110                 : #endif
     111              18 :   if (ret < 0) {
     112               0 :     NaClLog(LOG_FATAL,
     113                 :             "NaClFaultedThreadQueueEnable: Failed to allocate pipe for "
     114                 :             "faulted thread events\n");
     115               0 :   }
     116              18 :   nap->faulted_thread_fd_read = fds[0];
     117              18 :   nap->faulted_thread_fd_write = fds[1];
     118                 : #endif
     119              18 :   nap->enable_faulted_thread_queue = 1;
     120              18 :   return NaClDebugExceptionHandlerEnsureAttached(nap);
     121                 : }

Generated by: LCOV version 1.7