1 /* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2017-2020 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include <stdio.h> 19 #include <omp.h> 20 21 omp_lock_t lock; 22 omp_lock_t lock2; 23 24 /* Enforce execution order between two threads using a lock. */ 25 26 static void 27 omp_set_lock_in_order (int num, omp_lock_t *lock) 28 { 29 /* Ensure that thread num 0 first sets the lock. */ 30 if (num == 0) 31 omp_set_lock (lock); 32 #pragma omp barrier 33 34 /* Block thread num 1 until it can set the lock. */ 35 if (num == 1) 36 omp_set_lock (lock); 37 38 /* This bit here is guaranteed to be executed first by thread num 0, and 39 once thread num 0 unsets the lock, to be executed by thread num 1. */ 40 ; 41 } 42 43 /* Testcase for checking access to variables in a single / outer scope. 44 Make sure that variables not referred to in the parallel section are 45 accessible from the debugger. */ 46 47 void 48 single_scope (void) 49 { 50 static int s1 = -41, s2 = -42, s3 = -43; 51 int i1 = 11, i2 = 12, i3 = 13; 52 53 #pragma omp parallel num_threads (2) shared (s1, i1) private (s2, i2) 54 { 55 int thread_num = omp_get_thread_num (); 56 omp_set_lock_in_order (thread_num, &lock); 57 58 s2 = 100 * (thread_num + 1) + 2; 59 i2 = s2 + 10; 60 61 #pragma omp critical 62 printf ("single_scope: thread_num=%d, s1=%d, i1=%d, s2=%d, i2=%d\n", 63 thread_num, s1, i1, s2, i2); 64 65 omp_unset_lock (&lock); 66 } 67 68 printf ("single_scope: s1=%d, s2=%d, s3=%d, i1=%d, i2=%d, i3=%d\n", 69 s1, s2, s3, i1, i2, i3); 70 } 71 72 static int file_scope_var = 9876; 73 74 /* Testcase for checking access to variables from parallel region 75 nested within more than one lexical scope. Of particular interest 76 are variables which are not referenced in the parallel section. */ 77 78 void 79 multi_scope (void) 80 { 81 int i01 = 1, i02 = 2; 82 83 { 84 int i11 = 11, i12 = 12; 85 86 { 87 int i21 = -21, i22 = 22; 88 89 #pragma omp parallel num_threads (2) \ 90 firstprivate (i01) \ 91 shared (i11) \ 92 private (i21) 93 { 94 int thread_num = omp_get_thread_num (); 95 omp_set_lock_in_order (thread_num, &lock); 96 97 i21 = 100 * (thread_num + 1) + 21; 98 99 #pragma omp critical 100 printf ("multi_scope: thread_num=%d, i01=%d, i11=%d, i21=%d\n", 101 thread_num, i01, i11, i21); 102 103 omp_unset_lock (&lock); 104 } 105 106 printf ("multi_scope: i01=%d, i02=%d, i11=%d, " 107 "i12=%d, i21=%d, i22=%d\n", 108 i01, i02, i11, i12, i21, i22); 109 } 110 } 111 } 112 113 /* Nested functions in C is a GNU extension. Some non-GNU compilers 114 define __GNUC__, but they don't support nested functions. So, 115 unfortunately, we can't use that for our test. */ 116 #if HAVE_NESTED_FUNCTION_SUPPORT 117 118 /* Testcase for checking access of variables from within parallel 119 region in a lexically nested function. */ 120 121 void 122 nested_func (void) 123 { 124 static int s1 = -42; 125 int i = 1, j = 2, k = 3; 126 127 void 128 foo (int p, int q, int r) 129 { 130 int x = 4; 131 132 { 133 int y = 5, z = 6; 134 #pragma omp parallel num_threads (2) shared (i, p, x) private (j, q, y) 135 { 136 int tn = omp_get_thread_num (); 137 omp_set_lock_in_order (tn, &lock); 138 139 j = 1000 * (tn + 1); 140 q = j + 1; 141 y = q + 1; 142 #pragma omp critical 143 printf ("nested_func: tn=%d: i=%d, p=%d, x=%d, j=%d, q=%d, y=%d\n", 144 tn, i, p, x, j, q, y); 145 146 omp_unset_lock (&lock); 147 } 148 } 149 } 150 151 foo (10, 11, 12); 152 153 i = 101; j = 102; k = 103; 154 foo (20, 21, 22); 155 } 156 #endif 157 158 /* Testcase for checking access to variables from within a nested parallel 159 region. */ 160 161 void 162 nested_parallel (void) 163 { 164 int i = 1, j = 2; 165 int l = -1; 166 167 omp_set_nested (1); 168 omp_set_dynamic (0); 169 #pragma omp parallel num_threads (2) private (l) 170 { 171 int num = omp_get_thread_num (); 172 omp_set_lock_in_order (num, &lock); 173 174 int nthr = omp_get_num_threads (); 175 int off = num * nthr; 176 int k = off + 101; 177 l = off + 102; 178 #pragma omp parallel num_threads (2) shared (num) 179 { 180 int inner_num = omp_get_thread_num (); 181 omp_set_lock_in_order (inner_num, &lock2); 182 183 #pragma omp critical 184 printf ("nested_parallel (inner threads): outer thread num = %d, thread num = %d\n", num, inner_num); 185 186 omp_unset_lock (&lock2); 187 } 188 #pragma omp critical 189 printf ("nested_parallel (outer threads) %d: k = %d, l = %d\n", num, k, l); 190 191 omp_unset_lock (&lock); 192 } 193 } 194 195 int 196 main (int argc, char **argv) 197 { 198 omp_init_lock (&lock); 199 omp_init_lock (&lock2); 200 201 single_scope (); 202 multi_scope (); 203 #if HAVE_NESTED_FUNCTION_SUPPORT 204 nested_func (); 205 #endif 206 nested_parallel (); 207 208 omp_destroy_lock (&lock); 209 omp_destroy_lock (&lock2); 210 211 return 0; 212 } 213 214