2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl Server Runtime user thread state.
36 #ifndef NATIVE_CLIENT_SERVICE_RUNTIME_NACL_APP_THREAD_H__
37 #define NATIVE_CLIENT_SERVICE_RUNTIME_NACL_APP_THREAD_H__ 1
39 #include "native_client/include/nacl_base.h"
40 #include "native_client/service_runtime/nacl_bottom_half.h"
41 #include "native_client/service_runtime/nacl_config.h"
42 #include "native_client/service_runtime/nacl_desc_effector.h"
43 #include "native_client/service_runtime/nacl_sync.h"
44 #include "native_client/service_runtime/nacl_threads.h"
45 #include "native_client/service_runtime/sel_rt.h"
51 enum NaClThreadState
{
52 NACL_APP_THREAD_ALIVE
,
53 /* NACL_APP_THREAD_INTERRUPTIBLE_MUTEX, etc */
54 NACL_APP_THREAD_SUICIDE_PENDING
,
59 * Generally, only the thread itself will need to manipulate this
60 * structure, but occasionally we may need to blow away a thread for
61 * some reason, and look inside. While a thread is in the NaCl
62 * application running untrusted code, the lock must *not* be held.
64 struct NaClAppThread
{
66 struct NaClCondVar cv
;
68 int is_privileged
; /* can make "special" syscalls? */
72 struct NaClClosureResult result
;
77 * The NaCl app that contains this thread. The app must exist as
78 * long as a thread is still alive.
83 * The effector interface object used to manipulate NaCl apps by the
84 * objects in the NaClDesc class hierarchy. Used by this thread when
85 * making NaClDesc method calls from syscall handlers.
87 struct NaClDescEffector
*effp
;
89 int thread_num
; /* index into nap->threads */
91 struct NaClThread thread
; /* low level thread representation */
94 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
96 * The locking behavior described below is not yet implemented.
98 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
100 * When a thread invokes a service call from the NaCl application,
101 * it must first grab its own lock (mu) before it executes any code
102 * that can grab other service runtime locks/resources. The thread
103 * clears the holding_sr_locks flag as it is about to return from
104 * the service call. Short duration service calls can just hold the
105 * lock throughout; potentially blocking service calls must drop the
106 * thread lock and reacquire when it can unblock. Condition
107 * variables are used to allow the thread to wake up. If a thread
108 * is blocked waiting for I/O, a central epoll thread is responsible
109 * for waking up the thread. (The epoll thread serves the same
110 * purpose as hardware interrupt handlers.)
112 * To summarily kill a thread from elsewhere, we check the
113 * holding_sr_locks flag after acquiring the target thread's lock.
114 * If it is clear, then the thread is running in the application
115 * space (or at least it has not yet touched any service runtime
116 * resources), and we can directly pthread_kill it before we release
117 * the thread lock. If it is set, we set the state flag to
118 * NACL_APP_THREAD_SUICIDE_PENDING and release the thread lock,
119 * possibly waking the blocked thread.
121 * When the thread is about to leave service runtime code and return
122 * to the NaCl application, it should have released all locks to
123 * service-runtime resources. Next, the thread grabs its own lock
124 * to clear the holding_sr_locks flag, at which point it examines
125 * the suicide flag; if it finds that set, it should gracefully
128 int holding_sr_locks
;
131 * a thread cannot free up its own mutex lock and commit suicide,
132 * since another thread may be trying to summarily kill it and is
133 * waiting on the lock in order to ask it to commit suicide!
134 * instead, the suiciding thread just marks itself as dead, and a
135 * periodic thread grabs a global thread table lock to do thread
136 * deletion (which the thread requesting summary execution must also
139 enum NaClThreadState state
;
141 struct NaClThreadContext user
;
142 /* sys is only used to hold segment registers */
143 struct NaClThreadContext sys
;
145 * NaClThread abstraction allows us to specify the stack size
146 * (NACL_KERN_STACK_SIZE), but not its location. The underlying
147 * implementation takes care of finding memory for the thread stack,
148 * and when the thread exits (they're not joinable), the stack
149 * should be automatically released.
154 * user's %esp translated to system address, used for accessing syscall
159 int NaClAppThreadCtor(struct NaClAppThread
*natp
,
166 void NaClAppThreadDtor(struct NaClAppThread
*natp
);
169 * Low level initialization of thread, with validated values. The
170 * usr_entry and usr_esp values are directly used to initialize the
171 * user register values; the sys_tdb_base is the system address for
172 * allocating a %gs thread descriptor block base. The caller is
173 * responsible for error checking: usr_entry is a valid entry point (0
174 * mod N) and sys_tdb_base is in the NaClApp's address space.
176 int NaClAppThreadAllocSegCtor(struct NaClAppThread
*natp
,
181 uintptr_t sys_tdb_base
,
184 int NaClAppThreadIncRef(struct NaClAppThread
*natp
);
186 int NaClAppThreadDecRef(struct NaClAppThread
*natp
);