mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-26 00:39:03 +00:00
Initial open source release of OpenCL 2.2 CTS.
This commit is contained in:
250
test_conformance/c11_atomics/host_atomics.h
Normal file
250
test_conformance/c11_atomics/host_atomics.h
Normal file
@@ -0,0 +1,250 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed 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.
|
||||
//
|
||||
#ifndef _HOST_ATOMICS_H_
|
||||
#define _HOST_ATOMICS_H_
|
||||
|
||||
#include "../../test_common/harness/testHarness.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "Windows.h"
|
||||
#endif
|
||||
|
||||
//flag for test verification (good test should discover non-atomic functions and fail)
|
||||
//#define NON_ATOMIC_FUNCTIONS
|
||||
|
||||
enum TExplicitMemoryOrderType
|
||||
{
|
||||
MEMORY_ORDER_EMPTY,
|
||||
MEMORY_ORDER_RELAXED,
|
||||
MEMORY_ORDER_ACQUIRE,
|
||||
MEMORY_ORDER_RELEASE,
|
||||
MEMORY_ORDER_ACQ_REL,
|
||||
MEMORY_ORDER_SEQ_CST
|
||||
};
|
||||
|
||||
// host atomic types (applicable for atomic functions supported on host OS)
|
||||
#ifdef WIN32
|
||||
#define HOST_ATOMIC_INT unsigned long
|
||||
#define HOST_ATOMIC_UINT unsigned long
|
||||
#define HOST_ATOMIC_LONG unsigned long long
|
||||
#define HOST_ATOMIC_ULONG unsigned long long
|
||||
#define HOST_ATOMIC_FLOAT float
|
||||
#define HOST_ATOMIC_DOUBLE double
|
||||
#else
|
||||
#define HOST_ATOMIC_INT cl_int
|
||||
#define HOST_ATOMIC_UINT cl_uint
|
||||
#define HOST_ATOMIC_LONG cl_long
|
||||
#define HOST_ATOMIC_ULONG cl_ulong
|
||||
#define HOST_ATOMIC_FLOAT cl_float
|
||||
#define HOST_ATOMIC_DOUBLE cl_double
|
||||
#endif
|
||||
|
||||
#define HOST_ATOMIC_INTPTR_T32 HOST_ATOMIC_INT
|
||||
#define HOST_ATOMIC_UINTPTR_T32 HOST_ATOMIC_INT
|
||||
#define HOST_ATOMIC_SIZE_T32 HOST_ATOMIC_UINT
|
||||
#define HOST_ATOMIC_PTRDIFF_T32 HOST_ATOMIC_INT
|
||||
|
||||
#define HOST_ATOMIC_INTPTR_T64 HOST_ATOMIC_LONG
|
||||
#define HOST_ATOMIC_UINTPTR_T64 HOST_ATOMIC_LONG
|
||||
#define HOST_ATOMIC_SIZE_T64 HOST_ATOMIC_ULONG
|
||||
#define HOST_ATOMIC_PTRDIFF_T64 HOST_ATOMIC_LONG
|
||||
|
||||
#define HOST_ATOMIC_FLAG HOST_ATOMIC_INT
|
||||
|
||||
// host regular types corresponding to atomic types
|
||||
#define HOST_INT cl_int
|
||||
#define HOST_UINT cl_uint
|
||||
#define HOST_LONG cl_long
|
||||
#define HOST_ULONG cl_ulong
|
||||
#define HOST_FLOAT cl_float
|
||||
#define HOST_DOUBLE cl_double
|
||||
|
||||
#define HOST_INTPTR_T32 cl_int
|
||||
#define HOST_UINTPTR_T32 cl_uint
|
||||
#define HOST_SIZE_T32 cl_uint
|
||||
#define HOST_PTRDIFF_T32 cl_int
|
||||
|
||||
#define HOST_INTPTR_T64 cl_long
|
||||
#define HOST_UINTPTR_T64 cl_ulong
|
||||
#define HOST_SIZE_T64 cl_ulong
|
||||
#define HOST_PTRDIFF_T64 cl_long
|
||||
|
||||
#define HOST_FLAG cl_uint
|
||||
|
||||
// host atomic functions
|
||||
void host_atomic_thread_fence(TExplicitMemoryOrderType order);
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_add(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32))
|
||||
return InterlockedExchangeAdd(a, c);
|
||||
#elif defined(__GNUC__)
|
||||
return __sync_fetch_and_add(a, c);
|
||||
#else
|
||||
log_info("Host function not implemented: atomic_fetch_add\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_sub(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32))
|
||||
return InterlockedExchangeSubtract(a, c);
|
||||
#elif defined(__GNUC__)
|
||||
return __sync_fetch_and_sub(a, c);
|
||||
#else
|
||||
log_info("Host function not implemented: atomic_fetch_sub\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_exchange(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32))
|
||||
return InterlockedExchange(a, c);
|
||||
#elif defined(__GNUC__)
|
||||
return __sync_lock_test_and_set(a, c);
|
||||
#else
|
||||
log_info("Host function not implemented: atomic_exchange\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
template <> HOST_FLOAT host_atomic_exchange(volatile HOST_ATOMIC_FLOAT *a, HOST_FLOAT c,
|
||||
TExplicitMemoryOrderType order);
|
||||
template <> HOST_DOUBLE host_atomic_exchange(volatile HOST_ATOMIC_DOUBLE *a, HOST_DOUBLE c,
|
||||
TExplicitMemoryOrderType order);
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
bool host_atomic_compare_exchange(volatile AtomicType *a, CorrespondingType *expected, CorrespondingType desired,
|
||||
TExplicitMemoryOrderType order_success,
|
||||
TExplicitMemoryOrderType order_failure)
|
||||
{
|
||||
CorrespondingType tmp;
|
||||
#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32))
|
||||
tmp = InterlockedCompareExchange(a, desired, *expected);
|
||||
#elif defined(__GNUC__)
|
||||
tmp = __sync_val_compare_and_swap(a, *expected, desired);
|
||||
#else
|
||||
log_info("Host function not implemented: atomic_compare_exchange\n");
|
||||
tmp = 0;
|
||||
#endif
|
||||
if(tmp == *expected)
|
||||
return true;
|
||||
*expected = tmp;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_load(volatile AtomicType *a,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
#if defined( _MSC_VER ) || (defined( __INTEL_COMPILER ) && defined(WIN32))
|
||||
return InterlockedExchangeAdd(a, 0);
|
||||
#elif defined(__GNUC__)
|
||||
return __sync_add_and_fetch(a, 0);
|
||||
#else
|
||||
log_info("Host function not implemented: atomic_load\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
template <> HOST_FLOAT host_atomic_load(volatile HOST_ATOMIC_FLOAT *a,
|
||||
TExplicitMemoryOrderType order);
|
||||
template <> HOST_DOUBLE host_atomic_load(volatile HOST_ATOMIC_DOUBLE *a,
|
||||
TExplicitMemoryOrderType order);
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
void host_atomic_store(volatile AtomicType* a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
host_atomic_exchange(a, c, order);
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
void host_atomic_init(volatile AtomicType* a, CorrespondingType c)
|
||||
{
|
||||
host_atomic_exchange(a, c, MEMORY_ORDER_RELAXED);
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_or(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
CorrespondingType expected = host_atomic_load<AtomicType, CorrespondingType>(a, order);
|
||||
CorrespondingType desired;
|
||||
do
|
||||
desired = expected | c;
|
||||
while(!host_atomic_compare_exchange(a, &expected, desired, order, order));
|
||||
return expected;
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_and(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
CorrespondingType expected = host_atomic_load<AtomicType, CorrespondingType>(a, order);
|
||||
CorrespondingType desired;
|
||||
do
|
||||
desired = expected & c;
|
||||
while(!host_atomic_compare_exchange(a, &expected, desired, order, order));
|
||||
return expected;
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_xor(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
CorrespondingType expected = host_atomic_load<AtomicType, CorrespondingType>(a, order);
|
||||
CorrespondingType desired;
|
||||
do
|
||||
desired = expected ^ c;
|
||||
while(!host_atomic_compare_exchange(a, &expected, desired, order, order));
|
||||
return expected;
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_min(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
CorrespondingType expected = host_atomic_load<AtomicType, CorrespondingType>(a, order);
|
||||
CorrespondingType desired;
|
||||
do
|
||||
desired = expected < c ? expected : c;
|
||||
while(!host_atomic_compare_exchange(a, &expected, desired, order, order));
|
||||
return expected;
|
||||
}
|
||||
|
||||
template <typename AtomicType, typename CorrespondingType>
|
||||
CorrespondingType host_atomic_fetch_max(volatile AtomicType *a, CorrespondingType c,
|
||||
TExplicitMemoryOrderType order)
|
||||
{
|
||||
CorrespondingType expected = host_atomic_load<AtomicType, CorrespondingType>(a, order);
|
||||
CorrespondingType desired;
|
||||
do
|
||||
desired = expected > c ? expected : c;
|
||||
while(!host_atomic_compare_exchange(a, &expected, desired, order, order));
|
||||
return expected;
|
||||
}
|
||||
|
||||
bool host_atomic_flag_test_and_set(volatile HOST_ATOMIC_FLAG *a, TExplicitMemoryOrderType order);
|
||||
void host_atomic_flag_clear(volatile HOST_ATOMIC_FLAG *a, TExplicitMemoryOrderType order);
|
||||
|
||||
#endif //_HOST_ATOMICS_H_
|
||||
Reference in New Issue
Block a user