/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* java.lang.VMThread
*/
#include "Dalvik.h"
#include "native/InternalNativePriv.h"
/*
* static void create(Thread t, long stacksize)
*
* This is eventually called as a result of Thread.start().
*
* Throws an exception on failure.
*/
static void Dalvik_java_lang_VMThread_create(const u4* args, JValue* pResult)
{
Object* threadObj = (Object*) args[0];
s8 stackSize = GET_ARG_LONG(args, 1);
/* copying collector will pin threadObj for us since it was an argument */
dvmCreateInterpThread(threadObj, (int) stackSize);
RETURN_VOID();
}
/*
* static Thread currentThread()
*/
static void Dalvik_java_lang_VMThread_currentThread(const u4* args,
JValue* pResult)
{
UNUSED_PARAMETER(args);
RETURN_PTR(dvmThreadSelf()->threadObj);
}
/*
* void getStatus()
*
* Gets the Thread status. Result is in VM terms, has to be mapped to
* Thread.State by interpreted code.
*/
static void Dalvik_java_lang_VMThread_getStatus(const u4* args, JValue* pResult)
{
Object* thisPtr = (Object*) args[0];
Thread* thread;
int result;
dvmLockThreadList(NULL);
thread = dvmGetThreadFromThreadObject(thisPtr);
if (thread != NULL)
result = thread->status;
else
result = THREAD_ZOMBIE; // assume it used to exist and is now gone
dvmUnlockThreadList();
RETURN_INT(result);
}
/*
* boolean holdsLock(Object object)
*
* Returns whether the current thread has a monitor lock on the specific
* object.
*/
static void Dalvik_java_lang_VMThread_holdsLock(const u4* args, JValue* pResult)
{
Object* thisPtr = (Object*) args[0];
Object* object = (Object*) args[1];
Thread* thread;
if (object == NULL) {
dvmThrowException("Ljava/lang/NullPointerException;", NULL);
RETURN_VOID();
}
dvmLockThreadList(NULL);
thread = dvmGetThreadFromThreadObject(thisPtr);
int result = dvmHoldsLock(thread, object);
dvmUnlockThreadList();
RETURN_BOOLEAN(result);
}
/*
* void interrupt()
*
* Interrupt a thread that is waiting (or is about to wait) on a monitor.
*/
static void Dalvik_java_lang_VMThread_interrupt(const u4* args, JValue* pResult)
{
Object* thisPtr = (Object*) args[0];
Thread* thread;
dvmLockThreadList(NULL);
thread = dvmGetThreadFromThreadObject(thisPtr);
if (thread != NULL)
dvmThreadInterrupt(thread);
dvmUnlockThreadList();
RETURN_VOID();
}
/*
* static boolean interrupted()
*
* Determine if the current thread has been interrupted. Clears the flag.
*/
static void Dalvik_java_lang_VMThread_interrupted(const u4* args,
JValue* pResult)
{
Thread* self = dvmThreadSelf();
bool interrupted;
UNUSED_PARAMETER(args);
interrupted = self->interrupted;
self->interrupted = false;
RETURN_BOOLEAN(interrupted);
}
/*
* boolean isInterrupted()
*
* Determine if the specified thread has been interrupted. Does not clear
* the flag.
*/
static void Dalvik_java_lang_VMThread_isInterrupted(const u4* args,
JValue* pResult)
{
Object* thisPtr = (Object*) args[0];
Thread* thread;
bool interrupted;
dvmLockThreadList(NULL);
thread = dvmGetThreadFromThreadObject(thisPtr);
if (thread != NULL)
interrupted = thread->interrupted;
else
interrupted = false;
dvmUnlockThreadList();
RETURN_BOOLEAN(interrupted);
}
/*
* void nameChanged(String newName)
*
* The name of the target thread has changed. We may need to alert DDMS.
*/
static void Dalvik_java_lang_VMThread_nameChanged(const u4* args,
JValue* pResult)
{
Object* thisPtr = (Object*) args[0];
StringObject* nameStr = (StringObject*) args[1];
Thread* thread;
int threadId = -1;
/* get the thread's ID */
dvmLockThreadList(NULL);
thread = dvmGetThreadFromThreadObject(thisPtr);
if (thread != NULL)
threadId = thread->threadId;
dvmUnlockThreadList();
dvmDdmSendThreadNameChange(threadId, nameStr);
//char* str = dvmCreateCstrFromString(nameStr);
//LOGI("UPDATE: threadid=%d now '%s'\n", threadId, str);
//free(str);
RETURN_VOID();
}
/*
* void setPriority(int newPriority)
*
* Alter the priority of the specified thread. "newPriority" will range
* from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal"
* threads at Thread.NORM_PRIORITY (5).
*/
static void Dalvik_java_lang_VMThread_setPriority(const u4* args,
JValue* pResult)
{
Object* thisPtr = (Object*) args[0];
int newPriority = args[1];
Thread* thread;
dvmLockThreadList(NULL);
thread = dvmGetThreadFromThreadObject(thisPtr);
if (thread != NULL)
dvmChangeThreadPriority(thread, newPriority);
//dvmDumpAllThreads(false);
dvmUnlockThreadList();
RETURN_VOID();
}
/*
* static void sleep(long msec, int nsec)
*/
static void Dalvik_java_lang_VMThread_sleep(const u4* args, JValue* pResult)
{
dvmThreadSleep(GET_ARG_LONG(args,0), args[2]);
RETURN_VOID();
}
/*
* public void yield()
*
* Causes the thread to temporarily pause and allow other threads to execute.
*
* The exact behavior is poorly defined. Some discussion here:
* http://www.cs.umd.edu/~pugh/java/memoryModel/archive/0944.html
*/
static void Dalvik_java_lang_VMThread_yield(const u4* args, JValue* pResult)
{
UNUSED_PARAMETER(args);
sched_yield();
RETURN_VOID();
}
const DalvikNativeMethod dvm_java_lang_VMThread[] = {
{ "create", "(Ljava/lang/Thread;J)V",
Dalvik_java_lang_VMThread_create },
{ "currentThread", "()Ljava/lang/Thread;",
Dalvik_java_lang_VMThread_currentThread },
{ "getStatus", "()I",
Dalvik_java_lang_VMThread_getStatus },
{ "holdsLock", "(Ljava/lang/Object;)Z",
Dalvik_java_lang_VMThread_holdsLock },
{ "interrupt", "()V",
Dalvik_java_lang_VMThread_interrupt },
{ "interrupted", "()Z",
Dalvik_java_lang_VMThread_interrupted },
{ "isInterrupted", "()Z",
Dalvik_java_lang_VMThread_isInterrupted },
{ "nameChanged", "(Ljava/lang/String;)V",
Dalvik_java_lang_VMThread_nameChanged },
{ "setPriority", "(I)V",
Dalvik_java_lang_VMThread_setPriority },
{ "sleep", "(JI)V",
Dalvik_java_lang_VMThread_sleep },
{ "yield", "()V",
Dalvik_java_lang_VMThread_yield },
{ NULL, NULL, NULL },
};