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 #include "atomic.h" 18 #include "gc/accounting/card_table-inl.h" 19 #include "jni_internal.h" 20 #include "mirror/object.h" 21 #include "mirror/object-inl.h" 22 #include "scoped_thread_state_change.h" 23 24 namespace art { 25 26 static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) { 27 ScopedObjectAccess soa(env); 28 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 29 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; 30 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr); 31 // Note: android_atomic_release_cas() returns 0 on success, not failure. 32 int result = android_atomic_release_cas(expectedValue, newValue, address); 33 return (result == 0) ? JNI_TRUE : JNI_FALSE; 34 } 35 36 static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) { 37 ScopedObjectAccess soa(env); 38 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 39 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; 40 volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr); 41 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 42 bool success = QuasiAtomic::Cas64(expectedValue, newValue, address); 43 return success ? JNI_TRUE : JNI_FALSE; 44 } 45 46 static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) { 47 ScopedObjectAccess soa(env); 48 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 49 mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue); 50 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); 51 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; 52 int32_t* address = reinterpret_cast<int32_t*>(raw_addr); 53 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 54 int result = android_atomic_release_cas(reinterpret_cast<int32_t>(expectedValue), 55 reinterpret_cast<int32_t>(newValue), address); 56 if (result == 0) { 57 Runtime::Current()->GetHeap()->WriteBarrierField(obj, MemberOffset(offset), newValue); 58 } 59 return (result == 0) ? JNI_TRUE : JNI_FALSE; 60 } 61 62 static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) { 63 ScopedObjectAccess soa(env); 64 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 65 return obj->GetField32(MemberOffset(offset), false); 66 } 67 68 static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { 69 ScopedObjectAccess soa(env); 70 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 71 return obj->GetField32(MemberOffset(offset), true); 72 } 73 74 static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { 75 ScopedObjectAccess soa(env); 76 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 77 obj->SetField32(MemberOffset(offset), newValue, false); 78 } 79 80 static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { 81 ScopedObjectAccess soa(env); 82 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 83 obj->SetField32(MemberOffset(offset), newValue, true); 84 } 85 86 static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { 87 ScopedObjectAccess soa(env); 88 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 89 ANDROID_MEMBAR_STORE(); 90 obj->SetField32(MemberOffset(offset), newValue, false); 91 } 92 93 static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) { 94 ScopedObjectAccess soa(env); 95 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 96 return obj->GetField64(MemberOffset(offset), false); 97 } 98 99 static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { 100 ScopedObjectAccess soa(env); 101 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 102 return obj->GetField64(MemberOffset(offset), true); 103 } 104 105 static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { 106 ScopedObjectAccess soa(env); 107 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 108 obj->SetField64(MemberOffset(offset), newValue, false); 109 } 110 111 static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { 112 ScopedObjectAccess soa(env); 113 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 114 obj->SetField64(MemberOffset(offset), newValue, true); 115 } 116 117 static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { 118 ScopedObjectAccess soa(env); 119 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 120 ANDROID_MEMBAR_STORE(); 121 obj->SetField64(MemberOffset(offset), newValue, false); 122 } 123 124 static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { 125 ScopedObjectAccess soa(env); 126 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 127 mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true); 128 return soa.AddLocalReference<jobject>(value); 129 } 130 131 static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) { 132 ScopedObjectAccess soa(env); 133 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 134 mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false); 135 return soa.AddLocalReference<jobject>(value); 136 } 137 138 static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { 139 ScopedObjectAccess soa(env); 140 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 141 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); 142 obj->SetFieldObject(MemberOffset(offset), newValue, false); 143 } 144 145 static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { 146 ScopedObjectAccess soa(env); 147 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 148 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); 149 obj->SetFieldObject(MemberOffset(offset), newValue, true); 150 } 151 152 static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { 153 ScopedObjectAccess soa(env); 154 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); 155 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); 156 ANDROID_MEMBAR_STORE(); 157 obj->SetFieldObject(MemberOffset(offset), newValue, false); 158 } 159 160 static JNINativeMethod gMethods[] = { 161 NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"), 162 NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"), 163 NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"), 164 NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"), 165 NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"), 166 NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"), 167 NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"), 168 NATIVE_METHOD(Unsafe, getObjectVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"), 169 NATIVE_METHOD(Unsafe, putObjectVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"), 170 NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"), 171 NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"), 172 NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"), 173 NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"), 174 NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"), 175 NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"), 176 NATIVE_METHOD(Unsafe, getObject, "(Ljava/lang/Object;J)Ljava/lang/Object;"), 177 NATIVE_METHOD(Unsafe, putObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"), 178 NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"), 179 }; 180 181 void register_sun_misc_Unsafe(JNIEnv* env) { 182 REGISTER_NATIVE_METHODS("sun/misc/Unsafe"); 183 } 184 185 } // namespace art 186