File: gtid.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • 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 (130 lines) | stat: -rw-r--r-- 3,910 bytes parent folder | download | duplicates (4)
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
// RUN: %libomp-cxx-compile-and-run
// RUN: %libomp-cxx-compile && env OMP_NUM_THREADS=1 %libomp-run

/*
 * This test aims to check whether hidden helper thread has right gtid. We also
 * test if there is mixed dependences between regular tasks and hidden helper
 * tasks, the tasks are executed by right set of threads. It is equivalent to
 * the following code:
 *
 * #pragma omp parallel for
 * for (int i = 0; i < N; ++i) {
 *   int data1 = -1, data2 = -1, data3 = -1;
 *   int depvar;
 * #pragma omp task shared(data1) depend(inout: depvar)
 *   {
 *     data1 = omp_get_global_thread_id();
 *   }
 * #pragma omp task hidden helper shared(data2) depend(inout: depvar)
 *   {
 *     data2 = omp_get_global_thread_id();
 *   }
 * #pragma omp task shared(data3) depend(inout: depvar)
 *   {
 *     data3 = omp_get_global_thread_id();
 *   }
 * #pragma omp taskwait
 *   assert(data1 == 0 || data1 > __kmp_num_hidden_helper_threads);
 *   assert(data2 > 0 && data2 <= __kmp_num_hidden_helper_threads);
 *   assert(data3 == 0 || data3 > __kmp_num_hidden_helper_threads);
 * }
 */

#include "common.h"

extern "C" {
struct kmp_task_t_with_privates {
  kmp_task_t task;
};

struct anon {
  int32_t *data;
};
}

kmp_int32 __kmp_hidden_helper_threads_num;

kmp_int32 omp_task_entry(kmp_int32 gtid, kmp_task_t_with_privates *task) {
  auto shareds = reinterpret_cast<anon *>(task->task.shareds);
  auto p = shareds->data;
  *p = __kmpc_global_thread_num(nullptr);
  return 0;
}

template <bool hidden_helper_task> void assert_gtid(int v) {
  if (__kmp_hidden_helper_threads_num) {
    if (hidden_helper_task) {
      assert(v > 0 && v <= __kmp_hidden_helper_threads_num);
    } else {
      assert(v == 0 || v > __kmp_hidden_helper_threads_num);
    }
  } else {
    assert(v >= 0);
  }
}

int main(int argc, char *argv[]) {
  __kmp_hidden_helper_threads_num = get_num_hidden_helper_threads();

  constexpr const int N = 1024;
#pragma omp parallel for
  for (int i = 0; i < N; ++i) {
    int32_t data1 = -1, data2 = -1, data3 = -1;
    int depvar;
    int32_t gtid = __kmpc_global_thread_num(nullptr);

    // Task 1, regular task
    auto task1 = __kmpc_omp_task_alloc(
        nullptr, gtid, 1, sizeof(kmp_task_t_with_privates), sizeof(anon),
        reinterpret_cast<kmp_routine_entry_t>(omp_task_entry));
    auto shareds = reinterpret_cast<anon *>(task1->shareds);
    shareds->data = &data1;

    kmp_depend_info_t depinfo1;
    depinfo1.base_addr = reinterpret_cast<intptr_t>(&depvar);
    depinfo1.flag = 3; // INOUT
    depinfo1.len = 4;

    __kmpc_omp_task_with_deps(nullptr, gtid, task1, 1, &depinfo1, 0, nullptr);

    // Task 2, hidden helper task
    auto task2 = __kmpc_omp_target_task_alloc(
        nullptr, gtid, 1, sizeof(kmp_task_t_with_privates), sizeof(anon),
        reinterpret_cast<kmp_routine_entry_t>(omp_task_entry), -1);
    shareds = reinterpret_cast<anon *>(task2->shareds);
    shareds->data = &data2;

    kmp_depend_info_t depinfo2;
    depinfo2.base_addr = reinterpret_cast<intptr_t>(&depvar);
    depinfo2.flag = 3; // INOUT
    depinfo2.len = 4;

    __kmpc_omp_task_with_deps(nullptr, gtid, task2, 1, &depinfo2, 0, nullptr);

    // Task 3, regular task
    auto task3 = __kmpc_omp_task_alloc(
        nullptr, gtid, 1, sizeof(kmp_task_t_with_privates), sizeof(anon),
        reinterpret_cast<kmp_routine_entry_t>(omp_task_entry));
    shareds = reinterpret_cast<anon *>(task3->shareds);
    shareds->data = &data3;

    kmp_depend_info_t depinfo3;
    depinfo3.base_addr = reinterpret_cast<intptr_t>(&depvar);
    depinfo3.flag = 3; // INOUT
    depinfo3.len = 4;

    __kmpc_omp_task_with_deps(nullptr, gtid, task3, 1, &depinfo3, 0, nullptr);

    __kmpc_omp_taskwait(nullptr, gtid);

    // FIXME: 8 here is not accurate
    assert_gtid<false>(data1);
    assert_gtid<true>(data2);
    assert_gtid<false>(data3);
  }

  std::cout << "PASS\n";
  return 0;
}

// CHECK: PASS