#include "libgomp.h"
#include <stdlib.h>
static inline void
gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr,
enum gomp_schedule_type sched, long chunk_size)
{
ws->sched = sched;
ws->chunk_size = chunk_size;
ws->end = ((incr > 0 && start > end) || (incr < 0 && start < end))
? start : end;
ws->incr = incr;
ws->next = start;
}
static bool
gomp_loop_static_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
if (gomp_work_share_start (false))
gomp_loop_init (thr->ts.work_share, start, end, incr,
GFS_STATIC, chunk_size);
gomp_mutex_unlock (&thr->ts.work_share->lock);
return !gomp_iter_static_next (istart, iend);
}
static bool
gomp_loop_dynamic_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
bool ret;
if (gomp_work_share_start (false))
gomp_loop_init (thr->ts.work_share, start, end, incr,
GFS_DYNAMIC, chunk_size);
#ifdef HAVE_SYNC_BUILTINS
gomp_mutex_unlock (&thr->ts.work_share->lock);
ret = gomp_iter_dynamic_next (istart, iend);
#else
ret = gomp_iter_dynamic_next_locked (istart, iend);
gomp_mutex_unlock (&thr->ts.work_share->lock);
#endif
return ret;
}
static bool
gomp_loop_guided_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
bool ret;
if (gomp_work_share_start (false))
gomp_loop_init (thr->ts.work_share, start, end, incr,
GFS_GUIDED, chunk_size);
#ifdef HAVE_SYNC_BUILTINS
gomp_mutex_unlock (&thr->ts.work_share->lock);
ret = gomp_iter_guided_next (istart, iend);
#else
ret = gomp_iter_guided_next_locked (istart, iend);
gomp_mutex_unlock (&thr->ts.work_share->lock);
#endif
return ret;
}
bool
GOMP_loop_runtime_start (long start, long end, long incr,
long *istart, long *iend)
{
switch (gomp_run_sched_var)
{
case GFS_STATIC:
return gomp_loop_static_start (start, end, incr, gomp_run_sched_chunk,
istart, iend);
case GFS_DYNAMIC:
return gomp_loop_dynamic_start (start, end, incr, gomp_run_sched_chunk,
istart, iend);
case GFS_GUIDED:
return gomp_loop_guided_start (start, end, incr, gomp_run_sched_chunk,
istart, iend);
default:
abort ();
}
}
static bool
gomp_loop_ordered_static_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
if (gomp_work_share_start (true))
{
gomp_loop_init (thr->ts.work_share, start, end, incr,
GFS_STATIC, chunk_size);
gomp_ordered_static_init ();
}
gomp_mutex_unlock (&thr->ts.work_share->lock);
return !gomp_iter_static_next (istart, iend);
}
static bool
gomp_loop_ordered_dynamic_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
bool ret;
if (gomp_work_share_start (true))
gomp_loop_init (thr->ts.work_share, start, end, incr,
GFS_DYNAMIC, chunk_size);
ret = gomp_iter_dynamic_next_locked (istart, iend);
if (ret)
gomp_ordered_first ();
gomp_mutex_unlock (&thr->ts.work_share->lock);
return ret;
}
static bool
gomp_loop_ordered_guided_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
bool ret;
if (gomp_work_share_start (true))
gomp_loop_init (thr->ts.work_share, start, end, incr,
GFS_GUIDED, chunk_size);
ret = gomp_iter_guided_next_locked (istart, iend);
if (ret)
gomp_ordered_first ();
gomp_mutex_unlock (&thr->ts.work_share->lock);
return ret;
}
bool
GOMP_loop_ordered_runtime_start (long start, long end, long incr,
long *istart, long *iend)
{
switch (gomp_run_sched_var)
{
case GFS_STATIC:
return gomp_loop_ordered_static_start (start, end, incr,
gomp_run_sched_chunk,
istart, iend);
case GFS_DYNAMIC:
return gomp_loop_ordered_dynamic_start (start, end, incr,
gomp_run_sched_chunk,
istart, iend);
case GFS_GUIDED:
return gomp_loop_ordered_guided_start (start, end, incr,
gomp_run_sched_chunk,
istart, iend);
default:
abort ();
}
}
static bool
gomp_loop_static_next (long *istart, long *iend)
{
return !gomp_iter_static_next (istart, iend);
}
static bool
gomp_loop_dynamic_next (long *istart, long *iend)
{
bool ret;
#ifdef HAVE_SYNC_BUILTINS
ret = gomp_iter_dynamic_next (istart, iend);
#else
struct gomp_thread *thr = gomp_thread ();
gomp_mutex_lock (&thr->ts.work_share->lock);
ret = gomp_iter_dynamic_next_locked (istart, iend);
gomp_mutex_unlock (&thr->ts.work_share->lock);
#endif
return ret;
}
static bool
gomp_loop_guided_next (long *istart, long *iend)
{
bool ret;
#ifdef HAVE_SYNC_BUILTINS
ret = gomp_iter_guided_next (istart, iend);
#else
struct gomp_thread *thr = gomp_thread ();
gomp_mutex_lock (&thr->ts.work_share->lock);
ret = gomp_iter_guided_next_locked (istart, iend);
gomp_mutex_unlock (&thr->ts.work_share->lock);
#endif
return ret;
}
bool
GOMP_loop_runtime_next (long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
switch (thr->ts.work_share->sched)
{
case GFS_STATIC:
return gomp_loop_static_next (istart, iend);
case GFS_DYNAMIC:
return gomp_loop_dynamic_next (istart, iend);
case GFS_GUIDED:
return gomp_loop_guided_next (istart, iend);
default:
abort ();
}
}
static bool
gomp_loop_ordered_static_next (long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
int test;
gomp_ordered_sync ();
gomp_mutex_lock (&thr->ts.work_share->lock);
test = gomp_iter_static_next (istart, iend);
if (test >= 0)
gomp_ordered_static_next ();
gomp_mutex_unlock (&thr->ts.work_share->lock);
return test == 0;
}
static bool
gomp_loop_ordered_dynamic_next (long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
bool ret;
gomp_ordered_sync ();
gomp_mutex_lock (&thr->ts.work_share->lock);
ret = gomp_iter_dynamic_next_locked (istart, iend);
if (ret)
gomp_ordered_next ();
else
gomp_ordered_last ();
gomp_mutex_unlock (&thr->ts.work_share->lock);
return ret;
}
static bool
gomp_loop_ordered_guided_next (long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
bool ret;
gomp_ordered_sync ();
gomp_mutex_lock (&thr->ts.work_share->lock);
ret = gomp_iter_guided_next_locked (istart, iend);
if (ret)
gomp_ordered_next ();
else
gomp_ordered_last ();
gomp_mutex_unlock (&thr->ts.work_share->lock);
return ret;
}
bool
GOMP_loop_ordered_runtime_next (long *istart, long *iend)
{
struct gomp_thread *thr = gomp_thread ();
switch (thr->ts.work_share->sched)
{
case GFS_STATIC:
return gomp_loop_ordered_static_next (istart, iend);
case GFS_DYNAMIC:
return gomp_loop_ordered_dynamic_next (istart, iend);
case GFS_GUIDED:
return gomp_loop_ordered_guided_next (istart, iend);
default:
abort ();
}
}
static void
gomp_parallel_loop_start (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
long incr, enum gomp_schedule_type sched,
long chunk_size)
{
struct gomp_work_share *ws;
num_threads = gomp_resolve_num_threads (num_threads);
ws = gomp_new_work_share (false, num_threads);
gomp_loop_init (ws, start, end, incr, sched, chunk_size);
gomp_team_start (fn, data, num_threads, ws);
}
void
GOMP_parallel_loop_static_start (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
long incr, long chunk_size)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
GFS_STATIC, chunk_size);
}
void
GOMP_parallel_loop_dynamic_start (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
long incr, long chunk_size)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
GFS_DYNAMIC, chunk_size);
}
void
GOMP_parallel_loop_guided_start (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
long incr, long chunk_size)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
GFS_GUIDED, chunk_size);
}
void
GOMP_parallel_loop_runtime_start (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
long incr)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
gomp_run_sched_var, gomp_run_sched_chunk);
}
void
GOMP_loop_end (void)
{
gomp_work_share_end ();
}
void
GOMP_loop_end_nowait (void)
{
gomp_work_share_end_nowait ();
}
#ifdef HAVE_ATTRIBUTE_ALIAS
extern __typeof(gomp_loop_static_start) GOMP_loop_static_start
__attribute__((alias ("gomp_loop_static_start")));
extern __typeof(gomp_loop_dynamic_start) GOMP_loop_dynamic_start
__attribute__((alias ("gomp_loop_dynamic_start")));
extern __typeof(gomp_loop_guided_start) GOMP_loop_guided_start
__attribute__((alias ("gomp_loop_guided_start")));
extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start
__attribute__((alias ("gomp_loop_ordered_static_start")));
extern __typeof(gomp_loop_ordered_dynamic_start) GOMP_loop_ordered_dynamic_start
__attribute__((alias ("gomp_loop_ordered_dynamic_start")));
extern __typeof(gomp_loop_ordered_guided_start) GOMP_loop_ordered_guided_start
__attribute__((alias ("gomp_loop_ordered_guided_start")));
extern __typeof(gomp_loop_static_next) GOMP_loop_static_next
__attribute__((alias ("gomp_loop_static_next")));
extern __typeof(gomp_loop_dynamic_next) GOMP_loop_dynamic_next
__attribute__((alias ("gomp_loop_dynamic_next")));
extern __typeof(gomp_loop_guided_next) GOMP_loop_guided_next
__attribute__((alias ("gomp_loop_guided_next")));
extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next
__attribute__((alias ("gomp_loop_ordered_static_next")));
extern __typeof(gomp_loop_ordered_dynamic_next) GOMP_loop_ordered_dynamic_next
__attribute__((alias ("gomp_loop_ordered_dynamic_next")));
extern __typeof(gomp_loop_ordered_guided_next) GOMP_loop_ordered_guided_next
__attribute__((alias ("gomp_loop_ordered_guided_next")));
#else
bool
GOMP_loop_static_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
{
return gomp_loop_static_start (start, end, incr, chunk_size, istart, iend);
}
bool
GOMP_loop_dynamic_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
{
return gomp_loop_dynamic_start (start, end, incr, chunk_size, istart, iend);
}
bool
GOMP_loop_guided_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
{
return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend);
}
bool
GOMP_loop_ordered_static_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
return gomp_loop_ordered_static_start (start, end, incr, chunk_size,
istart, iend);
}
bool
GOMP_loop_ordered_dynamic_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
return gomp_loop_ordered_dynamic_start (start, end, incr, chunk_size,
istart, iend);
}
bool
GOMP_loop_ordered_guided_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
return gomp_loop_ordered_guided_start (start, end, incr, chunk_size,
istart, iend);
}
bool
GOMP_loop_static_next (long *istart, long *iend)
{
return gomp_loop_static_next (istart, iend);
}
bool
GOMP_loop_dynamic_next (long *istart, long *iend)
{
return gomp_loop_dynamic_next (istart, iend);
}
bool
GOMP_loop_guided_next (long *istart, long *iend)
{
return gomp_loop_guided_next (istart, iend);
}
bool
GOMP_loop_ordered_static_next (long *istart, long *iend)
{
return gomp_loop_ordered_static_next (istart, iend);
}
bool
GOMP_loop_ordered_dynamic_next (long *istart, long *iend)
{
return gomp_loop_ordered_dynamic_next (istart, iend);
}
bool
GOMP_loop_ordered_guided_next (long *istart, long *iend)
{
return gomp_loop_ordered_guided_next (istart, iend);
}
#endif