1 /* 2 * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. 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 18 19 #ifndef ATOMIC_COMMON_H_ 20 #define ATOMIC_COMMON_H_ 21 22 /** 23 * \brief Memory reference size/type codes. 24 * 25 * Legacy assumptions observed: 26 * - (code & 3) < 2 if and only if the type size is 1 or 2 bytes. 27 * - (code & 3) == log2(type size) if the type size is 1, 2, 4, or 8 bytes. 28 */ 29 typedef enum MSZ { 30 MSZ_SBYTE = 0x00, /* signed byte */ 31 MSZ_SHWORD = 0x01, /* signed 16-bit short */ 32 MSZ_UBYTE = 0x04, /* unsigned byte */ 33 MSZ_UHWORD = 0x05, /* unsigned 16-bit short */ 34 35 /* Codes for types larger than two bytes. These are all distinct values 36 * suitable for use as case labels in switches. The holes in this sequence 37 * of code values avoid violating the first legacy assumption described above. 38 */ 39 MSZ_SWORD = 0x02, /* signed 32-bit int */ 40 MSZ_SLWORD = 0x03, /* signed 64-bit long */ 41 MSZ_UWORD = 0x06, /* unsigned 32-bit int */ 42 MSZ_ULWORD = 0x07, /* unsigned 64-bit long */ 43 MSZ_FWORD = 0x0a, /* 32-bit single precision float */ 44 MSZ_FLWORD = 0x0b, /* 64-bit double precision float */ 45 MSZ_I8 = 0x0f, /* distinct 64-bit integer type */ 46 MSZ_PTR = 0x13, /* distinct 64-bit pointer type */ 47 MSZ_F10 = 0x16, /* X87 FPU 80-bit extended precision */ 48 MSZ_F16 = 0x17, /* 128-bit quad precision float */ 49 MSZ_F32 = 0x1a, /* 256-bit float */ 50 MSZ_F8x2 = 0x1b, /* 128-bit double-double float */ 51 52 MSZ_UNDEF = 0xff, /* undefined MSZ code */ 53 } MSZ; 54 55 /** Specifies memory order of an atomic operation. 56 Values corresponding to C11/C++11 memory orders are guaranteed 57 to match those of the target's C11/C++11 header. */ 58 typedef enum MEMORY_ORDER { 59 MO_RELAXED, 60 MO_CONSUME, 61 MO_ACQUIRE, 62 MO_RELEASE, 63 MO_ACQ_REL, 64 MO_SEQ_CST, 65 MO_SEQ_CST_NON_ATOMIC, /* OMPACCEL: SEQ_CST for CPU, non-atomic for GPU. It's used for reduction. */ 66 MO_MAX_DEF = MO_SEQ_CST, /**< maximum value with defined meaning */ 67 MO_UNDEF = 0xFF /**< denotes "undefined" */ 68 } MEMORY_ORDER; 69 70 /** Specifies scope an atomic operation. */ 71 typedef enum SYNC_SCOPE { 72 SS_SINGLETHREAD, ///< Synchronize only within a thread (e.g. a signal fence) 73 SS_PROCESS ///< Synchronize with other threads 74 } SYNC_SCOPE; 75 76 /** Specifies source of an atomic operation. */ 77 typedef enum ATOMIC_ORIGIN { 78 AORG_CPLUS, /**< C++11 or C11 atomic operation */ 79 AORG_OPENMP, /**< OpenMP */ 80 AORG_OPENACC, /**< OpenACC */ 81 AORG_MAX_DEF = AORG_OPENACC /**< maximum value with defined meaning */ 82 } ATOMIC_ORIGIN; 83 84 /** Specifies a read-modify-write operation. */ 85 typedef enum ATOMIC_RMW_OP { 86 AOP_XCHG, 87 AOP_ADD, 88 AOP_SUB, 89 AOP_AND, 90 AOP_OR, 91 AOP_MIN, 92 AOP_MAX, 93 AOP_XOR, 94 AOP_MUL, 95 AOP_DIV, 96 AOP_SHR, 97 AOP_SHL, 98 AOP_EQV, 99 AOP_NEQV, 100 AOP_MAX_DEF = AOP_XOR, /**< maximum value with defined meaning */ 101 AOP_UNDEF = 0xFF 102 } ATOMIC_RMW_OP; 103 104 typedef struct CMPXCHG_MEMORY_ORDER { 105 MEMORY_ORDER success; 106 MEMORY_ORDER failure; 107 } CMPXCHG_MEMORY_ORDER; 108 109 /** Information about an atomic operation. */ 110 typedef struct ATOMIC_INFO { 111 MSZ msz; ///< size of memory operand 112 ATOMIC_RMW_OP op; ///< AOP_UNDEF except for ATOMICRMWx instructions 113 ATOMIC_ORIGIN origin; 114 SYNC_SCOPE scope; 115 } ATOMIC_INFO; 116 117 /** True if MEMORY_ORDER m performs an acquire operation. 118 MO_CONSUME is considered to perform an acquire. */ 119 #define MO_HAS_ACQUIRE(m) ((m) != MO_RELAXED && (m) != MO_RELEASE) 120 121 /** True if MEMORY_ORDER m performs a release operation */ 122 #define MO_HAS_RELEASE(m) ((m) >= MO_RELEASE) 123 124 #endif 125 126 127