xref: /netbsd-src/external/gpl3/gdb/dist/gdb/testsuite/gdb.threads/omp-par-scope.c (revision 9fb66d812c00ebfb445c0b47dea128f32aa6fe96)
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