blob: 90359abe99b2a01e7cfd8c6b181e1e1d57a9cb5c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#include <apr_atomic.h>
#include "jni.h"
#include "Class.h"
#include "object_handles.h"
#include "environment.h"
#include "atomics.h"
#include "vm_arrays.h"
#include "port_atomic.h"
/*
* Common atomic functions.
* Platform dependent atomic functions are in corresponding arch/ subfolders.
*/
#ifndef REFS_USE_UNCOMPRESSED
bool gc_heap_slot_cas_ref_compressed (Managed_Object_Handle p_base_of_object_with_slot,
COMPRESSED_REFERENCE *p_slot,
Managed_Object_Handle expected,
Managed_Object_Handle value)
{
assert (p_base_of_object_with_slot != NULL);
COMPRESSED_REFERENCE compressed_expected = compress_reference((ManagedObject*)expected);
COMPRESSED_REFERENCE compressed_value = compress_reference((ManagedObject*)value);
bool result =
(apr_atomic_cas32(
(U_32*)p_slot, (U_32)compressed_value, (U_32)compressed_expected)
== (U_32)compressed_expected);
// TODO: uncomment foolowing line for GC
//INTERNAL(gc_write_barrier) (p_base_of_object_with_slot);
return result;
}
#endif // REFS_USE_UNCOMPRESSED
#ifndef REFS_USE_COMPRESSED
bool gc_heap_slot_cas_ref (Managed_Object_Handle p_base_of_object_with_slot,
Managed_Object_Handle *p_slot,
Managed_Object_Handle expected,
Managed_Object_Handle value)
{
assert (p_base_of_object_with_slot != NULL);
bool res = (apr_atomic_casptr (
(volatile void **)p_slot, value, expected) == expected);
// TODO: uncomment foolowing line for GC
//INTERNAL(gc_write_barrier) (p_base_of_object_with_slot);
return res;
}
#endif // REFS_USE_COMPRESSED
JNIEXPORT jlong getFieldOffset(JNIEnv * env, jobject field)
{
Field *f = (Field *) FromReflectedField(env, field);
return f->get_offset();
}
JNIEXPORT jboolean compareAndSetObjectField
(JNIEnv * env, jobject UNREF accesor, jobject obj, jlong offset, jobject expected, jobject value)
{
assert(hythread_is_suspend_enabled());
ObjectHandle h = (ObjectHandle)obj;
ObjectHandle v = (ObjectHandle)value;
ObjectHandle e = (ObjectHandle)expected;
tmn_suspend_disable();
U_8* java_ref = (U_8*)h->object;
ManagedObject** field_addr = (ManagedObject**)(java_ref + offset);
ManagedObject* val = (v==NULL)?NULL:v->object;
ManagedObject* exp = (e==NULL)?NULL:e->object;
bool result;
REFS_RUNTIME_SWITCH_IF
#ifdef REFS_RUNTIME_OR_COMPRESSED
result = gc_heap_slot_cas_ref_compressed((Managed_Object_Handle)(java_ref),
(COMPRESSED_REFERENCE *)(field_addr),
(Managed_Object_Handle)(exp),
(Managed_Object_Handle)(val));
#endif // REFS_RUNTIME_OR_COMPRESSED
REFS_RUNTIME_SWITCH_ELSE
#ifdef REFS_RUNTIME_OR_UNCOMPRESSED
result = gc_heap_slot_cas_ref((Managed_Object_Handle)(java_ref),
(Managed_Object_Handle *)(field_addr),
(Managed_Object_Handle)(exp),
(Managed_Object_Handle)(val));
#endif // REFS_RUNTIME_OR_UNCOMPRESSED
REFS_RUNTIME_SWITCH_ENDIF
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetBooleanField
(JNIEnv * env, jobject UNREF accesor, jobject obj, jlong offset, jboolean expected, jboolean value)
{
assert(hythread_is_suspend_enabled());
ObjectHandle h = (ObjectHandle)obj;
tmn_suspend_disable();
U_8* java_ref = (U_8*)h->object;
jboolean* field_addr = (jboolean*)(java_ref + offset);
bool result =
(port_atomic_cas8((U_8*)field_addr, (U_8)value, (U_8)expected) == (U_8)expected);
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetIntField
(JNIEnv * env, jobject UNREF accesor, jobject obj, jlong offset, jint expected, jint value)
{
assert(hythread_is_suspend_enabled());
ObjectHandle h = (ObjectHandle)obj;
tmn_suspend_disable();
U_8* java_ref = (U_8*)h->object;
jint* field_addr = (jint*)(java_ref + offset);
bool result =
(apr_atomic_cas32((U_32*)field_addr, (U_32)value, (U_32)expected) == (U_32)expected);
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetLongField
(JNIEnv * env, jobject UNREF accesor, jobject obj, jlong offset, jlong expected, jlong value)
{
assert(hythread_is_suspend_enabled());
ObjectHandle h = (ObjectHandle)obj;
tmn_suspend_disable();
U_8* java_ref = (U_8*)h->object;
jlong* field_addr = (jlong*)(java_ref + offset);
bool result =
(port_atomic_cas64((uint64*)field_addr, (uint64)value, (uint64)expected) == (uint64)expected);
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetObjectArray
(JNIEnv * UNREF env, jobject UNREF self, jobjectArray array, jint index, jobject expected, jobject value)
{
assert(hythread_is_suspend_enabled());
tmn_suspend_disable();
Vector_Handle vector_handle = (Vector_Handle) ((ObjectHandle) array)->object;
ManagedObject ** element_address =
get_vector_element_address_ref(vector_handle, index);
ManagedObject *exp = (expected==NULL) ? NULL : ((ObjectHandle) expected)->object;
ManagedObject *val = (value==NULL) ? NULL : ((ObjectHandle) value)->object;
bool result;
REFS_RUNTIME_SWITCH_IF
#ifdef REFS_RUNTIME_OR_COMPRESSED
result = gc_heap_slot_cas_ref_compressed((Managed_Object_Handle)(vector_handle),
(COMPRESSED_REFERENCE *)(element_address),
(Managed_Object_Handle)(exp),
(Managed_Object_Handle)(val));
#endif // REFS_RUNTIME_OR_COMPRESSED
REFS_RUNTIME_SWITCH_ELSE
#ifdef REFS_RUNTIME_OR_UNCOMPRESSED
result = gc_heap_slot_cas_ref((Managed_Object_Handle)(vector_handle),
(Managed_Object_Handle *)(element_address),
(Managed_Object_Handle)(exp),
(Managed_Object_Handle)(val));
#endif // REFS_RUNTIME_OR_UNCOMPRESSED
REFS_RUNTIME_SWITCH_ENDIF
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetBooleanArray
(JNIEnv * UNREF env, jobject UNREF self, jbooleanArray array, jint index, jboolean expected, jboolean value)
{
assert(hythread_is_suspend_enabled());
tmn_suspend_disable();
jboolean * field_addr = (jboolean *) get_vector_element_address_int8(
(Vector_Handle) ((ObjectHandle) array)->object,
index);
bool result =
(port_atomic_cas8((U_8 *)field_addr, (U_8)value, (U_8)expected) == (U_8)expected);
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetIntArray
(JNIEnv * UNREF env, jobject UNREF self, jintArray array, jint index, jint expected, jint value)
{
assert(hythread_is_suspend_enabled());
tmn_suspend_disable();
jint * field_addr = get_vector_element_address_int32(
(Vector_Handle) ((ObjectHandle) array)->object,
index);
bool result =
(apr_atomic_cas32((U_32 *)field_addr, (U_32)value, (U_32)expected) == (U_32)expected);
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean compareAndSetLongArray
(JNIEnv * UNREF env, jobject UNREF self, jlongArray array, jint index, jlong expected, jlong value)
{
assert(hythread_is_suspend_enabled());
tmn_suspend_disable();
jlong * field_addr = get_vector_element_address_int64(
(Vector_Handle) ((ObjectHandle) array)->object,
index);
bool result =
(port_atomic_cas64((uint64 *)field_addr, (uint64)value, (uint64)expected) == (uint64)expected);
tmn_suspend_enable();
return (jboolean)(result?JNI_TRUE:JNI_FALSE);
}
JNIEXPORT jboolean vmSupportsCAS8() {
return JNI_TRUE;
}