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 /* copying collector will pin threadObj for us since it was an argument */
37 dvmCreateInterpThread(threadObj, (int) stackSize);
38 RETURN_VOID();
39 }
40
41 /*
42 * static Thread currentThread()
43 */
Dalvik_java_lang_VMThread_currentThread(const u4 * args,JValue * pResult)44 static void Dalvik_java_lang_VMThread_currentThread(const u4* args,
45 JValue* pResult)
46 {
47 UNUSED_PARAMETER(args);
48
49 RETURN_PTR(dvmThreadSelf()->threadObj);
50 }
51
52 /*
53 * void getStatus()
54 *
55 * Gets the Thread status. Result is in VM terms, has to be mapped to
56 * Thread.State by interpreted code.
57 */
Dalvik_java_lang_VMThread_getStatus(const u4 * args,JValue * pResult)58 static void Dalvik_java_lang_VMThread_getStatus(const u4* args, JValue* pResult)
59 {
60 Object* thisPtr = (Object*) args[0];
61 Thread* thread;
62 int result;
63
64 dvmLockThreadList(NULL);
65 thread = dvmGetThreadFromThreadObject(thisPtr);
66 if (thread != NULL)
67 result = thread->status;
68 else
69 result = THREAD_ZOMBIE; // assume it used to exist and is now gone
70 dvmUnlockThreadList();
71
72 RETURN_INT(result);
73 }
74
75 /*
76 * boolean holdsLock(Object object)
77 *
78 * Returns whether the current thread has a monitor lock on the specific
79 * object.
80 */
Dalvik_java_lang_VMThread_holdsLock(const u4 * args,JValue * pResult)81 static void Dalvik_java_lang_VMThread_holdsLock(const u4* args, JValue* pResult)
82 {
83 Object* thisPtr = (Object*) args[0];
84 Object* object = (Object*) args[1];
85 Thread* thread;
86
87 if (object == NULL) {
88 dvmThrowNullPointerException("object == null");
89 RETURN_VOID();
90 }
91
92 dvmLockThreadList(NULL);
93 thread = dvmGetThreadFromThreadObject(thisPtr);
94 int result = dvmHoldsLock(thread, object);
95 dvmUnlockThreadList();
96
97 RETURN_BOOLEAN(result);
98 }
99
100 /*
101 * void interrupt()
102 *
103 * Interrupt a thread that is waiting (or is about to wait) on a monitor.
104 */
Dalvik_java_lang_VMThread_interrupt(const u4 * args,JValue * pResult)105 static void Dalvik_java_lang_VMThread_interrupt(const u4* args, JValue* pResult)
106 {
107 Object* thisPtr = (Object*) args[0];
108 Thread* thread;
109
110 dvmLockThreadList(NULL);
111 thread = dvmGetThreadFromThreadObject(thisPtr);
112 if (thread != NULL)
113 dvmThreadInterrupt(thread);
114 dvmUnlockThreadList();
115 RETURN_VOID();
116 }
117
118 /*
119 * static boolean interrupted()
120 *
121 * Determine if the current thread has been interrupted. Clears the flag.
122 */
Dalvik_java_lang_VMThread_interrupted(const u4 * args,JValue * pResult)123 static void Dalvik_java_lang_VMThread_interrupted(const u4* args,
124 JValue* pResult)
125 {
126 Thread* self = dvmThreadSelf();
127 bool interrupted;
128
129 UNUSED_PARAMETER(args);
130
131 interrupted = self->interrupted;
132 self->interrupted = false;
133 RETURN_BOOLEAN(interrupted);
134 }
135
136 /*
137 * boolean isInterrupted()
138 *
139 * Determine if the specified thread has been interrupted. Does not clear
140 * the flag.
141 */
Dalvik_java_lang_VMThread_isInterrupted(const u4 * args,JValue * pResult)142 static void Dalvik_java_lang_VMThread_isInterrupted(const u4* args,
143 JValue* pResult)
144 {
145 Object* thisPtr = (Object*) args[0];
146 Thread* thread;
147 bool interrupted;
148
149 dvmLockThreadList(NULL);
150 thread = dvmGetThreadFromThreadObject(thisPtr);
151 if (thread != NULL)
152 interrupted = thread->interrupted;
153 else
154 interrupted = false;
155 dvmUnlockThreadList();
156
157 RETURN_BOOLEAN(interrupted);
158 }
159
160 /*
161 * void nameChanged(String newName)
162 *
163 * The name of the target thread has changed. We may need to alert DDMS.
164 */
Dalvik_java_lang_VMThread_nameChanged(const u4 * args,JValue * pResult)165 static void Dalvik_java_lang_VMThread_nameChanged(const u4* args,
166 JValue* pResult)
167 {
168 Object* thisPtr = (Object*) args[0];
169 StringObject* nameStr = (StringObject*) args[1];
170 Thread* thread;
171 int threadId = -1;
172
173 /* get the thread's ID */
174 dvmLockThreadList(NULL);
175 thread = dvmGetThreadFromThreadObject(thisPtr);
176 if (thread != NULL)
177 threadId = thread->threadId;
178 dvmUnlockThreadList();
179
180 dvmDdmSendThreadNameChange(threadId, nameStr);
181 //char* str = dvmCreateCstrFromString(nameStr);
182 //ALOGI("UPDATE: threadid=%d now '%s'", threadId, str);
183 //free(str);
184
185 RETURN_VOID();
186 }
187
188 /*
189 * void setPriority(int newPriority)
190 *
191 * Alter the priority of the specified thread. "newPriority" will range
192 * from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal"
193 * threads at Thread.NORM_PRIORITY (5).
194 */
Dalvik_java_lang_VMThread_setPriority(const u4 * args,JValue * pResult)195 static void Dalvik_java_lang_VMThread_setPriority(const u4* args,
196 JValue* pResult)
197 {
198 Object* thisPtr = (Object*) args[0];
199 int newPriority = args[1];
200 Thread* thread;
201
202 dvmLockThreadList(NULL);
203 thread = dvmGetThreadFromThreadObject(thisPtr);
204 if (thread != NULL)
205 dvmChangeThreadPriority(thread, newPriority);
206 //dvmDumpAllThreads(false);
207 dvmUnlockThreadList();
208
209 RETURN_VOID();
210 }
211
212 /*
213 * static void sleep(long msec, int nsec)
214 */
Dalvik_java_lang_VMThread_sleep(const u4 * args,JValue * pResult)215 static void Dalvik_java_lang_VMThread_sleep(const u4* args, JValue* pResult)
216 {
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