1 /*
2 * Copyright (c) 2012, 2013
3 * Inferno Nettverk A/S, Norway. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. The above copyright notice, this list of conditions and the following
9 * disclaimer must appear in all copies of the software, derivative works
10 * or modified versions, and any portions thereof, aswell as in all
11 * supporting documentation.
12 * 2. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by
15 * Inferno Nettverk A/S, Norway.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Inferno Nettverk A/S requests users of this software to return to
31 *
32 * Software Distribution Coordinator or sdc@inet.no
33 * Inferno Nettverk A/S
34 * Oslo Research Park
35 * Gaustadall�en 21
36 * NO-0349 Oslo
37 * Norway
38 *
39 * any improvements or extensions that they make and grant Inferno Nettverk A/S
40 * the rights to redistribute these changes.
41 *
42 */
43
44 #include "common.h"
45
46 static const char rcsid[] =
47 "$Id: cpu.c,v 1.25 2013/10/27 15:24:42 karls Exp $";
48
49 int
sockd_setcpusettings(old,new)50 sockd_setcpusettings(old, new)
51 const cpusetting_t *old;
52 const cpusetting_t *new;
53 {
54 #if HAVE_SCHED_SETSCHEDULER || HAVE_SCHED_SETAFFINITY
55 const char *function = "sockd_setcpusettings()";
56 int rc;
57
58 #if HAVE_SCHED_SETSCHEDULER
59 SASSERTX(old->scheduling_isset);
60 SASSERTX(new->scheduling_isset);
61
62 slog(LOG_DEBUG, "%s: old cpu scheduling policy/priority: %s/%d, new: %s/%d",
63 function,
64 numeric2cpupolicy(old->policy),
65 old->param.sched_priority,
66 numeric2cpupolicy(new->policy),
67 new->param.sched_priority);
68
69 if (old->policy != new->policy
70 || old->param.sched_priority != new->param.sched_priority) {
71 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
72 rc = sched_setscheduler(0, new->policy, &new->param);
73 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
74
75 if (rc != 0) {
76 swarn("%s: could not change cpu scheduling policy/priority from "
77 "%s/%d to %s/%d%s",
78 function,
79 numeric2cpupolicy(old->policy),
80 old->param.sched_priority,
81 numeric2cpupolicy(new->policy),
82 new->param.sched_priority,
83 sockscf.state.haveprivs ? "" : " (normally special privileges "
84 "are required for this)");
85
86 return -1;
87 }
88
89 sockscf.state.cpu.policy = new->policy;
90 sockscf.state.cpu.param = new->param;
91 }
92 #endif /* HAVE_SCHED_SETSCHEDULER */
93
94 #if HAVE_SCHED_SETAFFINITY
95 if (new->affinity_isset && (cpu_equal(&old->mask, &new->mask) == 0)) {
96 const size_t setsize = cpu_get_setsize();
97 const long cpuc = sysconf(_SC_NPROCESSORS_ONLN);
98 size_t i, cpus_used, oldcpus_used, errcpus_used;
99 char cpus[2048], oldcpus[sizeof(cpus)], errcpus[sizeof(cpus)];
100
101 if (cpuc == -1)
102 serr("sysconf(_SC_NPROCESSORS_ONLN) failed");
103
104 *cpus = *oldcpus = *errcpus = NUL;
105 cpus_used = oldcpus_used = errcpus_used = 0;
106 for (i = 0; i < setsize; ++i) {
107 if (cpu_isset(i, &old->mask)) {
108 oldcpus_used += snprintf(&oldcpus[oldcpus_used],
109 sizeof(oldcpus) - oldcpus_used,
110 "%ld ", (long)i);
111 }
112
113 if (cpu_isset(i, &new->mask)) {
114 cpus_used += snprintf(&cpus[cpus_used],
115 sizeof(cpus) - cpus_used,
116 "%ld ", (long)i);
117
118 if (i + 1 >= (size_t)cpuc)
119 errcpus_used += snprintf(&errcpus[errcpus_used],
120 sizeof(errcpus) - errcpus_used,
121 "%ld ", (long)i);
122 }
123 }
124
125 slog(LOG_DEBUG, "%s: old cpu affinity: %s, new: %s",
126 function,
127 *oldcpus == NUL ? "<none set>" : oldcpus,
128 *cpus == NUL ? "<none set>" : cpus);
129
130 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
131 rc = cpu_setaffinity(0, sizeof(new->mask), &new->mask);
132 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
133
134 if (rc != 0) {
135 if (*errcpus != NUL)
136 swarn("%s: failed to set new cpu affinity. Probably because the "
137 "configured new mask contains the following cpus which do "
138 "not appear to be present on this system (which as far as we "
139 "can see, has a total of %ld cpus): %s",
140 function, cpuc, errcpus);
141 else
142 swarn("%s: failed to set new cpu affinity using mask %s",
143 function, cpuset2string(&new->mask, NULL, 0));
144
145 return -1;
146 }
147
148 sockscf.state.cpu.mask = new->mask;
149 }
150
151 #endif /* HAVE_SCHED_SETAFFINITY */
152 #endif /* HAVE_SCHED_SETSCHEDULER || HAVE_SCHED_SETAFFINITY */
153
154 #if HAVE_PROCESSOR_BIND
155 #endif /* HAVE_PROCESSOR_BIND */
156
157 return 0;
158 }
159