"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-timerfd.c" (15 Mar 2019, 5352 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-timerfd.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 #define COUNT_MAX       (256)
   28 #define TIMERFD_MAX     (256)
   29 
   30 /*
   31  *  stress_set_timerfd_freq()
   32  *  set timer frequency from given option
   33  */
   34 int stress_set_timerfd_freq(const char *opt)
   35 {
   36     uint64_t timerfd_freq;
   37 
   38     timerfd_freq = get_uint64(opt);
   39     check_range("timerfd-freq", timerfd_freq,
   40         MIN_TIMERFD_FREQ, MAX_TIMERFD_FREQ);
   41     return set_setting("timerfd-freq", TYPE_ID_UINT64, &timerfd_freq);
   42 }
   43 
   44 #if defined(HAVE_SYS_TIMERFD_H)
   45 
   46 static double rate_ns;
   47 
   48 /*
   49  *  stress_timerfd_set()
   50  *  set timerfd, ensure it is never zero
   51  */
   52 static void stress_timerfd_set(struct itimerspec *timer)
   53 {
   54     double rate;
   55 
   56     if (g_opt_flags & OPT_FLAGS_TIMERFD_RAND) {
   57         /* Mix in some random variation */
   58         double r = ((double)(mwc32() % 10000) - 5000.0) / 40000.0;
   59         rate = rate_ns + (rate_ns * r);
   60     } else {
   61         rate = rate_ns;
   62     }
   63 
   64     timer->it_value.tv_sec = (time_t)rate / 1000000000;
   65     timer->it_value.tv_nsec = (suseconds_t)rate % 1000000000;
   66 
   67     if (timer->it_value.tv_sec == 0 &&
   68         timer->it_value.tv_nsec < 1)
   69         timer->it_value.tv_nsec = 1;
   70 
   71     timer->it_interval.tv_sec = timer->it_value.tv_sec;
   72     timer->it_interval.tv_nsec = timer->it_value.tv_nsec;
   73 }
   74 
   75 /*
   76  *  stress_timerfd
   77  *  stress timerfd
   78  */
   79 static int stress_timerfd(const args_t *args)
   80 {
   81     struct itimerspec timer;
   82     uint64_t timerfd_freq = DEFAULT_TIMERFD_FREQ;
   83     int timerfd[TIMERFD_MAX], procfd, count = 0, i, max_timerfd = -1;
   84     char filename[PATH_MAX];
   85 
   86     if (!get_setting("timerfd-freq", &timerfd_freq)) {
   87         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
   88             timerfd_freq = MAX_TIMERFD_FREQ;
   89         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
   90             timerfd_freq = MIN_TIMERFD_FREQ;
   91     }
   92     rate_ns = timerfd_freq ? 1000000000.0 / timerfd_freq : 1000000000.0;
   93 
   94     for (i = 0; i < TIMERFD_MAX; i++) {
   95         timerfd[i] = timerfd_create(CLOCK_REALTIME, 0);
   96         if (timerfd[i] < 0) {
   97             if ((errno != EMFILE) &&
   98                 (errno != ENFILE) &&
   99                 (errno != ENOMEM)) {
  100                 pr_fail_err("timerfd_create");
  101                 return EXIT_FAILURE;
  102             }
  103         }
  104         count++;
  105         if (max_timerfd < timerfd[i])
  106             max_timerfd = timerfd[i];
  107     }
  108 
  109     if (count == 0) {
  110         pr_fail_err("timerfd_create, no timers created");
  111         return EXIT_FAILURE;
  112     }
  113     count = 0;
  114 
  115     stress_timerfd_set(&timer);
  116     for (i = 0; i < TIMERFD_MAX; i++) {
  117         if (timerfd_settime(timerfd[i], 0, &timer, NULL) < 0) {
  118             pr_fail_err("timer_settime");
  119             (void)close(timerfd[i]);
  120             return EXIT_FAILURE;
  121         }
  122     }
  123 
  124     (void)snprintf(filename, sizeof(filename), "/proc/%d/fdinfo/%d",
  125         (int)args->pid, timerfd[0]);
  126     procfd = open(filename, O_RDONLY);
  127 
  128     do {
  129         int ret;
  130         uint64_t exp;
  131         struct itimerspec value;
  132         struct timeval timeout;
  133         fd_set rdfs;
  134 
  135         FD_ZERO(&rdfs);
  136         for (i = 0; i < TIMERFD_MAX; i++)
  137             FD_SET(timerfd[i], &rdfs);
  138 
  139         timeout.tv_sec = 0;
  140         timeout.tv_usec = 500000;
  141 
  142         if (!g_keep_stressing_flag)
  143             break;
  144         ret = select(max_timerfd + 1, &rdfs, NULL, NULL, &timeout);
  145         if (ret < 0) {
  146             if (errno == EINTR)
  147                 continue;
  148             pr_fail_err("select");
  149             break;
  150         }
  151         if (ret < 1)
  152             continue; /* Timeout */
  153 
  154         for (i = 0; i < TIMERFD_MAX; i++) {
  155             if (!FD_ISSET(timerfd[i], &rdfs))
  156                 continue;
  157 
  158             ret = read(timerfd[i], &exp, sizeof exp);
  159             if (ret < 0) {
  160                 pr_fail_err("timerfd read");
  161                 break;
  162             }
  163             if (timerfd_gettime(timerfd[i], &value) < 0) {
  164                 pr_fail_err("timerfd_gettime");
  165                 break;
  166             }
  167             if (g_opt_flags & OPT_FLAGS_TIMERFD_RAND) {
  168                 stress_timerfd_set(&timer);
  169                 if (timerfd_settime(timerfd[i], 0, &timer, NULL) < 0) {
  170                     pr_fail_err("timer_settime");
  171                     break;
  172                 }
  173             }
  174             inc_counter(args);
  175         }
  176 
  177         /*
  178          *  Periodically read /proc/$pid/fdinfo/$timerfd,
  179          *  we don't care about failures, we just want to
  180          *  exercise this interface
  181          */
  182         if (LIKELY(procfd > -1) && UNLIKELY(count++ >= COUNT_MAX)) {
  183             ret = lseek(procfd, 0, SEEK_SET);
  184             if (LIKELY(ret == 0)) {
  185                 char buffer[4096];
  186 
  187                 ret = read(procfd, buffer, sizeof(buffer));
  188                 (void)ret;
  189             }
  190             count = 0;
  191         }
  192     } while (keep_stressing());
  193 
  194     for (i = 0; i < TIMERFD_MAX; i++) {
  195         if (timerfd[i] > 0)
  196             (void)close(timerfd[i]);
  197     }
  198     if (procfd > -1)
  199         (void)close(procfd);
  200 
  201     return EXIT_SUCCESS;
  202 }
  203 
  204 stressor_info_t stress_timerfd_info = {
  205     .stressor = stress_timerfd,
  206     .class = CLASS_INTERRUPT | CLASS_OS
  207 };
  208 #else
  209 stressor_info_t stress_timerfd_info = {
  210     .stressor = stress_not_implemented,
  211     .class = CLASS_INTERRUPT | CLASS_OS
  212 };
  213 #endif