19982f33eSPeyton, Jonathan L #ifndef LIBOMP_TEST_TOPOLOGY_H
29982f33eSPeyton, Jonathan L #define LIBOMP_TEST_TOPOLOGY_H
39982f33eSPeyton, Jonathan L
49982f33eSPeyton, Jonathan L #include "libomp_test_affinity.h"
59982f33eSPeyton, Jonathan L #include <stdio.h>
69982f33eSPeyton, Jonathan L #include <stdlib.h>
79982f33eSPeyton, Jonathan L #include <dirent.h>
89982f33eSPeyton, Jonathan L #include <errno.h>
99982f33eSPeyton, Jonathan L #include <ctype.h>
109982f33eSPeyton, Jonathan L #include <omp.h>
11*50b68a3dSPeyton, Jonathan L #include <stdarg.h>
129982f33eSPeyton, Jonathan L
139982f33eSPeyton, Jonathan L typedef enum topology_obj_type_t {
149982f33eSPeyton, Jonathan L TOPOLOGY_OBJ_THREAD,
159982f33eSPeyton, Jonathan L TOPOLOGY_OBJ_CORE,
169982f33eSPeyton, Jonathan L TOPOLOGY_OBJ_SOCKET,
179982f33eSPeyton, Jonathan L TOPOLOGY_OBJ_MAX
189982f33eSPeyton, Jonathan L } topology_obj_type_t;
199982f33eSPeyton, Jonathan L
209982f33eSPeyton, Jonathan L typedef struct place_list_t {
219982f33eSPeyton, Jonathan L int num_places;
22*50b68a3dSPeyton, Jonathan L int current_place;
23*50b68a3dSPeyton, Jonathan L int *place_nums;
249982f33eSPeyton, Jonathan L affinity_mask_t **masks;
259982f33eSPeyton, Jonathan L } place_list_t;
269982f33eSPeyton, Jonathan L
279982f33eSPeyton, Jonathan L // Return the first character in file 'f' that is not a whitespace character
289982f33eSPeyton, Jonathan L // including newlines and carriage returns
get_first_nonspace_from_file(FILE * f)299982f33eSPeyton, Jonathan L static int get_first_nonspace_from_file(FILE *f) {
309982f33eSPeyton, Jonathan L int c;
319982f33eSPeyton, Jonathan L do {
329982f33eSPeyton, Jonathan L c = fgetc(f);
339982f33eSPeyton, Jonathan L } while (c != EOF && (isspace(c) || c == '\n' || c == '\r'));
349982f33eSPeyton, Jonathan L return c;
359982f33eSPeyton, Jonathan L }
369982f33eSPeyton, Jonathan L
379982f33eSPeyton, Jonathan L // Read an integer from file 'f' into 'number'
389982f33eSPeyton, Jonathan L // Return 1 on successful read of integer,
399982f33eSPeyton, Jonathan L // 0 on unsuccessful read of integer,
409982f33eSPeyton, Jonathan L // EOF on end of file.
get_integer_from_file(FILE * f,int * number)419982f33eSPeyton, Jonathan L static int get_integer_from_file(FILE *f, int *number) {
429982f33eSPeyton, Jonathan L int n;
439982f33eSPeyton, Jonathan L n = fscanf(f, "%d", number);
449982f33eSPeyton, Jonathan L if (feof(f))
459982f33eSPeyton, Jonathan L return EOF;
469982f33eSPeyton, Jonathan L if (n != 1)
479982f33eSPeyton, Jonathan L return 0;
489982f33eSPeyton, Jonathan L return 1;
499982f33eSPeyton, Jonathan L }
509982f33eSPeyton, Jonathan L
519982f33eSPeyton, Jonathan L // Read a siblings list file from Linux /sys/devices/system/cpu/cpu?/topology/*
topology_get_mask_from_file(const char * filename)529982f33eSPeyton, Jonathan L static affinity_mask_t *topology_get_mask_from_file(const char *filename) {
539982f33eSPeyton, Jonathan L int status = EXIT_SUCCESS;
549982f33eSPeyton, Jonathan L FILE *f = fopen(filename, "r");
559982f33eSPeyton, Jonathan L if (!f) {
569982f33eSPeyton, Jonathan L perror(filename);
579982f33eSPeyton, Jonathan L exit(EXIT_FAILURE);
589982f33eSPeyton, Jonathan L }
599982f33eSPeyton, Jonathan L affinity_mask_t *mask = affinity_mask_alloc();
609982f33eSPeyton, Jonathan L while (1) {
619982f33eSPeyton, Jonathan L int c, i, n, lower, upper;
629982f33eSPeyton, Jonathan L // Read the first integer
639982f33eSPeyton, Jonathan L n = get_integer_from_file(f, &lower);
649982f33eSPeyton, Jonathan L if (n == EOF) {
659982f33eSPeyton, Jonathan L break;
669982f33eSPeyton, Jonathan L } else if (n == 0) {
679982f33eSPeyton, Jonathan L fprintf(stderr, "syntax error: expected integer\n");
689982f33eSPeyton, Jonathan L status = EXIT_FAILURE;
699982f33eSPeyton, Jonathan L break;
709982f33eSPeyton, Jonathan L }
719982f33eSPeyton, Jonathan L
729982f33eSPeyton, Jonathan L // Now either a , or -
739982f33eSPeyton, Jonathan L c = get_first_nonspace_from_file(f);
749982f33eSPeyton, Jonathan L if (c == EOF || c == ',') {
759982f33eSPeyton, Jonathan L affinity_mask_set(mask, lower);
769982f33eSPeyton, Jonathan L if (c == EOF)
779982f33eSPeyton, Jonathan L break;
789982f33eSPeyton, Jonathan L } else if (c == '-') {
799982f33eSPeyton, Jonathan L n = get_integer_from_file(f, &upper);
809982f33eSPeyton, Jonathan L if (n == EOF || n == 0) {
819982f33eSPeyton, Jonathan L fprintf(stderr, "syntax error: expected integer\n");
829982f33eSPeyton, Jonathan L status = EXIT_FAILURE;
839982f33eSPeyton, Jonathan L break;
849982f33eSPeyton, Jonathan L }
859982f33eSPeyton, Jonathan L for (i = lower; i <= upper; ++i)
869982f33eSPeyton, Jonathan L affinity_mask_set(mask, i);
879982f33eSPeyton, Jonathan L c = get_first_nonspace_from_file(f);
889982f33eSPeyton, Jonathan L if (c == EOF) {
899982f33eSPeyton, Jonathan L break;
909982f33eSPeyton, Jonathan L } else if (c == ',') {
919982f33eSPeyton, Jonathan L continue;
929982f33eSPeyton, Jonathan L } else {
939982f33eSPeyton, Jonathan L fprintf(stderr, "syntax error: unexpected character: '%c (%d)'\n", c,
949982f33eSPeyton, Jonathan L c);
959982f33eSPeyton, Jonathan L status = EXIT_FAILURE;
969982f33eSPeyton, Jonathan L break;
979982f33eSPeyton, Jonathan L }
989982f33eSPeyton, Jonathan L } else {
999982f33eSPeyton, Jonathan L fprintf(stderr, "syntax error: unexpected character: '%c (%d)'\n", c, c);
1009982f33eSPeyton, Jonathan L status = EXIT_FAILURE;
1019982f33eSPeyton, Jonathan L break;
1029982f33eSPeyton, Jonathan L }
1039982f33eSPeyton, Jonathan L }
1049982f33eSPeyton, Jonathan L fclose(f);
1059982f33eSPeyton, Jonathan L if (status == EXIT_FAILURE) {
1069982f33eSPeyton, Jonathan L affinity_mask_free(mask);
1079982f33eSPeyton, Jonathan L mask = NULL;
1089982f33eSPeyton, Jonathan L }
1099982f33eSPeyton, Jonathan L return mask;
1109982f33eSPeyton, Jonathan L }
1119982f33eSPeyton, Jonathan L
topology_get_num_cpus()1129982f33eSPeyton, Jonathan L static int topology_get_num_cpus() {
1139982f33eSPeyton, Jonathan L char buf[1024];
1149982f33eSPeyton, Jonathan L // Count the number of cpus
1159982f33eSPeyton, Jonathan L int cpu = 0;
1169982f33eSPeyton, Jonathan L while (1) {
1179982f33eSPeyton, Jonathan L snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%d", cpu);
1189982f33eSPeyton, Jonathan L DIR *dir = opendir(buf);
1199982f33eSPeyton, Jonathan L if (dir) {
1209982f33eSPeyton, Jonathan L closedir(dir);
1219982f33eSPeyton, Jonathan L cpu++;
1229982f33eSPeyton, Jonathan L } else {
1239982f33eSPeyton, Jonathan L break;
1249982f33eSPeyton, Jonathan L }
1259982f33eSPeyton, Jonathan L }
1269982f33eSPeyton, Jonathan L if (cpu == 0)
1279982f33eSPeyton, Jonathan L cpu = 1;
1289982f33eSPeyton, Jonathan L return cpu;
1299982f33eSPeyton, Jonathan L }
1309982f33eSPeyton, Jonathan L
1319982f33eSPeyton, Jonathan L // Return whether the current thread has access to all logical processors
topology_using_full_mask()1329982f33eSPeyton, Jonathan L static int topology_using_full_mask() {
1339982f33eSPeyton, Jonathan L int cpu;
1349982f33eSPeyton, Jonathan L int has_all = 1;
1359982f33eSPeyton, Jonathan L int num_cpus = topology_get_num_cpus();
1369982f33eSPeyton, Jonathan L affinity_mask_t *mask = affinity_mask_alloc();
1379982f33eSPeyton, Jonathan L get_thread_affinity(mask);
1389982f33eSPeyton, Jonathan L for (cpu = 0; cpu < num_cpus; ++cpu) {
1399982f33eSPeyton, Jonathan L if (!affinity_mask_isset(mask, cpu)) {
1409982f33eSPeyton, Jonathan L has_all = 0;
1419982f33eSPeyton, Jonathan L break;
1429982f33eSPeyton, Jonathan L }
1439982f33eSPeyton, Jonathan L }
1449982f33eSPeyton, Jonathan L affinity_mask_free(mask);
1459982f33eSPeyton, Jonathan L return has_all;
1469982f33eSPeyton, Jonathan L }
1479982f33eSPeyton, Jonathan L
1489982f33eSPeyton, Jonathan L // Return array of masks representing OMP_PLACES keyword (e.g., sockets, cores,
1499982f33eSPeyton, Jonathan L // threads)
topology_alloc_type_places(topology_obj_type_t type)1509982f33eSPeyton, Jonathan L static place_list_t *topology_alloc_type_places(topology_obj_type_t type) {
1519982f33eSPeyton, Jonathan L char buf[1024];
1529982f33eSPeyton, Jonathan L int i, cpu, num_places, num_unique;
153*50b68a3dSPeyton, Jonathan L int *place_nums;
1549982f33eSPeyton, Jonathan L int num_cpus = topology_get_num_cpus();
1559982f33eSPeyton, Jonathan L place_list_t *places = (place_list_t *)malloc(sizeof(place_list_t));
1569982f33eSPeyton, Jonathan L affinity_mask_t **masks =
1579982f33eSPeyton, Jonathan L (affinity_mask_t **)malloc(sizeof(affinity_mask_t *) * num_cpus);
1589982f33eSPeyton, Jonathan L num_unique = 0;
1599982f33eSPeyton, Jonathan L for (cpu = 0; cpu < num_cpus; ++cpu) {
1609982f33eSPeyton, Jonathan L affinity_mask_t *mask;
1619982f33eSPeyton, Jonathan L if (type == TOPOLOGY_OBJ_CORE) {
1629982f33eSPeyton, Jonathan L snprintf(buf, sizeof(buf),
1639982f33eSPeyton, Jonathan L "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list",
1649982f33eSPeyton, Jonathan L cpu);
1659982f33eSPeyton, Jonathan L mask = topology_get_mask_from_file(buf);
1669982f33eSPeyton, Jonathan L } else if (type == TOPOLOGY_OBJ_SOCKET) {
1679982f33eSPeyton, Jonathan L snprintf(buf, sizeof(buf),
1689982f33eSPeyton, Jonathan L "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list",
1699982f33eSPeyton, Jonathan L cpu);
1709982f33eSPeyton, Jonathan L mask = topology_get_mask_from_file(buf);
1719982f33eSPeyton, Jonathan L } else if (type == TOPOLOGY_OBJ_THREAD) {
1729982f33eSPeyton, Jonathan L mask = affinity_mask_alloc();
1739982f33eSPeyton, Jonathan L affinity_mask_set(mask, cpu);
1749982f33eSPeyton, Jonathan L } else {
1759982f33eSPeyton, Jonathan L fprintf(stderr, "Unknown topology type (%d)\n", (int)type);
1769982f33eSPeyton, Jonathan L exit(EXIT_FAILURE);
1779982f33eSPeyton, Jonathan L }
1789982f33eSPeyton, Jonathan L // Check for unique topology objects above the thread level
1799982f33eSPeyton, Jonathan L if (type != TOPOLOGY_OBJ_THREAD) {
1809982f33eSPeyton, Jonathan L for (i = 0; i < num_unique; ++i) {
1819982f33eSPeyton, Jonathan L if (affinity_mask_equal(masks[i], mask)) {
1829982f33eSPeyton, Jonathan L affinity_mask_free(mask);
1839982f33eSPeyton, Jonathan L mask = NULL;
1849982f33eSPeyton, Jonathan L break;
1859982f33eSPeyton, Jonathan L }
1869982f33eSPeyton, Jonathan L }
1879982f33eSPeyton, Jonathan L }
1889982f33eSPeyton, Jonathan L if (mask)
1899982f33eSPeyton, Jonathan L masks[num_unique++] = mask;
1909982f33eSPeyton, Jonathan L }
191*50b68a3dSPeyton, Jonathan L place_nums = (int *)malloc(sizeof(int) * num_unique);
192*50b68a3dSPeyton, Jonathan L for (i = 0; i < num_unique; ++i)
193*50b68a3dSPeyton, Jonathan L place_nums[i] = i;
1949982f33eSPeyton, Jonathan L places->num_places = num_unique;
1959982f33eSPeyton, Jonathan L places->masks = masks;
196*50b68a3dSPeyton, Jonathan L places->place_nums = place_nums;
197*50b68a3dSPeyton, Jonathan L places->current_place = -1;
1989982f33eSPeyton, Jonathan L return places;
1999982f33eSPeyton, Jonathan L }
2009982f33eSPeyton, Jonathan L
topology_alloc_openmp_places()2019982f33eSPeyton, Jonathan L static place_list_t *topology_alloc_openmp_places() {
2029982f33eSPeyton, Jonathan L int place, i;
2039982f33eSPeyton, Jonathan L int num_places = omp_get_num_places();
2049982f33eSPeyton, Jonathan L place_list_t *places = (place_list_t *)malloc(sizeof(place_list_t));
2059982f33eSPeyton, Jonathan L affinity_mask_t **masks =
2069982f33eSPeyton, Jonathan L (affinity_mask_t **)malloc(sizeof(affinity_mask_t *) * num_places);
207*50b68a3dSPeyton, Jonathan L int *place_nums = (int *)malloc(sizeof(int) * num_places);
2089982f33eSPeyton, Jonathan L for (place = 0; place < num_places; ++place) {
2099982f33eSPeyton, Jonathan L int num_procs = omp_get_place_num_procs(place);
2109982f33eSPeyton, Jonathan L int *ids = (int *)malloc(sizeof(int) * num_procs);
2119982f33eSPeyton, Jonathan L omp_get_place_proc_ids(place, ids);
2129982f33eSPeyton, Jonathan L affinity_mask_t *mask = affinity_mask_alloc();
2139982f33eSPeyton, Jonathan L for (i = 0; i < num_procs; ++i)
2149982f33eSPeyton, Jonathan L affinity_mask_set(mask, ids[i]);
2159982f33eSPeyton, Jonathan L masks[place] = mask;
216*50b68a3dSPeyton, Jonathan L place_nums[place] = place;
2179982f33eSPeyton, Jonathan L }
2189982f33eSPeyton, Jonathan L places->num_places = num_places;
219*50b68a3dSPeyton, Jonathan L places->place_nums = place_nums;
2209982f33eSPeyton, Jonathan L places->masks = masks;
221*50b68a3dSPeyton, Jonathan L places->current_place = omp_get_place_num();
222*50b68a3dSPeyton, Jonathan L return places;
223*50b68a3dSPeyton, Jonathan L }
224*50b68a3dSPeyton, Jonathan L
topology_alloc_openmp_partition()225*50b68a3dSPeyton, Jonathan L static place_list_t *topology_alloc_openmp_partition() {
226*50b68a3dSPeyton, Jonathan L int p, i;
227*50b68a3dSPeyton, Jonathan L int num_places = omp_get_partition_num_places();
228*50b68a3dSPeyton, Jonathan L place_list_t *places = (place_list_t *)malloc(sizeof(place_list_t));
229*50b68a3dSPeyton, Jonathan L int *place_nums = (int *)malloc(sizeof(int) * num_places);
230*50b68a3dSPeyton, Jonathan L affinity_mask_t **masks =
231*50b68a3dSPeyton, Jonathan L (affinity_mask_t **)malloc(sizeof(affinity_mask_t *) * num_places);
232*50b68a3dSPeyton, Jonathan L omp_get_partition_place_nums(place_nums);
233*50b68a3dSPeyton, Jonathan L for (p = 0; p < num_places; ++p) {
234*50b68a3dSPeyton, Jonathan L int place = place_nums[p];
235*50b68a3dSPeyton, Jonathan L int num_procs = omp_get_place_num_procs(place);
236*50b68a3dSPeyton, Jonathan L int *ids = (int *)malloc(sizeof(int) * num_procs);
237*50b68a3dSPeyton, Jonathan L if (num_procs == 0) {
238*50b68a3dSPeyton, Jonathan L fprintf(stderr, "place %d has 0 procs?\n", place);
239*50b68a3dSPeyton, Jonathan L exit(EXIT_FAILURE);
240*50b68a3dSPeyton, Jonathan L }
241*50b68a3dSPeyton, Jonathan L omp_get_place_proc_ids(place, ids);
242*50b68a3dSPeyton, Jonathan L affinity_mask_t *mask = affinity_mask_alloc();
243*50b68a3dSPeyton, Jonathan L for (i = 0; i < num_procs; ++i)
244*50b68a3dSPeyton, Jonathan L affinity_mask_set(mask, ids[i]);
245*50b68a3dSPeyton, Jonathan L if (affinity_mask_count(mask) == 0) {
246*50b68a3dSPeyton, Jonathan L fprintf(stderr, "place %d has 0 procs set?\n", place);
247*50b68a3dSPeyton, Jonathan L exit(EXIT_FAILURE);
248*50b68a3dSPeyton, Jonathan L }
249*50b68a3dSPeyton, Jonathan L masks[p] = mask;
250*50b68a3dSPeyton, Jonathan L }
251*50b68a3dSPeyton, Jonathan L places->num_places = num_places;
252*50b68a3dSPeyton, Jonathan L places->place_nums = place_nums;
253*50b68a3dSPeyton, Jonathan L places->masks = masks;
254*50b68a3dSPeyton, Jonathan L places->current_place = omp_get_place_num();
2559982f33eSPeyton, Jonathan L return places;
2569982f33eSPeyton, Jonathan L }
2579982f33eSPeyton, Jonathan L
2589982f33eSPeyton, Jonathan L // Free the array of masks from one of: topology_alloc_type_masks()
2599982f33eSPeyton, Jonathan L // or topology_alloc_openmp_masks()
topology_free_places(place_list_t * places)2609982f33eSPeyton, Jonathan L static void topology_free_places(place_list_t *places) {
2619982f33eSPeyton, Jonathan L int i;
2629982f33eSPeyton, Jonathan L for (i = 0; i < places->num_places; ++i)
2639982f33eSPeyton, Jonathan L affinity_mask_free(places->masks[i]);
2649982f33eSPeyton, Jonathan L free(places->masks);
265*50b68a3dSPeyton, Jonathan L free(places->place_nums);
2669982f33eSPeyton, Jonathan L free(places);
2679982f33eSPeyton, Jonathan L }
2689982f33eSPeyton, Jonathan L
topology_print_places(const place_list_t * p)2699982f33eSPeyton, Jonathan L static void topology_print_places(const place_list_t *p) {
2709982f33eSPeyton, Jonathan L int i;
2719982f33eSPeyton, Jonathan L char buf[1024];
2729982f33eSPeyton, Jonathan L for (i = 0; i < p->num_places; ++i) {
2739982f33eSPeyton, Jonathan L affinity_mask_snprintf(buf, sizeof(buf), p->masks[i]);
274*50b68a3dSPeyton, Jonathan L printf("Place %d: %s\n", p->place_nums[i], buf);
2759982f33eSPeyton, Jonathan L }
2769982f33eSPeyton, Jonathan L }
2779982f33eSPeyton, Jonathan L
278*50b68a3dSPeyton, Jonathan L // Print out an error message, possibly with two problem place lists,
279*50b68a3dSPeyton, Jonathan L // and then exit with failure
proc_bind_die(omp_proc_bind_t proc_bind,int T,int P,const char * format,...)280*50b68a3dSPeyton, Jonathan L static void proc_bind_die(omp_proc_bind_t proc_bind, int T, int P,
281*50b68a3dSPeyton, Jonathan L const char *format, ...) {
282*50b68a3dSPeyton, Jonathan L va_list args;
283*50b68a3dSPeyton, Jonathan L va_start(args, format);
284*50b68a3dSPeyton, Jonathan L const char *pb;
285*50b68a3dSPeyton, Jonathan L switch (proc_bind) {
286*50b68a3dSPeyton, Jonathan L case omp_proc_bind_false:
287*50b68a3dSPeyton, Jonathan L pb = "False";
288*50b68a3dSPeyton, Jonathan L break;
289*50b68a3dSPeyton, Jonathan L case omp_proc_bind_true:
290*50b68a3dSPeyton, Jonathan L pb = "True";
291*50b68a3dSPeyton, Jonathan L break;
292*50b68a3dSPeyton, Jonathan L case omp_proc_bind_master:
293*50b68a3dSPeyton, Jonathan L pb = "Master (Primary)";
294*50b68a3dSPeyton, Jonathan L break;
295*50b68a3dSPeyton, Jonathan L case omp_proc_bind_close:
296*50b68a3dSPeyton, Jonathan L pb = "Close";
297*50b68a3dSPeyton, Jonathan L break;
298*50b68a3dSPeyton, Jonathan L case omp_proc_bind_spread:
299*50b68a3dSPeyton, Jonathan L pb = "Spread";
300*50b68a3dSPeyton, Jonathan L break;
301*50b68a3dSPeyton, Jonathan L default:
302*50b68a3dSPeyton, Jonathan L pb = "(Unknown Proc Bind Type)";
303*50b68a3dSPeyton, Jonathan L break;
304*50b68a3dSPeyton, Jonathan L }
305*50b68a3dSPeyton, Jonathan L if (proc_bind == omp_proc_bind_spread || proc_bind == omp_proc_bind_close) {
306*50b68a3dSPeyton, Jonathan L if (T <= P) {
307*50b68a3dSPeyton, Jonathan L fprintf(stderr, "%s : (T(%d) <= P(%d)) : ", pb, T, P);
308*50b68a3dSPeyton, Jonathan L } else {
309*50b68a3dSPeyton, Jonathan L fprintf(stderr, "%s : (T(%d) > P(%d)) : ", pb, T, P);
310*50b68a3dSPeyton, Jonathan L }
311*50b68a3dSPeyton, Jonathan L } else {
312*50b68a3dSPeyton, Jonathan L fprintf(stderr, "%s : T = %d, P = %d : ", pb, T, P);
313*50b68a3dSPeyton, Jonathan L }
314*50b68a3dSPeyton, Jonathan L vfprintf(stderr, format, args);
315*50b68a3dSPeyton, Jonathan L va_end(args);
316*50b68a3dSPeyton, Jonathan L
317*50b68a3dSPeyton, Jonathan L exit(EXIT_FAILURE);
318*50b68a3dSPeyton, Jonathan L }
319*50b68a3dSPeyton, Jonathan L
320*50b68a3dSPeyton, Jonathan L // Return 1 on failure, 0 on success.
proc_bind_check(omp_proc_bind_t proc_bind,const place_list_t * parent,place_list_t ** children,int nchildren)321*50b68a3dSPeyton, Jonathan L static void proc_bind_check(omp_proc_bind_t proc_bind,
322*50b68a3dSPeyton, Jonathan L const place_list_t *parent, place_list_t **children,
323*50b68a3dSPeyton, Jonathan L int nchildren) {
324*50b68a3dSPeyton, Jonathan L place_list_t *partition;
325*50b68a3dSPeyton, Jonathan L int T, i, j, place, low, high, first, last, count, current_place, num_places;
326*50b68a3dSPeyton, Jonathan L const int *place_nums;
327*50b68a3dSPeyton, Jonathan L int P = parent->num_places;
328*50b68a3dSPeyton, Jonathan L
329*50b68a3dSPeyton, Jonathan L // Find the correct T (there could be null entries in children)
330*50b68a3dSPeyton, Jonathan L place_list_t **partitions =
331*50b68a3dSPeyton, Jonathan L (place_list_t **)malloc(sizeof(place_list_t *) * nchildren);
332*50b68a3dSPeyton, Jonathan L T = 0;
333*50b68a3dSPeyton, Jonathan L for (i = 0; i < nchildren; ++i)
334*50b68a3dSPeyton, Jonathan L if (children[i])
335*50b68a3dSPeyton, Jonathan L partitions[T++] = children[i];
336*50b68a3dSPeyton, Jonathan L // Only able to check spread, close, master (primary)
337*50b68a3dSPeyton, Jonathan L if (proc_bind != omp_proc_bind_spread && proc_bind != omp_proc_bind_close &&
338*50b68a3dSPeyton, Jonathan L proc_bind != omp_proc_bind_master)
339*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P, NULL, NULL,
340*50b68a3dSPeyton, Jonathan L "Cannot check this proc bind type\n");
341*50b68a3dSPeyton, Jonathan L
342*50b68a3dSPeyton, Jonathan L if (proc_bind == omp_proc_bind_spread) {
343*50b68a3dSPeyton, Jonathan L if (T <= P) {
344*50b68a3dSPeyton, Jonathan L // Run through each subpartition
345*50b68a3dSPeyton, Jonathan L for (i = 0; i < T; ++i) {
346*50b68a3dSPeyton, Jonathan L partition = partitions[i];
347*50b68a3dSPeyton, Jonathan L place_nums = partition->place_nums;
348*50b68a3dSPeyton, Jonathan L num_places = partition->num_places;
349*50b68a3dSPeyton, Jonathan L current_place = partition->current_place;
350*50b68a3dSPeyton, Jonathan L // Correct count?
351*50b68a3dSPeyton, Jonathan L low = P / T;
352*50b68a3dSPeyton, Jonathan L high = P / T + (P % T ? 1 : 0);
353*50b68a3dSPeyton, Jonathan L if (num_places != low && num_places != high) {
354*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
355*50b68a3dSPeyton, Jonathan L "Incorrect number of places for thread %d: %d. "
356*50b68a3dSPeyton, Jonathan L "Expecting between %d and %d\n",
357*50b68a3dSPeyton, Jonathan L i, num_places, low, high);
358*50b68a3dSPeyton, Jonathan L }
359*50b68a3dSPeyton, Jonathan L // Consecutive places?
360*50b68a3dSPeyton, Jonathan L for (j = 1; j < num_places; ++j) {
361*50b68a3dSPeyton, Jonathan L if (place_nums[j] != (place_nums[j - 1] + 1) % P) {
362*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
363*50b68a3dSPeyton, Jonathan L "Not consecutive places: %d, %d in partition\n",
364*50b68a3dSPeyton, Jonathan L place_nums[j - 1], place_nums[j]);
365*50b68a3dSPeyton, Jonathan L }
366*50b68a3dSPeyton, Jonathan L }
367*50b68a3dSPeyton, Jonathan L first = place_nums[0];
368*50b68a3dSPeyton, Jonathan L last = place_nums[num_places - 1];
369*50b68a3dSPeyton, Jonathan L // Primary thread executes on place of the parent thread?
370*50b68a3dSPeyton, Jonathan L if (i == 0) {
371*50b68a3dSPeyton, Jonathan L if (current_place != parent->current_place) {
372*50b68a3dSPeyton, Jonathan L proc_bind_die(
373*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
374*50b68a3dSPeyton, Jonathan L "Primary thread not on same place (%d) as parent thread (%d)\n",
375*50b68a3dSPeyton, Jonathan L current_place, parent->current_place);
376*50b68a3dSPeyton, Jonathan L }
377*50b68a3dSPeyton, Jonathan L } else {
378*50b68a3dSPeyton, Jonathan L // Thread's current place is first place within it's partition?
379*50b68a3dSPeyton, Jonathan L if (current_place != first) {
380*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
381*50b68a3dSPeyton, Jonathan L "Thread's current place (%d) is not the first place "
382*50b68a3dSPeyton, Jonathan L "in its partition [%d, %d]\n",
383*50b68a3dSPeyton, Jonathan L current_place, first, last);
384*50b68a3dSPeyton, Jonathan L }
385*50b68a3dSPeyton, Jonathan L }
386*50b68a3dSPeyton, Jonathan L // Partitions don't have intersections?
387*50b68a3dSPeyton, Jonathan L int f1 = first;
388*50b68a3dSPeyton, Jonathan L int l1 = last;
389*50b68a3dSPeyton, Jonathan L for (j = 0; j < i; ++j) {
390*50b68a3dSPeyton, Jonathan L int f2 = partitions[j]->place_nums[0];
391*50b68a3dSPeyton, Jonathan L int l2 = partitions[j]->place_nums[partitions[j]->num_places - 1];
392*50b68a3dSPeyton, Jonathan L if (f1 > l1 && f2 > l2) {
393*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
394*50b68a3dSPeyton, Jonathan L "partitions intersect. [%d, %d] and [%d, %d]\n", f1,
395*50b68a3dSPeyton, Jonathan L l1, f2, l2);
396*50b68a3dSPeyton, Jonathan L }
397*50b68a3dSPeyton, Jonathan L if (f1 > l1 && f2 <= l2)
398*50b68a3dSPeyton, Jonathan L if (f1 < l2 || l1 > f2) {
399*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
400*50b68a3dSPeyton, Jonathan L "partitions intersect. [%d, %d] and [%d, %d]\n", f1,
401*50b68a3dSPeyton, Jonathan L l1, f2, l2);
402*50b68a3dSPeyton, Jonathan L }
403*50b68a3dSPeyton, Jonathan L if (f1 <= l1 && f2 > l2)
404*50b68a3dSPeyton, Jonathan L if (f2 < l1 || l2 > f1) {
405*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
406*50b68a3dSPeyton, Jonathan L "partitions intersect. [%d, %d] and [%d, %d]\n", f1,
407*50b68a3dSPeyton, Jonathan L l1, f2, l2);
408*50b68a3dSPeyton, Jonathan L }
409*50b68a3dSPeyton, Jonathan L if (f1 <= l1 && f2 <= l2)
410*50b68a3dSPeyton, Jonathan L if (!(f2 > l1 || l2 < f1)) {
411*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
412*50b68a3dSPeyton, Jonathan L "partitions intersect. [%d, %d] and [%d, %d]\n", f1,
413*50b68a3dSPeyton, Jonathan L l1, f2, l2);
414*50b68a3dSPeyton, Jonathan L }
415*50b68a3dSPeyton, Jonathan L }
416*50b68a3dSPeyton, Jonathan L }
417*50b68a3dSPeyton, Jonathan L } else {
418*50b68a3dSPeyton, Jonathan L // T > P
419*50b68a3dSPeyton, Jonathan L // Each partition has only one place?
420*50b68a3dSPeyton, Jonathan L for (i = 0; i < T; ++i) {
421*50b68a3dSPeyton, Jonathan L if (partitions[i]->num_places != 1) {
422*50b68a3dSPeyton, Jonathan L proc_bind_die(
423*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
424*50b68a3dSPeyton, Jonathan L "Incorrect number of places for thread %d: %d. Expecting 1\n", i,
425*50b68a3dSPeyton, Jonathan L partitions[i]->num_places);
426*50b68a3dSPeyton, Jonathan L }
427*50b68a3dSPeyton, Jonathan L }
428*50b68a3dSPeyton, Jonathan L // Correct number of consecutive threads per partition?
429*50b68a3dSPeyton, Jonathan L low = T / P;
430*50b68a3dSPeyton, Jonathan L high = T / P + (T % P ? 1 : 0);
431*50b68a3dSPeyton, Jonathan L for (i = 1, count = 1; i < T; ++i) {
432*50b68a3dSPeyton, Jonathan L if (partitions[i]->place_nums[0] == partitions[i - 1]->place_nums[0]) {
433*50b68a3dSPeyton, Jonathan L count++;
434*50b68a3dSPeyton, Jonathan L if (count > high) {
435*50b68a3dSPeyton, Jonathan L proc_bind_die(
436*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
437*50b68a3dSPeyton, Jonathan L "Too many threads have place %d for their partition\n",
438*50b68a3dSPeyton, Jonathan L partitions[i]->place_nums[0]);
439*50b68a3dSPeyton, Jonathan L }
440*50b68a3dSPeyton, Jonathan L } else {
441*50b68a3dSPeyton, Jonathan L if (count < low) {
442*50b68a3dSPeyton, Jonathan L proc_bind_die(
443*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
444*50b68a3dSPeyton, Jonathan L "Not enough threads have place %d for their partition\n",
445*50b68a3dSPeyton, Jonathan L partitions[i]->place_nums[0]);
446*50b68a3dSPeyton, Jonathan L }
447*50b68a3dSPeyton, Jonathan L count = 1;
448*50b68a3dSPeyton, Jonathan L }
449*50b68a3dSPeyton, Jonathan L }
450*50b68a3dSPeyton, Jonathan L // Primary thread executes on place of the parent thread?
451*50b68a3dSPeyton, Jonathan L current_place = partitions[0]->place_nums[0];
452*50b68a3dSPeyton, Jonathan L if (parent->current_place != -1 &&
453*50b68a3dSPeyton, Jonathan L current_place != parent->current_place) {
454*50b68a3dSPeyton, Jonathan L proc_bind_die(
455*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
456*50b68a3dSPeyton, Jonathan L "Primary thread not on same place (%d) as parent thread (%d)\n",
457*50b68a3dSPeyton, Jonathan L current_place, parent->current_place);
458*50b68a3dSPeyton, Jonathan L }
459*50b68a3dSPeyton, Jonathan L }
460*50b68a3dSPeyton, Jonathan L } else if (proc_bind == omp_proc_bind_close ||
461*50b68a3dSPeyton, Jonathan L proc_bind == omp_proc_bind_master) {
462*50b68a3dSPeyton, Jonathan L // Check that each subpartition is the same as the parent
463*50b68a3dSPeyton, Jonathan L for (i = 0; i < T; ++i) {
464*50b68a3dSPeyton, Jonathan L partition = partitions[i];
465*50b68a3dSPeyton, Jonathan L place_nums = partition->place_nums;
466*50b68a3dSPeyton, Jonathan L num_places = partition->num_places;
467*50b68a3dSPeyton, Jonathan L current_place = partition->current_place;
468*50b68a3dSPeyton, Jonathan L if (parent->num_places != num_places) {
469*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
470*50b68a3dSPeyton, Jonathan L "Number of places in subpartition (%d) does not match "
471*50b68a3dSPeyton, Jonathan L "parent (%d)\n",
472*50b68a3dSPeyton, Jonathan L num_places, parent->num_places);
473*50b68a3dSPeyton, Jonathan L }
474*50b68a3dSPeyton, Jonathan L for (j = 0; j < num_places; ++j) {
475*50b68a3dSPeyton, Jonathan L if (parent->place_nums[j] != place_nums[j]) {
476*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
477*50b68a3dSPeyton, Jonathan L "Subpartition place (%d) does not match "
478*50b68a3dSPeyton, Jonathan L "parent partition place (%d)\n",
479*50b68a3dSPeyton, Jonathan L place_nums[j], parent->place_nums[j]);
480*50b68a3dSPeyton, Jonathan L }
481*50b68a3dSPeyton, Jonathan L }
482*50b68a3dSPeyton, Jonathan L }
483*50b68a3dSPeyton, Jonathan L // Find index into place_nums of current place for parent
484*50b68a3dSPeyton, Jonathan L for (j = 0; j < parent->num_places; ++j)
485*50b68a3dSPeyton, Jonathan L if (parent->place_nums[j] == parent->current_place)
486*50b68a3dSPeyton, Jonathan L break;
487*50b68a3dSPeyton, Jonathan L if (proc_bind == omp_proc_bind_close) {
488*50b68a3dSPeyton, Jonathan L if (T <= P) {
489*50b68a3dSPeyton, Jonathan L // close T <= P
490*50b68a3dSPeyton, Jonathan L // check place assignment for each thread
491*50b68a3dSPeyton, Jonathan L for (i = 0; i < T; ++i) {
492*50b68a3dSPeyton, Jonathan L partition = partitions[i];
493*50b68a3dSPeyton, Jonathan L current_place = partition->current_place;
494*50b68a3dSPeyton, Jonathan L if (current_place != parent->place_nums[j]) {
495*50b68a3dSPeyton, Jonathan L proc_bind_die(
496*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
497*50b68a3dSPeyton, Jonathan L "Thread %d's current place (%d) is incorrect. expected %d\n", i,
498*50b68a3dSPeyton, Jonathan L current_place, parent->place_nums[j]);
499*50b68a3dSPeyton, Jonathan L }
500*50b68a3dSPeyton, Jonathan L j = (j + 1) % parent->num_places;
501*50b68a3dSPeyton, Jonathan L }
502*50b68a3dSPeyton, Jonathan L } else {
503*50b68a3dSPeyton, Jonathan L // close T > P
504*50b68a3dSPeyton, Jonathan L // check place assignment for each thread
505*50b68a3dSPeyton, Jonathan L low = T / P;
506*50b68a3dSPeyton, Jonathan L high = T / P + (T % P ? 1 : 0);
507*50b68a3dSPeyton, Jonathan L count = 1;
508*50b68a3dSPeyton, Jonathan L if (partitions[0]->current_place != parent->current_place) {
509*50b68a3dSPeyton, Jonathan L proc_bind_die(
510*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
511*50b68a3dSPeyton, Jonathan L "Primary thread's place (%d) is not parent thread's place (%d)\n",
512*50b68a3dSPeyton, Jonathan L partitions[0]->current_place, parent->current_place);
513*50b68a3dSPeyton, Jonathan L }
514*50b68a3dSPeyton, Jonathan L for (i = 1; i < T; ++i) {
515*50b68a3dSPeyton, Jonathan L current_place = partitions[i]->current_place;
516*50b68a3dSPeyton, Jonathan L if (current_place == parent->place_nums[j]) {
517*50b68a3dSPeyton, Jonathan L count++;
518*50b68a3dSPeyton, Jonathan L if (count > high) {
519*50b68a3dSPeyton, Jonathan L proc_bind_die(
520*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
521*50b68a3dSPeyton, Jonathan L "Too many threads have place %d for their current place\n",
522*50b68a3dSPeyton, Jonathan L current_place);
523*50b68a3dSPeyton, Jonathan L }
524*50b68a3dSPeyton, Jonathan L } else {
525*50b68a3dSPeyton, Jonathan L if (count < low) {
526*50b68a3dSPeyton, Jonathan L proc_bind_die(
527*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
528*50b68a3dSPeyton, Jonathan L "Not enough threads have place %d for their current place\n",
529*50b68a3dSPeyton, Jonathan L parent->place_nums[j]);
530*50b68a3dSPeyton, Jonathan L }
531*50b68a3dSPeyton, Jonathan L j = (j + 1) % parent->num_places;
532*50b68a3dSPeyton, Jonathan L if (current_place != parent->place_nums[j]) {
533*50b68a3dSPeyton, Jonathan L proc_bind_die(
534*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
535*50b68a3dSPeyton, Jonathan L "Thread %d's place (%d) is not corret. Expected %d\n", i,
536*50b68a3dSPeyton, Jonathan L partitions[i]->current_place, parent->place_nums[j]);
537*50b68a3dSPeyton, Jonathan L }
538*50b68a3dSPeyton, Jonathan L count = 1;
539*50b68a3dSPeyton, Jonathan L }
540*50b68a3dSPeyton, Jonathan L }
541*50b68a3dSPeyton, Jonathan L }
542*50b68a3dSPeyton, Jonathan L } else {
543*50b68a3dSPeyton, Jonathan L // proc_bind_primary
544*50b68a3dSPeyton, Jonathan L // Every thread should be assigned to the primary thread's place
545*50b68a3dSPeyton, Jonathan L for (i = 0; i < T; ++i) {
546*50b68a3dSPeyton, Jonathan L if (partitions[i]->current_place != parent->current_place) {
547*50b68a3dSPeyton, Jonathan L proc_bind_die(
548*50b68a3dSPeyton, Jonathan L proc_bind, T, P,
549*50b68a3dSPeyton, Jonathan L "Thread %d's place (%d) is not the primary thread's place (%d)\n",
550*50b68a3dSPeyton, Jonathan L i, partitions[i]->current_place, parent->current_place);
551*50b68a3dSPeyton, Jonathan L }
552*50b68a3dSPeyton, Jonathan L }
553*50b68a3dSPeyton, Jonathan L }
554*50b68a3dSPeyton, Jonathan L }
555*50b68a3dSPeyton, Jonathan L
556*50b68a3dSPeyton, Jonathan L // Check that each partition's current place is within the partition
557*50b68a3dSPeyton, Jonathan L for (i = 0; i < T; ++i) {
558*50b68a3dSPeyton, Jonathan L current_place = partitions[i]->current_place;
559*50b68a3dSPeyton, Jonathan L num_places = partitions[i]->num_places;
560*50b68a3dSPeyton, Jonathan L first = partitions[i]->place_nums[0];
561*50b68a3dSPeyton, Jonathan L last = partitions[i]->place_nums[num_places - 1];
562*50b68a3dSPeyton, Jonathan L for (j = 0; j < num_places; ++j)
563*50b68a3dSPeyton, Jonathan L if (partitions[i]->place_nums[j] == current_place)
564*50b68a3dSPeyton, Jonathan L break;
565*50b68a3dSPeyton, Jonathan L if (j == num_places) {
566*50b68a3dSPeyton, Jonathan L proc_bind_die(proc_bind, T, P,
567*50b68a3dSPeyton, Jonathan L "Thread %d's current place (%d) is not within its "
568*50b68a3dSPeyton, Jonathan L "partition [%d, %d]\n",
569*50b68a3dSPeyton, Jonathan L i, current_place, first, last);
570*50b68a3dSPeyton, Jonathan L }
571*50b68a3dSPeyton, Jonathan L }
572*50b68a3dSPeyton, Jonathan L
573*50b68a3dSPeyton, Jonathan L free(partitions);
574*50b68a3dSPeyton, Jonathan L }
575*50b68a3dSPeyton, Jonathan L
5769982f33eSPeyton, Jonathan L #endif
577