001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.drlvm.thread;
019:
020: import org.apache.harmony.drlvm.VMHelper;
021: import org.vmmagic.unboxed.*;
022: import org.vmmagic.pragma.*;
023:
024: public class ThreadHelper {
025:
026: public static final int THREAD_SHIFT = 16;
027: public static final int RECURSION_BOUND_IN_PLACE = 0xf400;
028: public static final int HI_BITS = 0xffff0000;
029: public static final int RECURSION_INC_IN_PLACE = 0x800;
030: public static final int ZEROED_BITS_FOR_INITIAL_LOCK = 0xffff0400;
031:
032: public static final int LOCK_WORD_OFFSET = getLockWordOffset();
033: public static final int TLS_THREAD_ID_OFFSET = getThreadIdOffset();
034: public static final int THREAD_JAVA_OBJECT_OFFSET = getThreadJavaObjectOffset();
035:
036: @Inline
037: static int getThreadId() {
038: Address tlsAddr = VMHelper.getTlsBaseAddress();
039: Address tlsThreadIdFieldAddr = tlsAddr
040: .plus(TLS_THREAD_ID_OFFSET);
041: return tlsThreadIdFieldAddr.loadInt();
042: }
043:
044: @Inline
045: public static Thread getCurrentThread() {
046: Address tlsThread = VMHelper.getTlsBaseAddress();
047: Address javaObjectPtr = tlsThread.plus(
048: THREAD_JAVA_OBJECT_OFFSET).loadAddress();
049: if (javaObjectPtr.isZero()) {
050: return null;
051: } else {
052: return (Thread) javaObjectPtr.loadAddress()
053: .toObjectReference().toObject();
054: }
055: }
056:
057: @Inline
058: static void monitorEnterUseReservation(Object obj) {
059: Address lockWordPtr = ObjectReference.fromObject(obj)
060: .toAddress().plus(LOCK_WORD_OFFSET);
061: int threadId = getThreadId();
062: int lockword = lockWordPtr.loadInt();
063: int new_lockword = (threadId << THREAD_SHIFT) ^ lockword;
064:
065: if ((new_lockword & HI_BITS) == 0) {
066: // comparison above is some kind of tricky, two things are checked at once;
067: // if we got zero it means that there is NO fat lock here, and thread_id stored in lockword
068: // is the same as current thread_id
069:
070: if (new_lockword <= RECURSION_BOUND_IN_PLACE) {
071: //This is the most frequent path.
072: //lockword updated without atomic operation.
073: //this path works for reservation locks (already reserved) and thin locks if the lock
074: //was already captured by this thread.
075: lockword += RECURSION_INC_IN_PLACE;
076: lockWordPtr.store(lockword);
077: return;
078: }
079: } else {
080: // available possibilities here:
081: // 1. fat lock - 0x80000000 is set to 1 ; need goto slow path
082: // 2. captured thin lock for another thread ; need goto slow path
083: // 3. reserved lock for another thread. ; need goto slow path
084: // 4. non-locked thin lock.
085: // 5. The first lock for the object.
086: if ((lockword & ZEROED_BITS_FOR_INITIAL_LOCK) == 0) {
087: // no locks was here. Reserve it.
088: new_lockword += RECURSION_INC_IN_PLACE;
089: if (lockWordPtr.attempt(lockword, new_lockword)) {
090: return;
091: }
092: } else {
093: if ((lockword & HI_BITS) == 0) {
094: if (lockWordPtr.attempt(lockword, new_lockword)) {
095: return;
096: }
097: }
098: }
099: }
100: VMHelper.monitorEnter(obj);
101: }
102:
103: public static final int FAT_LOCK_MASK = 0x80000000;
104: public static final int RECURSION_MASK = 0x0000f800;
105:
106: @Inline
107: static void monitorExit(Object obj) {
108: Address lockWordPtr = ObjectReference.fromObject(obj)
109: .toAddress().plus(LOCK_WORD_OFFSET);
110: int lockword = lockWordPtr.loadInt();
111: if (((lockword & (FAT_LOCK_MASK | RECURSION_MASK))) != 0) {
112: if ((lockword & FAT_LOCK_MASK) == 0) {
113: lockword -= RECURSION_INC_IN_PLACE;
114: lockWordPtr.store(lockword);
115: return;
116: }
117: } else {
118: lockword &= ~HI_BITS;
119: lockWordPtr.store(lockword);
120: return;
121: }
122: VMHelper.monitorExit(obj);
123: }
124:
125: private static native int getThreadIdOffset();
126:
127: private static native int getLockWordOffset();
128:
129: private static native int getThreadJavaObjectOffset();
130: }
|