FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
affinity.c
1/** \cond
2 */
3/***********************************************************************
4 * GNU Lesser General Public License
5 *
6 * This file is part of the GFDL Flexible Modeling System (FMS).
7 *
8 * FMS is free software: you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or (at
11 * your option) any later version.
12 *
13 * FMS is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FMS. If not, see <http://www.gnu.org/licenses/>.
20 **********************************************************************/
21
22#ifndef _GNU_SOURCE
23#define _GNU_SOURCE
24#endif
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdbool.h>
30#include <unistd.h>
31#include <sched.h>
32#include <errno.h>
33#include <sys/resource.h>
34#include <sys/syscall.h>
35#ifdef __APPLE__
36#include <pthread.h>
37#endif
38/** \endcond
39 */
40// skips doc parsing for includes and license
41
42/**
43 * \addtogroup affinity
44 * \@{
45 */
46
47/**
48 * gettid function for systems that do not have this function (e.g. on Mac OS.)
49 */
50#ifndef HAVE_GETTID
51static pid_t gettid(void)
52{
53#if defined(__APPLE__)
54 uint64_t tid64;
55 pthread_threadid_np(NULL, &tid64);
56 pid_t tid = (pid_t)tid64;
57#else
58 pid_t tid = syscall(__NR_gettid);
59#endif
60 return tid;
61}
62#endif
63
64/**
65 * Returns this thread's CPU affinity, if bound to a single core,
66 * or else -1.
67 */
68int get_cpu_affinity(void)
69{
70#ifdef HAVE_SCHED_GETAFFINITY
71 cpu_set_t coremask; /* core affinity mask */
72
73 CPU_ZERO(&coremask);
74 if (sched_getaffinity(gettid(),sizeof(cpu_set_t),&coremask) != 0) {
75 fprintf(stderr,"Unable to get thread %d affinity. %s\n",gettid(),strerror(errno));
76 }
77
78 int cpu;
79 for (cpu=0;cpu < CPU_SETSIZE;cpu++) {
80 if (CPU_ISSET(cpu,&coremask)) {
81 return cpu;
82 }
83 }
84#endif
85 return -1;
86}
87
88/**
89 * Returns this groups CPUSET
90 * and also the CPUSET size or -1 (in case of a storage error)
91 */
92int get_cpuset(int fsz, int *output, int pe, _Bool debug)
93{
94#ifdef HAVE_SCHED_GETAFFINITY
95 cpu_set_t coremask; /* core affinity mask */
96
97 CPU_ZERO(&coremask);
98 if (sched_getaffinity(gettid(),sizeof(cpu_set_t),&coremask) != 0) {
99 fprintf(stderr,"Unable to get thread %d affinity. %s\n",gettid(),strerror(errno));
100 }
101
102 int cpu;
103 int count;
104
105 if (debug) {
106 for (cpu=0;cpu < CPU_SETSIZE;cpu++) {
107 if (CPU_ISSET(cpu,&coremask)) {
108 printf("=> get_cpuset - pe %d: %d\n",pe, cpu);
109 }
110 }
111 }
112
113 count = 0;
114 for (cpu=0;cpu < CPU_SETSIZE;cpu++) {
115 if (CPU_ISSET(cpu,&coremask)) {
116 if (count > fsz) {
117 return -1;
118 }
119 output[count] = cpu;
120 count ++;
121 }
122 }
123 return count;
124#else
125 return fsz;
126#endif
127}
128
129/**
130 * Set CPU affinity to one core.
131 */
132int set_cpu_affinity(int cpu)
133{
134#ifdef HAVE_SCHED_GETAFFINITY
135 cpu_set_t coremask; /* core affinity mask */
136
137 CPU_ZERO(&coremask);
138 CPU_SET(cpu,&coremask);
139 if (sched_setaffinity(gettid(),sizeof(cpu_set_t),&coremask) != 0) {
140 return -1;
141 }
142#endif
143 return 0;
144}
145///@}