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