1/*
2 * Copyright (c) 2014 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9#include <bomp_internal.h>
10
11/*
12 * These functions implement the PARALLEL construct
13 *
14 * #pragma omp parallel
15 * {
16 *  body;
17 * }
18 *
19 * is translated into
20 * void subfunction (void *data)
21 * {
22 *  use data;
23 *  body;
24 *  }
25 *  setup data;
26 *  GOMP_parallel_start (subfunction, &data, num_threads);
27 *  subfunction (&data);
28 *  GOMP_parallel_end ();
29 */
30
31void GOMP_parallel_start(void (*fn)(void *),
32                         void *data,
33                         unsigned nthreads)
34{
35    debug_printf("GOMP_parallel_start(%p, %p, %u)\n", fn, data, nthreads);
36
37    /* Identify the number of threads that can be spawned and start the processing */
38    if (!omp_in_parallel()) {
39        debug_printf("not in parallel\n");
40
41        struct omp_icv_task *icv_task = bomp_icv_task_new();
42        if (!icv_task) {
43            debug_printf("no icv task\n");
44            return;
45        }
46
47        icv_task->active_levels = 1;
48        icv_task->nthreads = omp_get_max_threads();
49        debug_printf("omp_get_max_threads = %u\n", icv_task->nthreads);
50
51        if (nthreads == 0 || (icv_task->dynamic && icv_task->nthreads < nthreads)) {
52            icv_task->nthreads = OMP_GET_ICV_GLOBAL(thread_limit);
53            debug_printf("resetting to = %u\n", icv_task->nthreads);
54        }
55
56        bomp_icv_set_task(icv_task);
57        debug_printf("icv task set %u\n", icv_task->nthreads);
58
59        /* start processing */
60        bomp_start_processing(fn, data, 0, icv_task->nthreads);
61    } else {
62        if (omp_get_nested()) {
63            // handle nested paralellism
64            assert(!"Handling nested paralellism\n");
65        }
66
67        /* we have already started enough threads */
68        uint32_t active_levels = OMP_GET_ICV_TASK(active_levels);
69        //debug_printf("setting active_levels to %u\n", active_levels+1);
70
71        OMP_SET_ICV_TASK(active_levels, active_levels+1);
72    }
73}
74
75void GOMP_parallel_end(void)
76{
77//    debug_printf("GOMP_parallel_end\n");
78
79    uint32_t active_levels = OMP_GET_ICV_TASK(active_levels);
80
81    if (active_levels == 1) {
82        bomp_end_processing();
83    } else  {
84//        debug_printf("setting active_levels to %u\n", active_levels-1);
85        OMP_SET_ICV_TASK(active_levels, active_levels-1);
86    }
87
88
89    debug_printf("GOMP_parallel_end end\n");
90}
91
92void GOMP_parallel(void (*fn)(void *),
93                   void *data,
94                   unsigned num_threads,
95                   unsigned int flags)
96{
97    debug_printf("GOMP_parallel");
98    assert(!"NYI");
99}
100
101#if OMP_VERSION >= OMP_VERSION_40
102bool GOMP_cancel(int which,
103                 bool do_cancel)
104{
105    assert(!"NYI");
106    return 0;
107}
108
109bool GOMP_cancellation_point(int which)
110{
111    assert(!"NYI");
112    return 0;
113}
114#endif
115