1169695Skan/* Copyright (C) 2005 Free Software Foundation, Inc.
2169695Skan   Contributed by Richard Henderson <rth@redhat.com>.
3169695Skan
4169695Skan   This file is part of the GNU OpenMP Library (libgomp).
5169695Skan
6169695Skan   Libgomp is free software; you can redistribute it and/or modify it
7169695Skan   under the terms of the GNU Lesser General Public License as published by
8169695Skan   the Free Software Foundation; either version 2.1 of the License, or
9169695Skan   (at your option) any later version.
10169695Skan
11169695Skan   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12169695Skan   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13169695Skan   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
14169695Skan   more details.
15169695Skan
16169695Skan   You should have received a copy of the GNU Lesser General Public License
17169695Skan   along with libgomp; see the file COPYING.LIB.  If not, write to the
18169695Skan   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19169695Skan   MA 02110-1301, USA.  */
20169695Skan
21169695Skan/* As a special exception, if you link this library with other files, some
22169695Skan   of which are compiled with GCC, to produce an executable, this library
23169695Skan   does not by itself cause the resulting executable to be covered by the
24169695Skan   GNU General Public License.  This exception does not however invalidate
25169695Skan   any other reasons why the executable file might be covered by the GNU
26169695Skan   General Public License.  */
27169695Skan
28169695Skan/* This file handles the (bare) PARALLEL construct.  */
29169695Skan
30169695Skan#include "libgomp.h"
31169695Skan
32169695Skan
33169695Skan/* Determine the number of threads to be launched for a PARALLEL construct.
34169695Skan   This algorithm is explicitly described in OpenMP 2.5 section 2.4.1.
35169695Skan   SPECIFIED is a combination of the NUM_THREADS clause and the IF clause.
36169695Skan   If the IF clause is false, SPECIFIED is forced to 1.  When NUM_THREADS
37169695Skan   is not present, SPECIFIED is 0.  */
38169695Skan
39169695Skanunsigned
40169695Skangomp_resolve_num_threads (unsigned specified)
41169695Skan{
42169695Skan  /* Early exit for false IF condition or degenerate NUM_THREADS.  */
43169695Skan  if (specified == 1)
44169695Skan    return 1;
45169695Skan
46169695Skan  /* If this is a nested region, and nested regions are disabled, force
47169695Skan     this team to use only one thread.  */
48169695Skan  if (gomp_thread()->ts.team && !gomp_nest_var)
49169695Skan    return 1;
50169695Skan
51169695Skan  /* If NUM_THREADS not specified, use nthreads_var.  */
52169695Skan  if (specified == 0)
53169695Skan    specified = gomp_nthreads_var;
54169695Skan
55169695Skan  /* If dynamic threads are enabled, bound the number of threads
56169695Skan     that we launch.  */
57169695Skan  if (gomp_dyn_var)
58169695Skan    {
59169695Skan      unsigned dyn = gomp_dynamic_max_threads ();
60169695Skan      if (dyn < specified)
61169695Skan	return dyn;
62169695Skan    }
63169695Skan
64169695Skan  return specified;
65169695Skan}
66169695Skan
67169695Skanvoid
68169695SkanGOMP_parallel_start (void (*fn) (void *), void *data, unsigned num_threads)
69169695Skan{
70169695Skan  num_threads = gomp_resolve_num_threads (num_threads);
71169695Skan  gomp_team_start (fn, data, num_threads, NULL);
72169695Skan}
73169695Skan
74169695Skanvoid
75169695SkanGOMP_parallel_end (void)
76169695Skan{
77169695Skan  gomp_team_end ();
78169695Skan}
79169695Skan
80169695Skan
81169695Skan/* The public OpenMP API for thread and team related inquiries.  */
82169695Skan
83169695Skanint
84169695Skanomp_get_num_threads (void)
85169695Skan{
86169695Skan  struct gomp_team *team = gomp_thread ()->ts.team;
87169695Skan  return team ? team->nthreads : 1;
88169695Skan}
89169695Skan
90169695Skan/* ??? Does this function need to disregard dyn_var?  I don't see
91169695Skan   how else one could get a useable "maximum".  */
92169695Skan
93169695Skanint
94169695Skanomp_get_max_threads (void)
95169695Skan{
96169695Skan  return gomp_resolve_num_threads (0);
97169695Skan}
98169695Skan
99169695Skanint
100169695Skanomp_get_thread_num (void)
101169695Skan{
102169695Skan  return gomp_thread ()->ts.team_id;
103169695Skan}
104169695Skan
105169695Skan/* ??? This isn't right.  The definition of this function is false if any
106169695Skan   of the IF clauses for any of the parallels is false.  Which is not the
107169695Skan   same thing as any outer team having more than one thread.  */
108169695Skan
109169695Skanint omp_in_parallel (void)
110169695Skan{
111169695Skan  struct gomp_team *team = gomp_thread ()->ts.team;
112169695Skan
113169695Skan  while (team)
114169695Skan    {
115169695Skan      if (team->nthreads > 1)
116169695Skan	return true;
117169695Skan      team = team->prev_ts.team;
118169695Skan    }
119169695Skan
120169695Skan  return false;
121169695Skan}
122169695Skan
123169695Skanialias (omp_get_num_threads)
124169695Skanialias (omp_get_max_threads)
125169695Skanialias (omp_get_thread_num)
126169695Skanialias (omp_in_parallel)
127