Home | History | Annotate | Download | only in native
      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  */
     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  */
     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  */
     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  */
     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  */
    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  */
    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  */
    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  */
    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     //LOGI("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  */
    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  */
    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  */
    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