xref: /netbsd-src/external/gpl3/gcc.old/dist/libgomp/config/rtems/proc.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Copyright (C) 2015-2020 Free Software Foundation, Inc.
2    Contributed by Sebastian Huber <sebastian.huber@embedded-brains.de>.
3 
4    This file is part of the GNU Offloading and Multi Processing Library
5    (libgomp).
6 
7    Libgomp is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15    more details.
16 
17    Under Section 7 of GPL version 3, you are granted additional
18    permissions described in the GCC Runtime Library Exception, version
19    3.1, as published by the Free Software Foundation.
20 
21    You should have received a copy of the GNU General Public License and
22    a copy of the GCC Runtime Library Exception along with this program;
23    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24    <http://www.gnu.org/licenses/>.  */
25 
26 /* This file contains RTEMS specific routines related to counting
27    online processors and dynamic load balancing.  */
28 
29 #include "libgomp.h"
30 #include "pool.h"
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 
36 struct gomp_thread_pool_reservoir **gomp_thread_pool_reservoirs;
37 
38 __thread struct gomp_tls_rtems_data gomp_tls_rtems_data;
39 
40 static void
allocate_thread_pool_reservoirs(void)41 allocate_thread_pool_reservoirs (void)
42 {
43   struct gomp_thread_pool_reservoir **reservoirs;
44   size_t size = _Sched_Count () * sizeof (*reservoirs);
45   reservoirs = gomp_malloc (size);
46   gomp_thread_pool_reservoirs = reservoirs;
47   memset (reservoirs, 0, size);
48 }
49 
50 static void
allocate_thread_pool_reservoir(unsigned long count,unsigned long priority,unsigned long scheduler)51 allocate_thread_pool_reservoir (unsigned long count, unsigned long priority,
52 				unsigned long scheduler)
53 {
54   struct gomp_thread_pool_reservoir *res;
55   struct gomp_thread_pool *pools;
56   unsigned long i;
57   size_t size;
58 
59   res = gomp_thread_pool_reservoirs[scheduler];
60   if (res != NULL)
61     gomp_fatal ("Multiple thread pool reservoir initialization");
62   size = sizeof (*res) + count * (sizeof(pools) + sizeof(*pools));
63   pools = gomp_malloc (size);
64   memset (pools, 0, size);
65   res = (struct gomp_thread_pool_reservoir *) (pools + count);
66   res->index = count;
67   res->priority = priority;
68   gomp_sem_init (&res->available, count);
69   pthread_spin_init (&res->lock, PTHREAD_PROCESS_PRIVATE);
70   for (i = 0; i < count; ++i)
71     res->pools[i] = &pools[i];
72   gomp_thread_pool_reservoirs[scheduler] = res;
73 }
74 
75 static char *
parse_thread_pools(char * env,unsigned long * count,unsigned long * priority,unsigned long * scheduler)76 parse_thread_pools (char *env, unsigned long *count, unsigned long *priority,
77 		    unsigned long *scheduler)
78 {
79   size_t len;
80   int i;
81 
82   if (*env == ':')
83     ++env;
84 
85   errno = 0;
86   *count = strtoul (env, &env, 10);
87   if (errno != 0)
88     gomp_fatal ("Invalid thread pool count");
89 
90   if (*env == '$')
91     {
92       ++env;
93       errno = 0;
94       *priority = strtoul (env, &env, 10);
95       if (errno != 0)
96 	gomp_fatal ("Invalid thread pool priority");
97     }
98   else
99     *priority = -1;
100 
101   if (*env != '@')
102     gomp_fatal ("Invalid thread pool scheduler prefix");
103   ++env;
104 
105   len = 0;
106   while (env[len] != '\0' && env[len] != ':')
107     ++len;
108   i = _Sched_Name_to_index (env, len);
109   if (i < 0)
110     gomp_fatal ("Invalid thread pool scheduler");
111   *scheduler = i;
112   env += len;
113 
114   return env;
115 }
116 
117 static void
init_thread_pool_reservoirs(void)118 init_thread_pool_reservoirs (void)
119 {
120   char *env = getenv ("GOMP_RTEMS_THREAD_POOLS");
121   if (env != NULL)
122     {
123       allocate_thread_pool_reservoirs ();
124       while (*env != '\0')
125 	{
126 	  unsigned long count;
127 	  unsigned long priority;
128 	  unsigned long scheduler;
129 	  env = parse_thread_pools (env, &count, &priority, &scheduler);
130 	  allocate_thread_pool_reservoir (count, priority, scheduler);
131 	}
132     }
133 }
134 
135 void
gomp_init_num_threads(void)136 gomp_init_num_threads (void)
137 {
138   gomp_global_icv.nthreads_var = omp_get_num_procs();
139   init_thread_pool_reservoirs ();
140 }
141 
142 unsigned
gomp_dynamic_max_threads(void)143 gomp_dynamic_max_threads (void)
144 {
145   unsigned n_onln = (unsigned) omp_get_num_procs();
146   unsigned nthreads_var = gomp_icv (false)->nthreads_var;
147 
148   if (n_onln > nthreads_var)
149     return nthreads_var;
150   else
151     return n_onln;
152 }
153 
154 int
omp_get_num_procs(void)155 omp_get_num_procs (void)
156 {
157   return sysconf (_SC_NPROCESSORS_ONLN);
158 }
159 
160 ialias (omp_get_num_procs)
161