0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: /**
0018: * @author Roman S. Bushmanov
0019: * @version $Revision: 1.1.2.4.4.4 $
0020: */package java.lang;
0021:
0022: import java.security.AccessController;
0023: import java.util.HashMap;
0024: import java.util.IdentityHashMap;
0025: import java.util.Iterator;
0026: import java.util.Map;
0027:
0028: import org.apache.harmony.lang.RuntimePermissionCollection;
0029: import org.apache.harmony.security.fortress.SecurityUtils;
0030: import org.apache.harmony.vm.VMStack;
0031:
0032: /**
0033: * @com.intel.drl.spec_ref
0034: */
0035: public class Thread implements Runnable {
0036:
0037: /**
0038: * @com.intel.drl.spec_ref
0039: */
0040: public static final int MAX_PRIORITY = 10;
0041:
0042: /**
0043: * @com.intel.drl.spec_ref
0044: */
0045: public static final int MIN_PRIORITY = 1;
0046:
0047: /**
0048: * @com.intel.drl.spec_ref
0049: */
0050: public static final int NORM_PRIORITY = 5;
0051:
0052: /**
0053: * Indent string used to print stack trace
0054: */
0055: private static final String STACK_TRACE_INDENT = " ";
0056:
0057: /**
0058: * This thread's thread group
0059: */
0060: ThreadGroup group;
0061:
0062: /**
0063: * This thread's context class loader
0064: */
0065: private ClassLoader contextClassLoader;
0066:
0067: /**
0068: * Indicates whether this thread was marked as daemon
0069: */
0070: private boolean daemon;
0071:
0072: /**
0073: * Thread's name
0074: */
0075: private String name;
0076:
0077: /**
0078: * Thread's priority
0079: */
0080: private int priority;
0081:
0082: /**
0083: * Stack size to be passed to VM for thread execution
0084: */
0085: private long stackSize;
0086:
0087: /**
0088: * Indicates if the thread was already started
0089: */
0090: boolean started = false;
0091:
0092: /**
0093: * Indicates if the thread is alive.
0094: */
0095: boolean isAlive = false;
0096:
0097: /**
0098: * Thread's target - a <code>Runnable</code> object whose <code>run</code>
0099: * method should be invoked
0100: */
0101: private Runnable target;
0102:
0103: /**
0104: * This map is used to provide <code>ThreadLocal</code> functionality.
0105: * Maps <code>ThreadLocal</code> object to value. Lazy initialization is
0106: * used to avoid circular dependance.
0107: */
0108: private Map<ThreadLocal<Object>, Object> localValues = null;
0109:
0110: /**
0111: * Uncaught exception handler for this thread
0112: */
0113: private UncaughtExceptionHandler exceptionHandler = null;
0114:
0115: /**
0116: * Default uncaught exception handler
0117: */
0118: private static UncaughtExceptionHandler defaultExceptionHandler = null;
0119:
0120: /**
0121: * Thread's ID
0122: */
0123: private long threadId;
0124:
0125: /**
0126: * Counter used to generate thread's ID
0127: */
0128: private static long threadOrdinalNum = 0;
0129:
0130: /**
0131: * Synchronization is done using internal lock.
0132: */
0133: Object lock = new Object();
0134:
0135: /**
0136: * used to generate a default thread name
0137: */
0138: private static final String THREAD = "Thread-";
0139:
0140: /**
0141: * System thread group for keeping helper threads.
0142: */
0143: static ThreadGroup systemThreadGroup = null;
0144:
0145: /**
0146: * Main thread group.
0147: */
0148: static ThreadGroup mainThreadGroup = null;
0149:
0150: /*
0151: * Number of threads that was created w/o garbage collection.
0152: */
0153: private static int currentGCWatermarkCount = 0;
0154:
0155: /*
0156: * Max number of threads to be created w/o GC, required collect dead Thread
0157: * references.
0158: */
0159: private static final int GC_WATERMARK_MAX_COUNT = 700;
0160:
0161: /**
0162: * @com.intel.drl.spec_ref
0163: */
0164: public Thread() {
0165: this (null, null, THREAD, 0);
0166: }
0167:
0168: /**
0169: * @com.intel.drl.spec_ref
0170: */
0171: public Thread(Runnable target) {
0172: this (null, target, THREAD, 0);
0173: }
0174:
0175: /**
0176: * @com.intel.drl.spec_ref
0177: */
0178: public Thread(Runnable target, String name) {
0179: this (null, target, name, 0);
0180: }
0181:
0182: /**
0183: * @com.intel.drl.spec_ref
0184: */
0185: public Thread(String name) {
0186: this (null, null, name, 0);
0187: }
0188:
0189: /**
0190: * @com.intel.drl.spec_ref
0191: */
0192: public Thread(ThreadGroup group, Runnable target) {
0193: this (group, target, THREAD, 0);
0194: }
0195:
0196: /**
0197: * @com.intel.drl.spec_ref
0198: */
0199: public Thread(ThreadGroup group, Runnable target, String name) {
0200: this (group, target, name, 0);
0201: }
0202:
0203: /**
0204: * Creates a new thread object for the thread attached to VM.
0205: * The first attached thread is the main thread.
0206: *
0207: * @param group determines the thread group to place the thread in
0208: * @param name thread's name
0209: * @param nativeAddr address of the attached native thread
0210: * @param stackeSize size of the thread's stack
0211: * @param priority thread's priority
0212: * @param daemon true if the thread is daemon, false otherwise
0213: */
0214: Thread(ThreadGroup group, String name, long nativeAddr,
0215: long stackSize, int priority, boolean daemon) {
0216:
0217: ClassLoader contextLoader = null;
0218:
0219: if (group == null) {
0220: if (systemThreadGroup == null) {
0221: // This is main thread.
0222: systemThreadGroup = new ThreadGroup();
0223: mainThreadGroup = new ThreadGroup(systemThreadGroup,
0224: "main");
0225: group = mainThreadGroup;
0226: } else {
0227: group = mainThreadGroup;
0228: }
0229: }
0230:
0231: this .group = group;
0232: this .stackSize = stackSize;
0233: this .priority = priority;
0234: this .daemon = daemon;
0235: this .threadId = getNextThreadId();
0236: this .name = (name != null) ? name : THREAD + threadId;
0237: // Each thread created from JNI has bootstrap class loader as
0238: // its context class loader. The only exception is the main thread
0239: // which has system class loader as its context class loader.
0240: this .contextClassLoader = contextLoader;
0241: this .target = null;
0242: // The thread is actually running.
0243: this .isAlive = true;
0244: this .started = true;
0245:
0246: ThreadWeakRef newRef = new ThreadWeakRef(this );
0247: newRef.setNativeAddr(nativeAddr);
0248:
0249: SecurityUtils.putContext(this , AccessController.getContext());
0250: // adding the thread to the thread group should be the last action
0251: group.add(this );
0252: }
0253:
0254: /**
0255: * @com.intel.drl.spec_ref
0256: */
0257: public Thread(ThreadGroup group, Runnable target, String name,
0258: long stackSize) {
0259:
0260: Thread currentThread = VMThreadManager.currentThread();
0261: SecurityManager securityManager = System.getSecurityManager();
0262:
0263: ThreadGroup threadGroup = null;
0264: if (group != null) {
0265: if (securityManager != null) {
0266: securityManager.checkAccess(group);
0267: }
0268: threadGroup = group;
0269: } else if (securityManager != null) {
0270: threadGroup = securityManager.getThreadGroup();
0271: }
0272: if (threadGroup == null) {
0273: threadGroup = currentThread.group;
0274: }
0275:
0276: threadGroup.checkGroup();
0277:
0278: this .group = threadGroup;
0279: this .daemon = currentThread.daemon;
0280: this .contextClassLoader = currentThread.contextClassLoader;
0281: this .target = target;
0282: this .stackSize = stackSize;
0283: this .priority = currentThread.priority;
0284: this .threadId = getNextThreadId();
0285: // throws NullPointerException if the given name is null
0286: this .name = (name != THREAD) ? this .name = name.toString()
0287: : THREAD + threadId;
0288:
0289: initializeInheritableLocalValues(currentThread);
0290:
0291: checkGCWatermark();
0292:
0293: ThreadWeakRef oldRef = ThreadWeakRef.poll();
0294: ThreadWeakRef newRef = new ThreadWeakRef(this );
0295:
0296: long oldPointer = (oldRef == null) ? 0 : oldRef.getNativeAddr();
0297: long newPointer = VMThreadManager
0298: .init(this , newRef, oldPointer);
0299: if (newPointer == 0) {
0300: throw new OutOfMemoryError("Failed to create new thread");
0301: }
0302: newRef.setNativeAddr(newPointer);
0303:
0304: SecurityUtils.putContext(this , AccessController.getContext());
0305: checkAccess();
0306: }
0307:
0308: /**
0309: * @com.intel.drl.spec_ref
0310: */
0311: public Thread(ThreadGroup group, String name) {
0312: this (group, null, name, 0);
0313: }
0314:
0315: /**
0316: * @com.intel.drl.spec_ref
0317: */
0318: public static int activeCount() {
0319: return currentThread().group.activeCount();
0320: }
0321:
0322: /**
0323: * @com.intel.drl.spec_ref
0324: */
0325: public static Thread currentThread() {
0326: return VMThreadManager.currentThread();
0327: }
0328:
0329: /**
0330: * @com.intel.drl.spec_ref
0331: */
0332: public static void dumpStack() {
0333: StackTraceElement[] stack = (new Throwable()).getStackTrace();
0334: System.err.println("Stack trace");
0335: for (int i = 0; i < stack.length; i++) {
0336: System.err.println(STACK_TRACE_INDENT + stack[i]);
0337: }
0338: }
0339:
0340: /**
0341: * @com.intel.drl.spec_ref
0342: */
0343: public static int enumerate(Thread[] list) {
0344: return currentThread().group.enumerate(list);
0345: }
0346:
0347: /**
0348: * @com.intel.drl.spec_ref
0349: */
0350: public static boolean holdsLock(Object object) {
0351: if (object == null) {
0352: throw new NullPointerException();
0353: }
0354: return VMThreadManager.holdsLock(object);
0355: }
0356:
0357: /**
0358: * @com.intel.drl.spec_ref
0359: */
0360: public static boolean interrupted() {
0361: return VMThreadManager.isInterrupted();
0362: }
0363:
0364: /**
0365: * @com.intel.drl.spec_ref
0366: */
0367: public static void sleep(long millis) throws InterruptedException {
0368: sleep(millis, 0);
0369: }
0370:
0371: /**
0372: * @com.intel.drl.spec_ref
0373: */
0374: public static void sleep(long millis, int nanos)
0375: throws InterruptedException {
0376: if (millis < 0 || nanos < 0 || nanos > 999999) {
0377: throw new IllegalArgumentException(
0378: "Arguments don't match the expected range!");
0379: }
0380: int status = VMThreadManager.sleep(millis, nanos);
0381: if (status == VMThreadManager.TM_ERROR_INTERRUPT) {
0382: throw new InterruptedException();
0383: } else if (status != VMThreadManager.TM_ERROR_NONE) {
0384: throw new InternalError("Thread Manager internal error "
0385: + status);
0386: }
0387: }
0388:
0389: /**
0390: * @com.intel.drl.spec_ref
0391: */
0392: public static void yield() {
0393: int status = VMThreadManager.yield();
0394: if (status != VMThreadManager.TM_ERROR_NONE) {
0395: throw new InternalError("Thread Manager internal error "
0396: + status);
0397: }
0398: }
0399:
0400: /**
0401: * @com.intel.drl.spec_ref
0402: */
0403: public final void checkAccess() {
0404: SecurityManager securityManager = System.getSecurityManager();
0405: if (securityManager != null) {
0406: securityManager.checkAccess(this );
0407: }
0408: }
0409:
0410: /**
0411: * @com.intel.drl.spec_ref
0412: * @deprecated
0413: */
0414: public int countStackFrames() {
0415: return 0; //deprecated
0416: }
0417:
0418: /**
0419: * @com.intel.drl.spec_ref
0420: * @deprecated
0421: */
0422: public void destroy() {
0423: // this method is not implemented
0424: throw new NoSuchMethodError();
0425: }
0426:
0427: /**
0428: * @com.intel.drl.spec_ref
0429: */
0430: public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
0431: SecurityManager securityManager = System.getSecurityManager();
0432: if (securityManager != null) {
0433: securityManager
0434: .checkPermission(RuntimePermissionCollection.GET_STACK_TRACE_PERMISSION);
0435: securityManager
0436: .checkPermission(RuntimePermissionCollection.MODIFY_THREAD_GROUP_PERMISSION);
0437: }
0438:
0439: // find the initial ThreadGroup in the tree
0440: ThreadGroup parent = new ThreadGroup(currentThread()
0441: .getThreadGroup(), "Temporary");
0442: ThreadGroup newParent = parent.getParent();
0443: parent.destroy();
0444: while (newParent != null) {
0445: parent = newParent;
0446: newParent = parent.getParent();
0447: }
0448: int threadsCount = parent.activeCount() + 1;
0449: int count;
0450: Thread[] liveThreads;
0451: while (true) {
0452: liveThreads = new Thread[threadsCount];
0453: count = parent.enumerate(liveThreads);
0454: if (count == threadsCount) {
0455: threadsCount *= 2;
0456: } else {
0457: break;
0458: }
0459: }
0460: Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>(
0461: count + 1);
0462: for (int i = 0; i < count; i++) {
0463: StackTraceElement[] ste = liveThreads[i].getStackTrace();
0464: if (ste.length != 0) {
0465: map.put(liveThreads[i], ste);
0466: }
0467: }
0468: return map;
0469: }
0470:
0471: /**
0472: * @com.intel.drl.spec_ref
0473: */
0474: public ClassLoader getContextClassLoader() {
0475: synchronized (lock) {
0476: // First, if the conditions
0477: // 1) there is a security manager
0478: // 2) the caller's class loader is not null
0479: // 3) the caller's class loader is not the same as or an
0480: // ancestor of contextClassLoader
0481: // are satisfied we should perform a security check.
0482: SecurityManager securityManager = System
0483: .getSecurityManager();
0484: if (securityManager != null) {
0485: //the first condition is satisfied
0486: ClassLoader callerClassLoader = VMClassRegistry
0487: .getClassLoader(VMStack.getCallerClass(0));
0488: if (callerClassLoader != null) {
0489: //the second condition is satisfied
0490: ClassLoader classLoader = contextClassLoader;
0491: while (classLoader != null) {
0492: if (classLoader == callerClassLoader) {
0493: //the third condition is not satisfied
0494: return contextClassLoader;
0495: }
0496: classLoader = classLoader.getParent();
0497: }
0498: //the third condition is satisfied
0499: securityManager
0500: .checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
0501: }
0502: }
0503: return contextClassLoader;
0504: }
0505: }
0506:
0507: /**
0508: * @com.intel.drl.spec_ref
0509: */
0510: public final String getName() {
0511: return name;
0512: }
0513:
0514: /**
0515: * @com.intel.drl.spec_ref
0516: */
0517: public final int getPriority() {
0518: return priority;
0519: }
0520:
0521: /**
0522: * @com.intel.drl.spec_ref
0523: */
0524: public StackTraceElement[] getStackTrace() {
0525: if (currentThread() != this ) {
0526: SecurityManager securityManager = System
0527: .getSecurityManager();
0528: if (securityManager != null) {
0529: securityManager
0530: .checkPermission(RuntimePermissionCollection.GET_STACK_TRACE_PERMISSION);
0531: }
0532: }
0533: StackTraceElement ste[] = VMStack.getThreadStackTrace(this );
0534: return ste != null ? ste : new StackTraceElement[0];
0535: }
0536:
0537: /**
0538: * @com.intel.drl.spec_ref
0539: */
0540: public final ThreadGroup getThreadGroup() {
0541: return group;
0542: }
0543:
0544: /**
0545: * @com.intel.drl.spec_ref
0546: */
0547: public long getId() {
0548: return threadId;
0549: }
0550:
0551: /**
0552: * @com.intel.drl.spec_ref
0553: */
0554: public void interrupt() {
0555: synchronized (lock) {
0556: checkAccess();
0557: int status = VMThreadManager.interrupt(this );
0558: if (status != VMThreadManager.TM_ERROR_NONE) {
0559: throw new InternalError(
0560: "Thread Manager internal error " + status);
0561: }
0562: }
0563: }
0564:
0565: /**
0566: * @com.intel.drl.spec_ref
0567: */
0568: public final boolean isAlive() {
0569: synchronized (lock) {
0570: return this .isAlive;
0571: }
0572: }
0573:
0574: /**
0575: * @com.intel.drl.spec_ref
0576: */
0577: public final boolean isDaemon() {
0578: return daemon;
0579: }
0580:
0581: /**
0582: * @com.intel.drl.spec_ref
0583: */
0584: public boolean isInterrupted() {
0585: return VMThreadManager.isInterrupted(this );
0586: }
0587:
0588: /**
0589: * @com.intel.drl.spec_ref
0590: */
0591: public final synchronized void join() throws InterruptedException {
0592: while (isAlive()) {
0593: wait();
0594: }
0595: }
0596:
0597: /**
0598: * @com.intel.drl.spec_ref
0599: */
0600: public final synchronized void join(long millis)
0601: throws InterruptedException {
0602: if (millis == 0) {
0603: join();
0604: } else {
0605: long end = System.currentTimeMillis() + millis;
0606: while (isAlive()) {
0607: wait(millis);
0608: millis = end - System.currentTimeMillis();
0609: if (millis <= 0) {
0610: break;
0611: }
0612: }
0613: }
0614: }
0615:
0616: /**
0617: * @com.intel.drl.spec_ref
0618: */
0619: public final synchronized void join(long millis, int nanos)
0620: throws InterruptedException {
0621: if (millis < 0 || nanos < 0 || nanos > 999999) {
0622: throw new IllegalArgumentException();
0623: } else if (millis == 0 && nanos == 0) {
0624: join();
0625: } else {
0626: long end = System.nanoTime() + 1000000 * millis
0627: + (long) nanos;
0628: long rest;
0629: while (isAlive()) {
0630: wait(millis, nanos);
0631: rest = end - System.nanoTime();
0632: if (rest <= 0)
0633: break;
0634: nanos = (int) (rest % 1000000);
0635: millis = rest / 1000000;
0636: }
0637: }
0638: }
0639:
0640: /**
0641: * Note that this is unsnchronized - the assumption is that
0642: * hythread does the synchronization for us
0643: *
0644: * @com.intel.drl.spec_ref
0645: * @deprecated
0646: */
0647: public final void resume() {
0648: checkAccess();
0649: int status = VMThreadManager.resume(this );
0650: if (status != VMThreadManager.TM_ERROR_NONE) {
0651: throw new InternalError("Thread Manager internal error "
0652: + status);
0653: }
0654: }
0655:
0656: /**
0657: * @com.intel.drl.spec_ref
0658: */
0659: public void run() {
0660: if (target != null) {
0661: target.run();
0662: }
0663: }
0664:
0665: void runImpl() {
0666: synchronized (lock) {
0667: this .isAlive = true;
0668: this .started = true;
0669: lock.notifyAll();
0670: }
0671:
0672: run();
0673: }
0674:
0675: /**
0676: * @com.intel.drl.spec_ref
0677: */
0678: public void setContextClassLoader(ClassLoader classLoader) {
0679: synchronized (lock) {
0680: SecurityManager securityManager = System
0681: .getSecurityManager();
0682: if (securityManager != null) {
0683: securityManager
0684: .checkPermission(RuntimePermissionCollection.SET_CONTEXT_CLASS_LOADER_PERMISSION);
0685: }
0686: contextClassLoader = classLoader;
0687: }
0688: }
0689:
0690: /**
0691: * @com.intel.drl.spec_ref We assume that 'active thread' means the same as
0692: * 'alive thread'.
0693: */
0694: public final void setDaemon(boolean daemon) {
0695: synchronized (lock) {
0696: checkAccess();
0697: if (isAlive()) {
0698: throw new IllegalThreadStateException();
0699: }
0700: this .daemon = daemon;
0701: }
0702: }
0703:
0704: /**
0705: * @com.intel.drl.spec_ref New name should not be <code>null</code>.
0706: * @throws NullPointerException if new name is <code>null</code>
0707: */
0708: public final void setName(String name) {
0709: checkAccess();
0710: // throws NullPointerException if the given name is null
0711: this .name = name.toString();
0712: }
0713:
0714: /**
0715: * @com.intel.drl.spec_ref
0716: */
0717: public final void setPriority(int priority) {
0718: checkAccess();
0719: if (priority > MAX_PRIORITY || priority < MIN_PRIORITY) {
0720: throw new IllegalArgumentException(
0721: "Wrong Thread priority value");
0722: }
0723: ThreadGroup threadGroup = group;
0724: this .priority = (priority > threadGroup.maxPriority) ? threadGroup.maxPriority
0725: : priority;
0726: int status = VMThreadManager.setPriority(this , this .priority);
0727: if (status != VMThreadManager.TM_ERROR_NONE) {
0728: //throw new InternalError("Thread Manager internal error " + status);
0729: }
0730: }
0731:
0732: /**
0733: * @com.intel.drl.spec_ref
0734: */
0735: public synchronized void start() {
0736: synchronized (lock) {
0737: if (started) {
0738: //this thread was started
0739: throw new IllegalThreadStateException(
0740: "This thread was already started!");
0741: }
0742:
0743: // adding the thread to the thread group
0744: group.add(this );
0745:
0746: if (VMThreadManager
0747: .start(this , stackSize, daemon, priority) != 0) {
0748: throw new OutOfMemoryError(
0749: "Failed to create new thread");
0750: }
0751:
0752: // wjw -- why are we *waiting* for a child thread to actually start running?
0753: // this *guarantees* two context switches
0754: // nothing in j.l.Thread spec says we have to do this
0755: // my guess is that this actually masks an underlying race condition that we need to fix.
0756:
0757: boolean interrupted = false;
0758: while (!this .started) {
0759: try {
0760: lock.wait();
0761: } catch (InterruptedException e) {
0762: interrupted = true;
0763: }
0764: }
0765:
0766: if (interrupted) {
0767: Thread.currentThread().interrupt();
0768: }
0769: }
0770: }
0771:
0772: /**
0773: * Performs premortal actions. First it processes uncaught exception if any.
0774: * Second removes current thread from its thread group.
0775: * VM calls this method when current thread is detaching from VM.
0776: *
0777: * @param uncaughtException uncaught exception or null
0778: */
0779: void detach(Throwable uncaughtException) {
0780: try {
0781: if (uncaughtException != null) {
0782: getUncaughtExceptionHandler().uncaughtException(this ,
0783: uncaughtException);
0784: }
0785: } finally {
0786: group.remove(this );
0787: synchronized (this ) {
0788: isAlive = false;
0789: notifyAll();
0790: }
0791: }
0792: }
0793:
0794: public enum State {
0795: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
0796: }
0797:
0798: /**
0799: * @com.intel.drl.spec_ref
0800: */
0801: public Thread.State getState() {
0802:
0803: boolean dead = false;
0804: synchronized (lock) {
0805: if (started && !isAlive())
0806: dead = true;
0807: }
0808: if (dead)
0809: return State.TERMINATED;
0810:
0811: int state = (VMThreadManager.getState(this ));
0812:
0813: if (0 != (state & VMThreadManager.TM_THREAD_STATE_TERMINATED)) {
0814: return State.TERMINATED;
0815: } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_WAITING_WITH_TIMEOUT)) {
0816: return State.TIMED_WAITING;
0817: } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_WAITING)
0818: || 0 != (state & VMThreadManager.TM_THREAD_STATE_PARKED)) {
0819: return State.WAITING;
0820: } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER)) {
0821: return State.BLOCKED;
0822:
0823: } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_RUNNABLE)) {
0824: return State.RUNNABLE;
0825:
0826: //TODO track down all situations where a thread is really in RUNNABLE state
0827: // but TM_THREAD_STATE_RUNNABLE is not set. In the meantime, leave the following
0828: // TM_THREAD_STATE_ALIVE test as it is.
0829: } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_ALIVE)) {
0830: return State.RUNNABLE;
0831: } else {
0832: return State.NEW; // by deduction, if its none of the above
0833: }
0834: }
0835:
0836: /**
0837: * @com.intel.drl.spec_ref
0838: * @deprecated
0839: */
0840: public final void stop() {
0841: synchronized (lock) {
0842: if (isAlive()) {
0843: stop(new ThreadDeath());
0844: }
0845: }
0846: }
0847:
0848: /**
0849: * @com.intel.drl.spec_ref
0850: * @deprecated
0851: */
0852: public final void stop(Throwable throwable) {
0853: SecurityManager securityManager = System.getSecurityManager();
0854: if (securityManager != null) {
0855: securityManager.checkAccess(this );
0856: if (currentThread() != this
0857: || !(throwable instanceof ThreadDeath)) {
0858: securityManager
0859: .checkPermission(RuntimePermissionCollection.STOP_THREAD_PERMISSION);
0860: }
0861: }
0862: if (throwable == null) {
0863: throw new NullPointerException("The argument is null!");
0864: }
0865: synchronized (lock) {
0866: if (isAlive()) {
0867: int status = VMThreadManager.stop(this , throwable);
0868: if (status != VMThreadManager.TM_ERROR_NONE) {
0869: throw new InternalError(
0870: "Thread Manager internal error " + status);
0871: }
0872: }
0873: }
0874: }
0875:
0876: /**
0877: * Note that this is unsnchronized - the assumption is that
0878: * hythread does the synchronization for us
0879: *
0880: * @com.intel.drl.spec_ref
0881: * @deprecated
0882: */
0883: public final void suspend() {
0884: checkAccess();
0885:
0886: int status = VMThreadManager.suspend(this );
0887: if (status != VMThreadManager.TM_ERROR_NONE) {
0888: throw new InternalError("Thread Manager internal error "
0889: + status);
0890: }
0891: }
0892:
0893: /**
0894: * @com.intel.drl.spec_ref
0895: */
0896: public String toString() {
0897: ThreadGroup threadGroup = group;
0898: return "Thread[" + name + "," + priority + ","
0899: + ((threadGroup == null) ? "" : threadGroup.name) + "]";
0900: }
0901:
0902: /**
0903: * @com.intel.drl.spec_ref
0904: */
0905: public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
0906: return defaultExceptionHandler;
0907: }
0908:
0909: /**
0910: * @com.intel.drl.spec_ref
0911: */
0912: public static void setDefaultUncaughtExceptionHandler(
0913: UncaughtExceptionHandler eh) {
0914: SecurityManager sm = System.getSecurityManager();
0915: if (sm != null) {
0916: sm
0917: .checkPermission(RuntimePermissionCollection.SET_DEFAULT_UNCAUGHT_EXCEPTION_HANDLER_PERMISSION);
0918: }
0919: defaultExceptionHandler = eh;
0920: }
0921:
0922: /**
0923: * @com.intel.drl.spec_ref
0924: */
0925: public UncaughtExceptionHandler getUncaughtExceptionHandler() {
0926: if (exceptionHandler != null) {
0927: return exceptionHandler;
0928: }
0929: return getThreadGroup();
0930: }
0931:
0932: /**
0933: * @com.intel.drl.spec_ref
0934: */
0935: public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
0936: SecurityManager sm = System.getSecurityManager();
0937: if (sm != null) {
0938: sm
0939: .checkPermission(RuntimePermissionCollection.MODIFY_THREAD_PERMISSION);
0940: }
0941: exceptionHandler = eh;
0942: }
0943:
0944: /**
0945: * Associates the value specified to the <code>ThreadLocal</code> object
0946: * given. <br>
0947: * This nethod is designed to provide <code>ThreadLocal</code>
0948: * functionality.
0949: */
0950: void setThreadLocal(ThreadLocal<Object> local, Object value) {
0951: if (localValues == null) {
0952: localValues = new IdentityHashMap<ThreadLocal<Object>, Object>();
0953: }
0954: localValues.put(local, value);
0955: }
0956:
0957: /**
0958: * Returns the value associated with the <code>ThreadLocal</code> object
0959: * specified. If no value is associated, returns the value produced by
0960: * <code>initialValue()</code> method called for this object and
0961: * associates this value to <code>ThreadLocal</code> object. <br>
0962: * This nethod is designed to provide <code>ThreadLocal</code>
0963: * functionality.
0964: */
0965: Object getThreadLocal(ThreadLocal<Object> local) {
0966: Object value;
0967: if (localValues == null) {
0968: localValues = new IdentityHashMap<ThreadLocal<Object>, Object>();
0969: value = local.initialValue();
0970: localValues.put(local, value);
0971: return value;
0972: }
0973: if (localValues.containsKey(local)) {
0974: return localValues.get(local);
0975: }
0976: value = local.initialValue();
0977: localValues.put(local, value);
0978: return value;
0979: }
0980:
0981: /**
0982: * Removes the association (if any) between the <code>ThreadLocal</code> object
0983: * given and this thread's value. <br>
0984: * This nethod is designed to provide <code>ThreadLocal</code>
0985: * functionality.
0986: */
0987: void removeLocalValue(ThreadLocal<Object> local) {
0988: if (localValues != null) {
0989: localValues.remove(local);
0990: }
0991: }
0992:
0993: /**
0994: * Initializes local values represented by
0995: * <code>InheritableThreadLocal</code> objects having local values for the
0996: * parent thread <br>
0997: * This method is designed to provide the functionality of
0998: * <code>InheritableThreadLocal</code> class <br>
0999: * This method should be called from <code>Thread</code>'s constructor.
1000: */
1001: private void initializeInheritableLocalValues(Thread parent) {
1002: Map<ThreadLocal<Object>, Object> parentLocalValues = parent.localValues;
1003: if (parentLocalValues == null) {
1004: return;
1005: }
1006: localValues = new IdentityHashMap<ThreadLocal<Object>, Object>(
1007: parentLocalValues.size());
1008: for (Iterator<ThreadLocal<Object>> it = parentLocalValues
1009: .keySet().iterator(); it.hasNext();) {
1010: ThreadLocal<Object> local = it.next();
1011: if (local instanceof InheritableThreadLocal) {
1012: Object parentValue = parentLocalValues.get(local);
1013: InheritableThreadLocal<Object> iLocal = (InheritableThreadLocal<Object>) local;
1014: localValues.put(local, iLocal.childValue(parentValue));
1015: }
1016: }
1017: }
1018:
1019: /**
1020: * generates a unique thread ID
1021: */
1022: private static synchronized long getNextThreadId() {
1023: return ++threadOrdinalNum;
1024: }
1025:
1026: /*
1027: * Checks if more then GC_WATERMARK_MAX_COUNT threads was created and calls
1028: * System.gc() to ensure that dead thread references was collected.
1029: */
1030: private void checkGCWatermark() {
1031: if (++currentGCWatermarkCount % GC_WATERMARK_MAX_COUNT == 0) {
1032: System.gc();
1033: }
1034: }
1035:
1036: /**
1037: * @com.intel.drl.spec_ref
1038: */
1039: public static interface UncaughtExceptionHandler {
1040:
1041: /**
1042: * @com.intel.drl.spec_ref
1043: */
1044: void uncaughtException(Thread t, Throwable e);
1045: }
1046: }
|