"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-schedpolicy.c" (15 Mar 2019, 5257 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-schedpolicy.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.50_vs_0.09.51.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if (defined(_POSIX_PRIORITY_SCHEDULING) || defined(__linux__)) && \
   28      !defined(__OpenBSD__) && !defined(__minix__) && !defined(__APPLE__)
   29 
   30 static const int policies[] = {
   31 #if defined(SCHED_IDLE)
   32     SCHED_IDLE,
   33 #endif
   34 #if defined(SCHED_FIFO)
   35     SCHED_FIFO,
   36 #endif
   37 #if defined(SCHED_RR)
   38     SCHED_RR,
   39 #endif
   40 #if defined(SCHED_OTHER)
   41     SCHED_OTHER,
   42 #endif
   43 #if defined(SCHED_BATCH)
   44     SCHED_BATCH,
   45 #endif
   46 };
   47 
   48 static int stress_schedpolicy(const args_t *args)
   49 {
   50     int policy = 0;
   51 
   52     if (SIZEOF_ARRAY(policies) == 0) {
   53         if (args->instance == 0) {
   54             pr_inf("%s: no scheduling policies "
   55                 "available, skipping test\n",
   56                 args->name);
   57         }
   58         return EXIT_NOT_IMPLEMENTED;
   59     }
   60 
   61     do {
   62 #if defined(HAVE_SCHED_GETATTR) && \
   63     defined(HAVE_SCHED_SETATTR)
   64         struct shim_sched_attr attr;
   65 #endif
   66         struct sched_param param;
   67         int ret = 0;
   68         int max_prio, min_prio, rng_prio;
   69         int new_policy = policies[policy];
   70         const pid_t pid = mwc1() ? 0 : args->pid;
   71         const char *new_policy_name = stress_get_sched_name(new_policy);
   72 
   73         switch (new_policy) {
   74 #if defined(SCHED_IDLE)
   75         case SCHED_IDLE:
   76 #endif
   77 #if defined(SCHED_BATCH)
   78         case SCHED_BATCH:
   79 #endif
   80 #if defined(SCHED_OTHER)
   81         case SCHED_OTHER:
   82 #endif
   83             param.sched_priority = 0;
   84             ret = sched_setscheduler(pid, new_policy, &param);
   85             break;
   86 #if defined(SCHED_RR)
   87         case SCHED_RR:
   88 #if defined(HAVE_SCHED_RR_GET_INTERVAL)
   89             {
   90                 struct timespec t;
   91 
   92                 ret = sched_rr_get_interval(pid, &t);
   93                 (void)ret;
   94             }
   95 #endif
   96             CASE_FALLTHROUGH;
   97 #endif
   98 #if defined(SCHED_FIFO)
   99         case SCHED_FIFO:
  100 #endif
  101             min_prio = sched_get_priority_min(policy);
  102             max_prio = sched_get_priority_max(policy);
  103 
  104             /* Check if min/max is supported or not */
  105             if ((min_prio == -1) || (max_prio == -1))
  106                 continue;
  107 
  108             rng_prio = max_prio - min_prio;
  109             if (rng_prio == 0) {
  110                 pr_err("%s: invalid min/max priority "
  111                     "range for scheduling policy %s "
  112                     "(min=%d, max=%d)\n",
  113                     args->name,
  114                     new_policy_name,
  115                     min_prio, max_prio);
  116                 break;
  117             }
  118             param.sched_priority = (mwc32() % (rng_prio)) +
  119                         min_prio;
  120             ret = sched_setscheduler(pid, new_policy, &param);
  121             break;
  122         default:
  123             /* Should never get here */
  124             break;
  125         }
  126         if (ret < 0) {
  127             /*
  128              *  Some systems return EINVAL for non-POSIX
  129              *  scheduling policies, silently ignore these
  130              *  failures.
  131              */
  132             if ((errno != EPERM) && (errno != EINVAL)) {
  133                 pr_fail("%s: sched_setscheduler "
  134                     "failed: errno=%d (%s) "
  135                     "for scheduler policy %s\n",
  136                     args->name, errno, strerror(errno),
  137                     new_policy_name);
  138             }
  139         } else {
  140             ret = sched_getscheduler(pid);
  141             if (ret < 0) {
  142                 pr_fail_err("sched_getscheduler");
  143             } else if (ret != policies[policy]) {
  144                 pr_fail("%s: sched_getscheduler "
  145                     "failed: pid %d has policy %d (%s) "
  146                     "but function returned %d instead\n",
  147                     args->name, (int)pid, new_policy,
  148                     new_policy_name, ret);
  149             }
  150         }
  151 #if defined(_POSIX_PRIORITY_SCHEDULING)
  152         (void)memset(&param, 0, sizeof param);
  153         ret = sched_getparam(pid, &param);
  154         if ((ret < 0) && ((errno != EINVAL) && (errno != EPERM)))
  155             pr_fail_err("sched_getparam failed");
  156 
  157         ret = sched_setparam(pid, &param);
  158         if ((ret < 0) && ((errno != EINVAL) && (errno != EPERM)))
  159             pr_fail_err("sched_setparam");
  160 #endif
  161 
  162 #if defined(HAVE_SCHED_GETATTR) && \
  163     defined(HAVE_SCHED_SETATTR)
  164         /*
  165          *  Nothing too clever here, just get and set for now
  166          */
  167         (void)memset(&attr, 0, sizeof(attr));
  168         attr.size = sizeof(attr);
  169         ret = shim_sched_getattr(pid, &attr, sizeof(attr), 0);
  170         if (ret < 0) {
  171             if (errno != ENOSYS) {
  172                 pr_fail_err("sched_getattr");
  173             }
  174         }
  175 
  176         attr.size = sizeof(attr);
  177         ret = shim_sched_setattr(pid, &attr, 0);
  178         if (ret < 0) {
  179             if (errno != ENOSYS) {
  180                 pr_fail_err("sched_getattr");
  181             }
  182         }
  183 #endif
  184 
  185         (void)shim_sched_yield();
  186         policy++;
  187         policy %= SIZEOF_ARRAY(policies);
  188         inc_counter(args);
  189     } while (keep_stressing());
  190 
  191     return EXIT_SUCCESS;
  192 }
  193 
  194 stressor_info_t stress_schedpolicy_info = {
  195     .stressor = stress_schedpolicy,
  196     .class = CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS
  197 };
  198 #else
  199 stressor_info_t stress_schedpolicy_info = {
  200     .stressor = stress_not_implemented,
  201     .class = CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS
  202 };
  203 #endif