xref: /netbsd-src/external/gpl3/gcc/dist/libgomp/config/rtems/proc.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Copyright (C) 2015-2022 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   char *end;
82 
83   if (*env == ':')
84     ++env;
85 
86   errno = 0;
87   *count = strtoul (env, &end, 10);
88   if (errno != 0 || end == env)
89     gomp_fatal ("Invalid thread pool count");
90   env = end;
91 
92   if (*env == '$')
93     {
94       ++env;
95       errno = 0;
96       *priority = strtoul (env, &end, 10);
97       if (errno != 0 || end == env)
98 	gomp_fatal ("Invalid thread pool priority");
99       env = end;
100     }
101   else
102     *priority = -1;
103 
104   if (*env != '@')
105     gomp_fatal ("Invalid thread pool scheduler prefix");
106   ++env;
107 
108   len = 0;
109   while (env[len] != '\0' && env[len] != ':')
110     ++len;
111   i = _Sched_Name_to_index (env, len);
112   if (i < 0)
113     gomp_fatal ("Invalid thread pool scheduler");
114   *scheduler = i;
115   env += len;
116 
117   return env;
118 }
119 
120 static void
init_thread_pool_reservoirs(void)121 init_thread_pool_reservoirs (void)
122 {
123   char *env = getenv ("GOMP_RTEMS_THREAD_POOLS");
124   if (env != NULL)
125     {
126       allocate_thread_pool_reservoirs ();
127       while (*env != '\0')
128 	{
129 	  unsigned long count;
130 	  unsigned long priority;
131 	  unsigned long scheduler;
132 	  env = parse_thread_pools (env, &count, &priority, &scheduler);
133 	  allocate_thread_pool_reservoir (count, priority, scheduler);
134 	}
135     }
136 }
137 
138 void
gomp_init_num_threads(void)139 gomp_init_num_threads (void)
140 {
141   gomp_global_icv.nthreads_var = omp_get_num_procs();
142   init_thread_pool_reservoirs ();
143 }
144 
145 unsigned
gomp_dynamic_max_threads(void)146 gomp_dynamic_max_threads (void)
147 {
148   unsigned n_onln = (unsigned) omp_get_num_procs();
149   unsigned nthreads_var = gomp_icv (false)->nthreads_var;
150 
151   if (n_onln > nthreads_var)
152     return nthreads_var;
153   else
154     return n_onln;
155 }
156 
157 int
omp_get_num_procs(void)158 omp_get_num_procs (void)
159 {
160   return sysconf (_SC_NPROCESSORS_ONLN);
161 }
162 
163 ialias (omp_get_num_procs)
164