1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * java.lang.VMThread
19 */
20 #include "Dalvik.h"
21 #include "native/InternalNativePriv.h"
22
23
24 /*
25 * static void create(Thread t, long stacksize)
26 *
27 * This is eventually called as a result of Thread.start().
28 *
29 * Throws an exception on failure.
30 */
Dalvik_java_lang_VMThread_create(const u4 * args,JValue * pResult)31 static void Dalvik_java_lang_VMThread_create(const u4* args, JValue* pResult)
32 {
33 Object* threadObj = (Object*) args[0];
34 s8 stackSize = GET_ARG_LONG(args, 1);
35
36 dvmCreateInterpThread(threadObj, (int) stackSize);
37 RETURN_VOID();
38 }
39
40 /*
41 * static Thread currentThread()
42 */
Dalvik_java_lang_VMThread_currentThread(const u4 * args,JValue * pResult)43 static void Dalvik_java_lang_VMThread_currentThread(const u4* args,
44 JValue* pResult)
45 {
46 UNUSED_PARAMETER(args);
47
48 RETURN_PTR(dvmThreadSelf()->threadObj);
49 }
50
51 /*
52 * void getStatus()
53 *
54 * Gets the Thread status. Result is in VM terms, has to be mapped to
55 * Thread.State by interpreted code.
56 */
Dalvik_java_lang_VMThread_getStatus(const u4 * args,JValue * pResult)57 static void Dalvik_java_lang_VMThread_getStatus(const u4* args, JValue* pResult)
58 {
59 Object* thisPtr = (Object*) args[0];
60 Thread* thread;
61 int result;
62
63 dvmLockThreadList(NULL);
64 thread = dvmGetThreadFromThreadObject(thisPtr);
65 if (thread != NULL)
66 result = thread->status;
67 else
68 result = THREAD_ZOMBIE; // assume it used to exist and is now gone
69 dvmUnlockThreadList();
70
71 RETURN_INT(result);
72 }
73
74 /*
75 * boolean holdsLock(Object object)
76 *
77 * Returns whether the current thread has a monitor lock on the specific
78 * object.
79 */
Dalvik_java_lang_VMThread_holdsLock(const u4 * args,JValue * pResult)80 static void Dalvik_java_lang_VMThread_holdsLock(const u4* args, JValue* pResult)
81 {
82 Object* thisPtr = (Object*) args[0];
83 Object* object = (Object*) args[1];
84 Thread* thread;
85
86 if (object == NULL) {
87 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
88 RETURN_VOID();
89 }
90
91 dvmLockThreadList(NULL);
92 thread = dvmGetThreadFromThreadObject(thisPtr);
93 int result = dvmHoldsLock(thread, object);
94 dvmUnlockThreadList();
95
96 RETURN_BOOLEAN(result);
97 }
98
99 /*
100 * void interrupt()
101 *
102 * Interrupt a thread that is waiting (or is about to wait) on a monitor.
103 */
Dalvik_java_lang_VMThread_interrupt(const u4 * args,JValue * pResult)104 static void Dalvik_java_lang_VMThread_interrupt(const u4* args, JValue* pResult)
105 {
106 Object* thisPtr = (Object*) args[0];
107 Thread* thread;
108
109 dvmLockThreadList(NULL);
110 thread = dvmGetThreadFromThreadObject(thisPtr);
111 if (thread != NULL)
112 dvmThreadInterrupt(thread);
113 dvmUnlockThreadList();
114 RETURN_VOID();
115 }
116
117 /*
118 * static boolean interrupted()
119 *
120 * Determine if the current thread has been interrupted. Clears the flag.
121 */
Dalvik_java_lang_VMThread_interrupted(const u4 * args,JValue * pResult)122 static void Dalvik_java_lang_VMThread_interrupted(const u4* args,
123 JValue* pResult)
124 {
125 Thread* self = dvmThreadSelf();
126 bool interrupted;
127
128 UNUSED_PARAMETER(args);
129
130 interrupted = self->interrupted;
131 self->interrupted = false;
132 RETURN_BOOLEAN(interrupted);
133 }
134
135 /*
136 * boolean isInterrupted()
137 *
138 * Determine if the specified thread has been interrupted. Does not clear
139 * the flag.
140 */
Dalvik_java_lang_VMThread_isInterrupted(const u4 * args,JValue * pResult)141 static void Dalvik_java_lang_VMThread_isInterrupted(const u4* args,
142 JValue* pResult)
143 {
144 Object* thisPtr = (Object*) args[0];
145 Thread* thread;
146 bool interrupted;
147
148 dvmLockThreadList(NULL);
149 thread = dvmGetThreadFromThreadObject(thisPtr);
150 if (thread != NULL)
151 interrupted = thread->interrupted;
152 else
153 interrupted = false;
154 dvmUnlockThreadList();
155
156 RETURN_BOOLEAN(interrupted);
157 }
158
159 /*
160 * void nameChanged(String newName)
161 *
162 * The name of the target thread has changed. We may need to alert DDMS.
163 */
Dalvik_java_lang_VMThread_nameChanged(const u4 * args,JValue * pResult)164 static void Dalvik_java_lang_VMThread_nameChanged(const u4* args,
165 JValue* pResult)
166 {
167 Object* thisPtr = (Object*) args[0];
168 StringObject* nameStr = (StringObject*) args[1];
169 Thread* thread;
170 int threadId = -1;
171
172 /* get the thread's ID */
173 dvmLockThreadList(NULL);
174 thread = dvmGetThreadFromThreadObject(thisPtr);
175 if (thread != NULL)
176 threadId = thread->threadId;
177 dvmUnlockThreadList();
178
179 dvmDdmSendThreadNameChange(threadId, nameStr);
180 //char* str = dvmCreateCstrFromString(nameStr);
181 //LOGI("UPDATE: threadid=%d now '%s'\n", threadId, str);
182 //free(str);
183
184 RETURN_VOID();
185 }
186
187 /*
188 * void setPriority(int newPriority)
189 *
190 * Alter the priority of the specified thread. "newPriority" will range
191 * from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal"
192 * threads at Thread.NORM_PRIORITY (5).
193 */
Dalvik_java_lang_VMThread_setPriority(const u4 * args,JValue * pResult)194 static void Dalvik_java_lang_VMThread_setPriority(const u4* args,
195 JValue* pResult)
196 {
197 Object* thisPtr = (Object*) args[0];
198 int newPriority = args[1];
199 Thread* thread;
200
201 dvmLockThreadList(NULL);
202 thread = dvmGetThreadFromThreadObject(thisPtr);
203 if (thread != NULL)
204 dvmChangeThreadPriority(thread, newPriority);
205 //dvmDumpAllThreads(false);
206 dvmUnlockThreadList();
207
208 RETURN_VOID();
209 }
210
211 /*
212 * static void sleep(long msec, int nsec)
213 */
Dalvik_java_lang_VMThread_sleep(const u4 * args,JValue * pResult)214 static void Dalvik_java_lang_VMThread_sleep(const u4* args, JValue* pResult)
215 {
216 Thread* self = dvmThreadSelf();
217 dvmThreadSleep(GET_ARG_LONG(args,0), args[2]);
218 RETURN_VOID();
219 }
220
221 /*
222 * public void yield()
223 *
224 * Causes the thread to temporarily pause and allow other threads to execute.
225 *
226 * The exact behavior is poorly defined. Some discussion here:
227 * http://www.cs.umd.edu/~pugh/java/memoryModel/archive/0944.html
228 */
Dalvik_java_lang_VMThread_yield(const u4 * args,JValue * pResult)229 static void Dalvik_java_lang_VMThread_yield(const u4* args, JValue* pResult)
230 {
231 UNUSED_PARAMETER(args);
232
233 sched_yield();
234
235 RETURN_VOID();
236 }
237
238 const DalvikNativeMethod dvm_java_lang_VMThread[] = {
239 { "create", "(Ljava/lang/Thread;J)V",
240 Dalvik_java_lang_VMThread_create },
241 { "currentThread", "()Ljava/lang/Thread;",
242 Dalvik_java_lang_VMThread_currentThread },
243 { "getStatus", "()I",
244 Dalvik_java_lang_VMThread_getStatus },
245 { "holdsLock", "(Ljava/lang/Object;)Z",
246 Dalvik_java_lang_VMThread_holdsLock },
247 { "interrupt", "()V",
248 Dalvik_java_lang_VMThread_interrupt },
249 { "interrupted", "()Z",
250 Dalvik_java_lang_VMThread_interrupted },
251 { "isInterrupted", "()Z",
252 Dalvik_java_lang_VMThread_isInterrupted },
253 { "nameChanged", "(Ljava/lang/String;)V",
254 Dalvik_java_lang_VMThread_nameChanged },
255 { "setPriority", "(I)V",
256 Dalvik_java_lang_VMThread_setPriority },
257 { "sleep", "(JI)V",
258 Dalvik_java_lang_VMThread_sleep },
259 { "yield", "()V",
260 Dalvik_java_lang_VMThread_yield },
261 { NULL, NULL, NULL },
262 };
263
264