"Fossies" - the Fresh Open Source Software Archive

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

    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 int stress_set_mq_size(const char *opt)
   28 {
   29     uint64_t sz;
   30     int mq_size;
   31 
   32     sz = get_uint64(opt);
   33     check_range("mq-size", sz, MIN_MQ_SIZE, MAX_MQ_SIZE);
   34     mq_size = (int)sz;
   35     return set_setting("mq-size", TYPE_ID_INT, &mq_size);
   36 }
   37 
   38 #if defined(HAVE_MQUEUE_H) &&   \
   39     defined(HAVE_LIB_RT) && \
   40     defined(HAVE_MQ_POSIX)
   41 
   42 typedef struct {
   43     uint64_t    value;
   44     bool        stop;
   45 } msg_t;
   46 
   47 static void stress_mq_notify_func(union sigval s)
   48 {
   49     (void)s;
   50 }
   51 
   52 /*
   53  *  stress_mq
   54  *  stress POSIX message queues
   55  */
   56 static int stress_mq(const args_t *args)
   57 {
   58     pid_t pid;
   59     mqd_t mq = -1;
   60     int sz, max_sz, mq_size = DEFAULT_MQ_SIZE;
   61     FILE *fp;
   62     struct mq_attr attr;
   63     char mq_name[64];
   64     bool do_timed;
   65     time_t time_start;
   66     struct timespec abs_timeout;
   67 
   68     if (!get_setting("mq-size", &mq_size)) {
   69         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
   70             mq_size = MAX_MQ_SIZE;
   71         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
   72             mq_size = MIN_MQ_SIZE;
   73     }
   74     sz = mq_size;
   75 
   76     (void)snprintf(mq_name, sizeof(mq_name), "/%s-%i-%" PRIu32,
   77         args->name, args->pid, args->instance);
   78     if ((fp = fopen("/proc/sys/fs/mqueue/msg_default", "r")) != NULL) {
   79         if (fscanf(fp, "%20d", &max_sz) != 1)
   80             max_sz = MAX_MQ_SIZE;
   81         (void)fclose(fp);
   82         if (max_sz < MIN_MQ_SIZE)
   83             max_sz = MIN_MQ_SIZE;
   84         if (max_sz > MAX_MQ_SIZE)
   85             max_sz = MAX_MQ_SIZE;
   86     } else {
   87         max_sz = MAX_MQ_SIZE;
   88     }
   89 
   90     if (sz > max_sz)
   91         sz = max_sz;
   92     /*
   93      *  Determine a workable MQ size if we can't determine it from /proc
   94      */
   95     while (sz > 0) {
   96         attr.mq_flags = 0;
   97         attr.mq_maxmsg = sz;
   98         attr.mq_msgsize = sizeof(msg_t);
   99         attr.mq_curmsgs = 0;
  100 
  101         mq = mq_open(mq_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);
  102         if (mq >= 0)
  103             break;
  104         if (errno == ENOSYS) {
  105             pr_inf("%s: POSIX message queues not implemented, skipping stressor\n",
  106                 args->name);
  107             return EXIT_NOT_IMPLEMENTED;
  108         }
  109         sz--;
  110     }
  111     if (mq < 0) {
  112         pr_fail_dbg("mq_open");
  113         return EXIT_FAILURE;
  114     }
  115     if (sz < mq_size) {
  116         pr_inf("%s: POSIX message queue requested "
  117             "size %d messages, maximum of %d allowed\n",
  118             args->name, mq_size, sz);
  119     }
  120     pr_dbg("%s: POSIX message queue %s with %lu messages\n",
  121         args->name, mq_name, (unsigned long)attr.mq_maxmsg);
  122 
  123     if (time(&time_start) == ((time_t)-1)) {
  124         do_timed = false;
  125         pr_fail_dbg("mq_timed send and receive skipped, can't get time");
  126     } else {
  127         do_timed = true;
  128         abs_timeout.tv_sec = time_start + g_opt_timeout + 1;
  129         abs_timeout.tv_nsec = 0;
  130     }
  131 
  132 
  133 again:
  134     pid = fork();
  135     if (pid < 0) {
  136         if (g_keep_stressing_flag &&
  137             ((errno == EAGAIN) || (errno == ENOMEM)))
  138             goto again;
  139         pr_fail_dbg("fork");
  140         return EXIT_FAILURE;
  141     } else if (pid == 0) {
  142         struct sigevent sigev;
  143 
  144         (void)memset(&sigev, 0, sizeof sigev);
  145         sigev.sigev_notify = SIGEV_THREAD;
  146         sigev.sigev_notify_function = stress_mq_notify_func;
  147         sigev.sigev_notify_attributes = NULL;
  148 
  149         (void)setpgid(0, g_pgrp);
  150         stress_parent_died_alarm();
  151 
  152         while (g_keep_stressing_flag) {
  153             uint64_t i = 0;
  154 
  155             for (;;) {
  156                 msg_t msg;
  157                 int ret;
  158                 const uint64_t timed = (i & 1);
  159 
  160                 if (!(i & 1023)) {
  161 #if defined(__linux__)
  162                     char buffer[1024];
  163 
  164                     /* Read state of queue from mq fd */
  165                     ret = read(mq, buffer, sizeof(buffer));
  166                     if (ret < 0)
  167                         pr_fail_dbg("mq read");
  168 #endif
  169 
  170                     mq_notify(mq, &sigev);
  171                 }
  172 
  173                 /*
  174                  * toggle between timedreceive and receive
  175                  */
  176                 if (do_timed && (timed))
  177                     ret = mq_timedreceive(mq, (char *)&msg, sizeof(msg), NULL, &abs_timeout);
  178                 else
  179                     ret = mq_receive(mq, (char *)&msg, sizeof(msg), NULL);
  180 
  181                 if (ret < 0) {
  182                     pr_fail_dbg(timed ? "mq_timedreceive" : "mq_receive");
  183                     break;
  184                 }
  185                 if (msg.stop)
  186                     break;
  187                 if (g_opt_flags & OPT_FLAGS_VERIFY) {
  188                     if (msg.value != i) {
  189                         pr_fail("%s: mq_receive: expected message "
  190                             "containing 0x%" PRIx64
  191                             " but received 0x%" PRIx64 " instead\n",
  192                             args->name, i, msg.value);
  193                     }
  194                 }
  195                 i++;
  196             }
  197             _exit(EXIT_SUCCESS);
  198         }
  199     } else {
  200         uint64_t i = 0;
  201         int status;
  202         int attr_count = 0;
  203         msg_t msg;
  204 
  205         /* Parent */
  206         (void)setpgid(pid, g_pgrp);
  207 
  208         do {
  209             int ret;
  210             const uint64_t timed = (i & 1);
  211 
  212             (void)memset(&msg, 0, sizeof(msg));
  213             msg.value = get_counter(args);
  214             msg.stop = false;
  215             if ((attr_count++ & 31) == 0) {
  216                 if (mq_getattr(mq, &attr) < 0)
  217                     pr_fail_dbg("mq_getattr");
  218             }
  219 
  220             /*
  221              * toggle between timedsend and send
  222              */
  223             if (do_timed && (timed))
  224                 ret = mq_timedsend(mq, (char *)&msg, sizeof(msg), 1, &abs_timeout);
  225             else
  226                 ret = mq_send(mq, (char *)&msg, sizeof(msg), 1);
  227 
  228             if (ret < 0) {
  229                 if (errno != EINTR)
  230                     pr_fail_dbg(timed ? "mq_timedsend" : "mq_send");
  231                 break;
  232             }
  233             i++;
  234             inc_counter(args);
  235         } while (keep_stressing());
  236 
  237         msg.value = get_counter(args);
  238         msg.stop = true;
  239 
  240         if (mq_send(mq, (char *)&msg, sizeof(msg), 1) < 0) {
  241             pr_fail_dbg("termination mq_send");
  242         }
  243         (void)kill(pid, SIGKILL);
  244         (void)waitpid(pid, &status, 0);
  245 
  246         if (mq_close(mq) < 0)
  247             pr_fail_dbg("mq_close");
  248         if (mq_unlink(mq_name) < 0)
  249             pr_fail_dbg("mq_unlink");
  250     }
  251     return EXIT_SUCCESS;
  252 }
  253 
  254 stressor_info_t stress_mq_info = {
  255     .stressor = stress_mq,
  256     .class = CLASS_SCHEDULER | CLASS_OS
  257 };
  258 #else
  259 stressor_info_t stress_mq_info = {
  260     .stressor = stress_not_implemented,
  261     .class = CLASS_SCHEDULER | CLASS_OS
  262 };
  263 #endif