"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-clock.c" (15 Mar 2019, 7992 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-clock.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.51_vs_0.09.52.

    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(HAVE_LIB_RT) &&     \
   28     defined(HAVE_CLOCK_GETTIME) &&  \
   29     defined(HAVE_CLOCK_SETTIME)
   30 
   31 typedef struct {
   32     const int   id;     /* Clock ID */
   33     const char  *name;      /* Clock name */
   34 } clock_info_t;
   35 
   36 #define CLOCK_INFO(x)   { x, #x }
   37 
   38 static const clock_info_t clocks[] = {
   39 #if defined(CLOCK_REALTIME)
   40     CLOCK_INFO(CLOCK_REALTIME),
   41 #endif
   42 #if defined(CLOCK_REALTIME_COARSE)
   43     CLOCK_INFO(CLOCK_REALTIME_COARSE),
   44 #endif
   45 #if defined(CLOCK_MONOTONIC)
   46     CLOCK_INFO(CLOCK_MONOTONIC),
   47 #endif
   48 #if defined(CLOCK_MONOTONIC_RAW)
   49     CLOCK_INFO(CLOCK_MONOTONIC_RAW),
   50 #endif
   51 #if defined(CLOCK_MONOTONIC_ACTIVE)
   52     CLOCK_INFO(CLOCK_MONOTONIC_ACTIVE),
   53 #endif
   54 #if defined(CLOCK_BOOTTIME)
   55     CLOCK_INFO(CLOCK_BOOTTIME),
   56 #endif
   57 #if defined(CLOCK_PROCESS_CPUTIME_ID)
   58     CLOCK_INFO(CLOCK_PROCESS_CPUTIME_ID),
   59 #endif
   60 #if defined(CLOCK_THREAD_CPUTIME_ID)
   61     CLOCK_INFO(CLOCK_THREAD_CPUTIME_ID)
   62 #endif
   63 #if defined(CLOCK_MONOTONIC_ACTIVE)
   64     CLOCK_INFO(CLOCK_MONOTONIC_ACTIVE)
   65 #endif
   66 };
   67 
   68 #if defined(HAVE_CLOCK_NANOSLEEP)
   69 static const int clocks_nanosleep[] = {
   70 #if defined(CLOCK_REALTIME)
   71     CLOCK_REALTIME,
   72 #endif
   73 #if defined(CLOCK_MONOTONIC)
   74     CLOCK_MONOTONIC,
   75 #endif
   76 #if defined(CLOCK_THREAD_CPUTIME_ID)
   77     CLOCK_THREAD_CPUTIME_ID
   78 #endif
   79 };
   80 #endif
   81 
   82 #if defined(HAVE_TIMER_CREATE) &&   \
   83     defined(HAVE_TIMER_DELETE) &&   \
   84     defined(HAVE_TIMER_GETTIME) &&  \
   85     defined(HAVE_TIMER_GETOVERRUN) &&   \
   86     defined(HAVE_TIMER_SETTIME) 
   87 static const int timers[] = {
   88 #if defined(CLOCK_REALTIME)
   89     CLOCK_REALTIME,
   90 #endif
   91 #if defined(CLOCK_MONOTONIC)
   92     CLOCK_MONOTONIC,
   93 #endif
   94 #if defined(CLOCK_THREAD_CPUTIME_ID)
   95     CLOCK_THREAD_CPUTIME_ID
   96 #endif
   97 };
   98 #endif
   99 
  100 #if defined(HAVE_CLOCK_NANOSLEEP) ||    \
  101     (defined(HAVE_TIMER_CREATE) &&  \
  102     defined(HAVE_TIMER_DELETE) &&   \
  103     defined(HAVE_TIMER_GETTIME) &&  \
  104     defined(HAVE_TIMER_GETOVERRUN) &&   \
  105     defined(HAVE_TIMER_SETTIME))
  106 /*
  107  *  stress_clock_name()
  108  *  clock id to name
  109  */
  110 static const char *stress_clock_name(int id)
  111 {
  112     size_t i;
  113 
  114     for (i = 0; i < SIZEOF_ARRAY(clocks); i++) {
  115         if (clocks[i].id == id)
  116             return clocks[i].name;
  117     }
  118     return "(unknown clock)";
  119 }
  120 #endif
  121 
  122 /*
  123  *  stress_clock()
  124  *  stress system by rapid clocking system calls
  125  */
  126 static int stress_clock(const args_t *args)
  127 {
  128     do {
  129 #if defined(CLOCK_THREAD_CPUTIME_ID) && \
  130     defined(HAVE_CLOCK_GETTIME) &&  \
  131     defined(HAVE_CLOCK_SETTIME)
  132         {
  133             int ret;
  134             struct timespec t;
  135 
  136             /*
  137              *  Exercise setting local thread CPU timer
  138              */
  139             ret = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t);
  140             if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY) &&
  141                 (errno != EINVAL) && (errno != ENOSYS))
  142                 pr_fail("%s: clock_gettime failed for "
  143                     "timer 'CLOCK_THREAD_CPUTIME_ID', errno=%d (%s)\n",
  144                     args->name, errno, strerror(errno));
  145 
  146             /*
  147              *  According to clock_settime(2), setting the timer
  148              *  CLOCK_THREAD_CPUTIME_ID is not possible on Linux.
  149              *  Try to set it and ignore the result because it will
  150              *  currently return -EINVAL, but it may not do so in the
  151              *  future.
  152              */
  153             ret = clock_settime(CLOCK_THREAD_CPUTIME_ID, &t);
  154             (void)ret;
  155         }
  156 #endif
  157 
  158 #if defined(HAVE_CLOCK_GETRES)
  159         {
  160             size_t i;
  161             struct timespec t;
  162 
  163             /*
  164              *  Exercise clock_getres and clock_gettime for each clock
  165              */
  166             for (i = 0; i < SIZEOF_ARRAY(clocks); i++) {
  167                 int ret;
  168 
  169                 ret = clock_getres(clocks[i].id, &t);
  170                 if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY) &&
  171                         (errno != EINVAL) && (errno != ENOSYS))
  172                     pr_fail("%s: clock_getres failed for "
  173                         "timer '%s', errno=%d (%s)\n",
  174                             args->name, clocks[i].name, errno, strerror(errno));
  175                 ret = clock_gettime(clocks[i].id, &t);
  176                 if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY) &&
  177                         (errno != EINVAL) && (errno != ENOSYS))
  178                     pr_fail("%s: clock_gettime failed for "
  179                         "timer '%s', errno=%d (%s)\n",
  180                         args->name, clocks[i].name, errno, strerror(errno));
  181             }
  182         }
  183 #endif
  184 
  185 #if defined(HAVE_CLOCK_NANOSLEEP)
  186         {
  187             size_t i;
  188             struct timespec t;
  189 
  190             /*
  191              *  Exercise clock_nanosleep for each clock
  192              */
  193             for (i = 0; i < SIZEOF_ARRAY(clocks_nanosleep); i++) {
  194                 int ret;
  195 
  196                 t.tv_sec = 0;
  197                 t.tv_nsec = 25000;
  198                 /*
  199                  *  Calling with TIMER_ABSTIME will force
  200                  *  clock_nanosleep() to return immediately
  201                  */
  202                 ret = clock_nanosleep(clocks_nanosleep[i], TIMER_ABSTIME, &t, NULL);
  203                 if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY))
  204                     pr_fail("%s: clock_nanosleep failed for timer '%s', "
  205                         "errno=%d (%s)\n", args->name,
  206                         stress_clock_name(clocks_nanosleep[i]),
  207                         errno, strerror(errno));
  208             }
  209         }
  210 #endif
  211 
  212 #if defined(HAVE_TIMER_CREATE) &&   \
  213     defined(HAVE_TIMER_DELETE) &&   \
  214     defined(HAVE_TIMER_GETTIME) &&  \
  215     defined(HAVE_TIMER_GETOVERRUN) &&   \
  216     defined(HAVE_TIMER_SETTIME) 
  217         {
  218             size_t i;
  219 
  220             /*
  221              *  Stress the timers
  222              */
  223             for (i = 0; i < SIZEOF_ARRAY(timers); i++) {
  224                 timer_t timer_id;
  225                 struct itimerspec its;
  226                 struct sigevent sevp;
  227                 int64_t loops = 1000000;
  228                 int ret;
  229 
  230                 (void)memset(&sevp, 0, sizeof(sevp));
  231                 sevp.sigev_notify = SIGEV_NONE;
  232                 ret = timer_create(timers[i], &sevp, &timer_id);
  233                 if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY)) {
  234                     if ((errno == EINVAL) || (errno == EPERM))
  235                         continue;
  236                     pr_fail("%s: timer_create failed for timer '%s', "
  237                         "errno=%d (%s)\n", args->name,
  238                         stress_clock_name(timers[i]),
  239                         errno, strerror(errno));
  240                     continue;
  241                 }
  242 
  243                 /* One shot mode, for 50000 ns */
  244                 its.it_value.tv_sec = 0;
  245                 its.it_value.tv_nsec = 50000;
  246                 its.it_interval.tv_sec = 0;
  247                 its.it_interval.tv_nsec = 0;
  248 
  249                 ret = timer_settime(timer_id, 0, &its, NULL);
  250                 if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY)) {
  251                     pr_fail("%s: timer_settime failed for timer '%s', "
  252                         "errno=%d (%s)\n", args->name,
  253                         stress_clock_name(timers[i]),
  254                         errno, strerror(errno));
  255                     goto timer_delete;
  256                 }
  257 
  258                 do {
  259                     ret = timer_gettime(timer_id, &its);
  260                     if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY)) {
  261                         pr_fail("%s: timer_gettime failed for timer '%s', "
  262                             "errno=%d (%s)\n", args->name,
  263                             stress_clock_name(timers[i]),
  264                             errno, strerror(errno));
  265                         goto timer_delete;
  266                     }
  267                     ret = timer_getoverrun(timer_id);
  268                     (void)ret;
  269 
  270                     loops--;
  271                 } while ((loops > 0) && g_keep_stressing_flag && (its.it_value.tv_nsec != 0));
  272 
  273 timer_delete:
  274                 ret = timer_delete(timer_id);
  275                 if ((ret < 0) && (g_opt_flags & OPT_FLAGS_VERIFY)) {
  276                     pr_fail("%s: timer_delete failed for timer '%s', "
  277                         "errno=%d (%s)\n", args->name,
  278                         stress_clock_name(timers[i]),
  279                         errno, strerror(errno));
  280                     break;
  281                 }
  282             }
  283         }
  284 #endif
  285         inc_counter(args);
  286     } while (keep_stressing());
  287 
  288     return EXIT_SUCCESS;
  289 }
  290 
  291 stressor_info_t stress_clock_info = {
  292     .stressor = stress_clock,
  293     .class = CLASS_INTERRUPT | CLASS_OS
  294 };
  295 #else
  296 stressor_info_t stress_clock_info = {
  297     .stressor = stress_not_implemented,
  298     .class = CLASS_INTERRUPT | CLASS_OS
  299 };
  300 #endif