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