1 /* Copyright (C) 2008-2014 Free Software Foundation, Inc.
2 This file is part of the UPC runtime library.
3 Written by Gary Funck <gary@intrepid.com>
4 and Nenad Vukicevic <nenad@intrepid.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
28 #include "upc_config.h"
29 #include "upc_sysdep.h"
32 #include "upc_affinity.h"
35 /* The opaque type upc_cpu_avoid_t, forward references this type. */
36 struct upc_cpu_avoid_struct
42 __upc_affinity_supported ()
47 /* Calculate the right affinity for the thread based on
48 the currnet scheduling and NUMA policies. Executed by
49 the monitoring thread. AVOID is a pointer to a data
50 structure that lists cpu's that aren't eligible for
54 __upc_affinity_init (upc_info_p u
, upc_cpu_avoid_p avoid
,
57 const upc_sched_policy_t sched_policy
= u
->sched_policy
;
58 const int num_cpus
= u
->num_cpus
;
59 const int num_nodes
= u
->num_nodes
;
60 int t
, next_sched_cpu
;
61 if (!__upc_numa_init (u
, err_msg
))
63 /* Calculate affinity for each thread. */
64 for (t
= 0, next_sched_cpu
= 0; t
< THREADS
; ++t
)
66 const upc_thread_info_p tinfo
= &u
->thread_info
[t
];
68 int sched_affinity
, mem_affinity
;
71 case GUPCR_SCHED_POLICY_CPU
:
72 /* One cpu = multiple threads */
74 melem
= pelem
% num_nodes
;
75 sched_affinity
= pelem
;
78 case GUPCR_SCHED_POLICY_CPU_STRICT
:
79 /* One cpu = one thread */
80 while (CPU_ISSET (next_sched_cpu
, &avoid
->cpu_set
)
81 && next_sched_cpu
< num_cpus
)
85 if (next_sched_cpu
>= num_cpus
)
87 *err_msg
= "UPC error: unable to allocate CPU for all threads.";
90 pelem
= next_sched_cpu
;
91 melem
= pelem
% num_nodes
;
92 sched_affinity
= pelem
;
96 case GUPCR_SCHED_POLICY_NODE
:
97 /* Use NUMA for node scheduling */
98 if (!__upc_numa_allocate (u
, t
, &sched_affinity
, &mem_affinity
,
103 /* Auto scheduling */
107 tinfo
->sched_affinity
= sched_affinity
;
108 tinfo
->mem_affinity
= mem_affinity
;
113 /* Allocate, and return a pointer to the data structure used to record
114 the list of CPU's that are unavailable. */
117 __upc_affinity_cpu_avoid_new ()
119 upc_cpu_avoid_p avoid
;
120 avoid
= (upc_cpu_avoid_p
) calloc (1, sizeof (upc_cpu_avoid_t
));
129 /* Free the previously allocated data structure that is used
130 to record list of CPU's that are unavailable. */
133 __upc_affinity_cpu_avoid_free (const upc_cpu_avoid_p avoid
)
136 free ((void *) avoid
);
139 /* Mark CPU as being unavailable for allocation. */
142 __upc_affinity_cpu_avoid_set (const int cpu
, const upc_cpu_avoid_p avoid
)
144 CPU_SET (cpu
, &avoid
->cpu_set
);
147 #ifdef DEBUG_AFFINITY
149 upc_sched_policy_to_string (const upc_sched_policy_t sched_policy
)
151 switch (sched_policy
)
153 case GUPCR_SCHED_POLICY_AUTO
:
155 case GUPCR_SCHED_POLICY_NODE
:
157 case GUPCR_SCHED_POLICY_CPU
:
159 case GUPCR_SCHED_POLICY_CPU_STRICT
:
160 return "sched strict";
162 return "sched <unknown>";
166 upc_mem_policy_to_string (const upc_mem_policy_t mem_policy
)
170 case GUPCR_MEM_POLICY_AUTO
:
172 case GUPCR_MEM_POLICY_NODE
:
174 case GUPCR_MEM_POLICY_STRICT
:
177 return "mem <unknown>";
179 #endif /* DEBUG_AFFINITY */
181 /* Set thread's affinity based on the pre-calculated
182 policies. Executed by each thread as the first thing after thread
186 __upc_affinity_set (upc_info_p u
, int thread_id
)
188 const upc_thread_info_p tinfo
= &u
->thread_info
[thread_id
];
189 switch (u
->sched_policy
)
191 case GUPCR_SCHED_POLICY_CPU
:
192 case GUPCR_SCHED_POLICY_CPU_STRICT
:
194 const int sched_affinity
= tinfo
->sched_affinity
;
197 CPU_SET (sched_affinity
, &set
);
198 if (sched_setaffinity (0, sizeof (set
), &set
))
200 __upc_fatal ("Scheduling cannot be set");
204 case GUPCR_SCHED_POLICY_NODE
:
205 __upc_numa_sched_set (u
, thread_id
);
208 /* auto - no scheduling support */
211 /* set memory policy only if we are not AUTO scheduling */
212 if ((u
->sched_policy
!= GUPCR_SCHED_POLICY_AUTO
) &&
213 (u
->mem_policy
!= GUPCR_MEM_POLICY_AUTO
))
214 __upc_numa_memory_affinity_set (u
, thread_id
);
215 #ifdef DEBUG_AFFINITY
216 printf ("affinity: %d (%s,%s) scheduling (%d,%d)\n", thread_id
,
217 upc_sched_policy_to_string (u
->sched_policy
),
218 upc_mem_policy_to_string (u
->mem_policy
),
219 tinfo
->sched_affinity
, tinfo
->mem_affinity
);
220 #endif /* DEBUG_AFFINITY */