File: nacl_threads.c

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (127 lines) | stat: -rw-r--r-- 3,925 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/*
 * NaCl Server Runtime threads implementation layer.
 */

#include <stdlib.h>
/*
 * We need sys/mman.h for PAGE_SIZE on Android.  PAGE_SIZE is what
 * PTHREAD_STACK_MIN defined to, so Android's pthread.h is somewhat
 * buggy in that regard.
 */
#include <sys/mman.h>
#include <sys/types.h>
#include <signal.h>
#include <pthread.h>
#include <limits.h>
/*
 * PTHREAD_STACK_MIN should come from pthread.h as documented, but is
 * actually pulled in by limits.h.
 */

#include "native_client/src/include/portability.h"
#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/shared/platform/nacl_threads.h"
#include "native_client/src/trusted/service_runtime/nacl_config.h"

#if !defined(__native_client__) && NACL_KERN_STACK_SIZE < PTHREAD_STACK_MIN
# error "NaCl service runtime stack size is smaller than PTHREAD_STACK_MIN"
#endif

static int NaClThreadCreate(struct NaClThread  *ntp,
                            void               (*start_fn)(void *),
                            void               *state,
                            size_t             stack_size,
                            int                is_detached) {
  pthread_attr_t  attr;
  int             code;
  int             rv;

  rv = 0;

  if (stack_size < PTHREAD_STACK_MIN) {
    stack_size = PTHREAD_STACK_MIN;
  }
  if (0 != (code = pthread_attr_init(&attr))) {
    NaClLog(LOG_ERROR,
            "NaClThreadCtor: pthread_atr_init returned %d",
            code);
    goto done;
  }
  if (0 != (code = pthread_attr_setstacksize(&attr, stack_size))) {
    NaClLog(LOG_ERROR,
            "NaClThreadCtor: pthread_attr_setstacksize returned %d",
            code);
    goto done_attr_dtor;
  }
  if (is_detached) {
    if (0 != (code = pthread_attr_setdetachstate(&attr,
                                                 PTHREAD_CREATE_DETACHED))) {
      NaClLog(LOG_ERROR,
              "nacl_thread: pthread_attr_setdetachstate returned %d",
              code);
      goto done_attr_dtor;
    }
  }
  if (0 != (code = pthread_create(&ntp->tid,
                                  &attr,
                                  (void *(*)(void *)) start_fn,
                                  state))) {
    NaClLog(LOG_ERROR,
            "nacl_thread: pthread_create returned %d",
            code);
    goto done_attr_dtor;
  }
  rv = 1;
 done_attr_dtor:
  (void) pthread_attr_destroy(&attr);  /* often a noop */
 done:
  return rv;
}

/*
 * Even if ctor fails, it should be okay -- and required -- to invoke
 * the dtor on it.
 */
int NaClThreadCtor(struct NaClThread  *ntp,
                   void               (*start_fn)(void *),
                   void               *state,
                   size_t             stack_size) {
  return NaClThreadCreate(ntp, start_fn, state, stack_size,
                          /* is_detached= */ 1);
}

int NaClThreadCreateJoinable(struct NaClThread  *ntp,
                             void               (*start_fn)(void *),
                             void               *state,
                             size_t             stack_size) {
  return NaClThreadCreate(ntp, start_fn, state, stack_size,
                          /* is_detached= */ 0);
}

void NaClThreadDtor(struct NaClThread *ntp) {
  /*
   * The threads that we create are not joinable, and we cannot tell
   * when they are truly gone.  Fortunately, the threads themselves
   * and the underlying thread library are responsible for ensuring
   * that resources such as the thread stack are properly released.
   */
  UNREFERENCED_PARAMETER(ntp);
}

void NaClThreadJoin(struct NaClThread *ntp) {
  pthread_join(ntp->tid, NULL);
}

void NaClThreadExit(void) {
  pthread_exit(NULL);
}

void NaClThreadYield(void) {
  sched_yield();
}