File: kmp_atomic_cas.c

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (187 lines) | stat: -rw-r--r-- 6,362 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// RUN: %libomp-compile-and-run

#include <stdio.h>
#include <stdbool.h>
#include <omp.h>

// Used to detect architecture
#include "../../src/kmp_platform.h"

#ifdef  __cplusplus
extern "C" {
#endif
typedef void* ident_t;
extern bool
__kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
extern bool
__kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, short d);
extern bool
__kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, int *x, int e, int d);
extern bool
__kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, long long *x, long long e,
                         long long d);
extern char
__kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
extern short
__kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, short d);
extern int
__kmpc_atomic_val_4_cas(ident_t *loc, int gtid, int *x, int e, int d);
extern long long
__kmpc_atomic_val_8_cas(ident_t *loc, int gtid, long long *x, long long e,
                        long long d);
#ifdef  __cplusplus
}
#endif

int main() {
  int ret = 0;
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
  bool r;
  char c0 = 1;
  char c1 = 2;
  char c2 = 3;
  char co = 2;
  char cc = 0;
  short s0 = 11;
  short s1 = 12;
  short s2 = 13;
  short so = 12;
  short sc = 0;
  int i0 = 211;
  int i1 = 212;
  int i2 = 213;
  int io = 212;
  int ic = 0;
  long long l0 = 3111;
  long long l1 = 3112;
  long long l2 = 3113;
  long long lo = 3112;
  long long lc = 0;

// initialize OpenMP runtime library
  omp_set_dynamic(0);

//  #pragma omp atomic compare update capture
//    { r = x == e; if(r) { x = d; } }
// char, co == c1 initially, co == c2 finally
  r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c0, c2); // no-op
  if (co != c1) {
    ret++; printf("Error bool_1_cas no-op: %d != %d\n", co, c1); }
  if (r) { ret++; printf("Error bool_1_cas no-op ret: %d\n", r); }
  r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c1, c2);
  if (co != c2) {
    ret++; printf("Error bool_1_cas: %d != %d\n", co, c2); }
  if (!r) { ret++; printf("Error bool_1_cas ret: %d\n", r); }
// short
  r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s0, s2); // no-op
  if (so != s1) {
    ret++; printf("Error bool_2_cas no-op: %d != %d\n", so, s1); }
  if (r) { ret++; printf("Error bool_2_cas no-op ret: %d\n", r); }
  r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s1, s2);
  if (so != s2) {
    ret++; printf("Error bool_2_cas: %d != %d\n", so, s2); }
  if (!r) { ret++; printf("Error bool_2_cas ret: %d\n", r); }
// int
  r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i0, i2); // no-op
  if (io != i1) {
    ret++; printf("Error bool_4_cas no-op: %d != %d\n", io, i1); }
  if (r) { ret++; printf("Error bool_4_cas no-op ret: %d\n", r); }
  r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i1, i2);
  if (io != i2) {
    ret++; printf("Error bool_4_cas: %d != %d\n", io, i2); }
  if (!r) { ret++; printf("Error bool_4_cas ret: %d\n", r); }
// long long
  r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l0, l2); // no-op
  if (lo != l1) {
    ret++; printf("Error bool_8_cas no-op: %lld != %lld\n", lo, l1); }
  if (r) { ret++; printf("Error bool_8_cas no-op ret: %d\n", r); }
  r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l1, l2);
  if (lo != l2) {
    ret++; printf("Error bool_8_cas: %lld != %lld\n", lo, l2); }
  if (!r) { ret++; printf("Error bool_8_cas ret: %d\n", r); }

//  #pragma omp atomic compare update capture
//    { v = x; if (x == e) { x = d; } }
// char, co == c2 initially, co == c1 finally
  cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c0, c1); // no-op
  if (co != c2) {
    ret++; printf("Error val_1_cas no-op: %d != %d\n", co, c2); }
  if (cc != c2) {
    ret++; printf("Error val_1_cas no-op ret: %d != %d\n", cc, c2); }
  cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c2, c1);
  if (co != c1) {
    ret++; printf("Error val_1_cas: %d != %d\n", co, c1); }
  if (cc != c2) { ret++; printf("Error val_1_cas ret: %d != %d\n", cc, c2); }
// short
  sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s0, s1); // no-op
  if (so != s2) {
    ret++; printf("Error val_2_cas no-op: %d != %d\n", so, s2); }
  if (sc != s2) {
    ret++; printf("Error val_2_cas no-op ret: %d != %d\n", sc, s2); }
  sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s2, s1);
  if (so != s1) {
    ret++; printf("Error val_2_cas: %d != %d\n", so, s1); }
  if (sc != s2) {
    ret++; printf("Error val_2_cas ret: %d != %d\n", sc, s2); }
// int
  ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i0, i1); // no-op
  if (io != i2) {
    ret++; printf("Error val_4_cas no-op: %d != %d\n", io, i2); }
  if (ic != i2) {
    ret++; printf("Error val_4_cas no-op ret: %d != %d\n", ic, i2); }
  ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i2, i1);
  if (io != i1) {
    ret++; printf("Error val_4_cas: %d != %d\n", io, i1); }
  if (ic != i2) {
    ret++; printf("Error val_4_cas ret: %d != %d\n", ic, i2); }
// long long
  lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l0, l1); // no-op
  if (lo != l2) {
    ret++; printf("Error val_8_cas no-op: %lld != %lld\n", lo, l2); }
  if (lc != l2) {
    ret++; printf("Error val_8_cas no-op ret: %lld != %lld\n", lc, l2); }
  lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l2, l1);
  if (lo != l1) {
    ret++; printf("Error val_8_cas: %lld != %lld\n", lo, l1); }
  if (lc != l2) {
    ret++; printf("Error val_8_cas ret: %lld != %lld\n", lc, l2); }

// check in parallel
  i0 = 1;
  i1 = 0;
  for (io = 0; io < 5; ++io) {
    #pragma omp parallel num_threads(2) private(i2, ic, r)
    {
      if (omp_get_thread_num() == 0) {
        // th0 waits for th1 to increment i1, then th0 increments i0
        #pragma omp atomic read
          i2 = i1;
        ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1);
        while(ic != i2) {
          #pragma omp atomic read
            i2 = i1;
          ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1);
        }
      } else {
        // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed
        r = 0;
        while(!r) {
          #pragma omp atomic read
            i2 = i0;
          r = __kmpc_atomic_bool_4_cas(NULL, 0, &i1, i2 - 1, i2);
        }
      }
    }
  }
  if (i0 != 6 || i1 != 5) {
    ret++;
    printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5);
  }

  if (ret == 0)
    printf("passed\n");
#else
  printf("Unsupported architecture, skipping test...\n");
#endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
  return ret;
}