LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - thread_suspension_common.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 42 41 97.6 %
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                 : #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           12186 : void NaClUntrustedThreadsSuspendAll(struct NaClApp *nap, int save_registers) {
      19                 :   size_t index;
      20                 : 
      21           12186 :   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           24381 :   for (index = 0; index < nap->threads.num_entries; index++) {
      31           12195 :     struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index);
      32           12195 :     if (natp != NULL) {
      33           12194 :       NaClUntrustedThreadSuspend(natp, save_registers);
      34                 :     }
      35                 :   }
      36           12186 : }
      37                 : 
      38           12169 : void NaClUntrustedThreadsResumeAll(struct NaClApp *nap) {
      39                 :   size_t index;
      40           24344 :   for (index = 0; index < nap->threads.num_entries; index++) {
      41           12175 :     struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index);
      42           12175 :     if (natp != NULL) {
      43           12175 :       NaClUntrustedThreadResume(natp);
      44                 :     }
      45                 :   }
      46                 : 
      47           12169 :   NaClXMutexUnlock(&nap->threads_mu);
      48           12169 : }
      49                 : 
      50           11105 : void NaClAppThreadGetSuspendedRegisters(struct NaClAppThread *natp,
      51                 :                                         struct NaClSignalContext *regs) {
      52           11105 :   if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) != 0) {
      53           10492 :     NaClAppThreadGetSuspendedRegistersInternal(natp, regs);
      54           10492 :     if (!NaClSignalContextIsUntrusted(natp, regs)) {
      55                 :       enum NaClUnwindCase unwind_case;
      56           10393 :       NaClGetRegistersForContextSwitch(natp, regs, &unwind_case);
      57                 :     }
      58                 :   } else {
      59             613 :     NaClThreadContextToSignalContext(&natp->user, regs);
      60                 :   }
      61           11105 : }
      62                 : 
      63           10000 : int NaClAppThreadIsSuspendedInSyscall(struct NaClAppThread *natp) {
      64           10000 :   if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) != 0) {
      65                 :     struct NaClSignalContext regs;
      66            9882 :     NaClAppThreadGetSuspendedRegistersInternal(natp, &regs);
      67            9882 :     return !NaClSignalContextIsUntrusted(natp, &regs);
      68                 :   }
      69             118 :   return 1;
      70                 : }
      71                 : 
      72            1080 : void NaClAppThreadSetSuspendedRegisters(struct NaClAppThread *natp,
      73                 :                                         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            1080 :   if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) != 0) {
      80                 :     struct NaClSignalContext current_regs;
      81             588 :     NaClAppThreadGetSuspendedRegistersInternal(natp, &current_regs);
      82             588 :     if (NaClSignalContextIsUntrusted(natp, &current_regs)) {
      83              77 :       NaClAppThreadSetSuspendedRegistersInternal(natp, regs);
      84                 :     } else {
      85             511 :       NaClLog(LOG_WARNING,
      86                 :               "NaClAppThreadSetSuspendedRegisters: Registers not modified "
      87                 :               "(thread suspended during trusted/untrusted context switch)\n");
      88                 :     }
      89                 :   } else {
      90             492 :     NaClLog(LOG_WARNING,
      91                 :             "NaClAppThreadSetSuspendedRegisters: Registers not modified "
      92                 :             "(thread suspended inside syscall)\n");
      93                 :   }
      94            1080 : }
      95                 : 
      96              20 : 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                 :   int fds[2];
     106                 : #if NACL_LINUX
     107              20 :   int ret = pipe2(fds, O_CLOEXEC);
     108                 : #else
     109                 :   int ret = pipe(fds);
     110                 : #endif
     111              20 :   if (ret < 0) {
     112               0 :     NaClLog(LOG_FATAL,
     113                 :             "NaClFaultedThreadQueueEnable: Failed to allocate pipe for "
     114                 :             "faulted thread events\n");
     115                 :   }
     116              20 :   nap->faulted_thread_fd_read = fds[0];
     117              20 :   nap->faulted_thread_fd_write = fds[1];
     118                 : #endif
     119              20 :   nap->enable_faulted_thread_queue = 1;
     120              20 :   return NaClDebugExceptionHandlerEnsureAttached(nap);
     121                 : }

Generated by: LCOV version 1.7