"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-sem-sysv.c" (15 Mar 2019, 6969 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-sem-sysv.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_SEM_SYSV)
   28 typedef union _semun {
   29     int              val;   /* Value for SETVAL */
   30     struct semid_ds *buf;   /* Buffer for IPC_STAT, IPC_SET */
   31     unsigned short  *array; /* Array for GETALL, SETALL */
   32     struct seminfo  *__buf; /* Buffer for IPC_INFO (Linux-specific) */
   33 } semun_t;
   34 #endif
   35 
   36 int stress_set_semaphore_sysv_procs(const char *opt)
   37 {
   38     uint64_t semaphore_sysv_procs;
   39 
   40     semaphore_sysv_procs = get_uint64(opt);
   41     check_range("sem-sysv-procs", semaphore_sysv_procs,
   42         MIN_SEMAPHORE_PROCS, MAX_SEMAPHORE_PROCS);
   43     return set_setting("sem-sysv-procs", TYPE_ID_UINT64, &semaphore_sysv_procs);
   44 }
   45 
   46 #if defined(HAVE_SEM_SYSV)
   47 
   48 /*
   49  *  stress_semaphore_sysv_init()
   50  *  initialise a System V semaphore
   51  */
   52 static void stress_semaphore_sysv_init(void)
   53 {
   54     int count = 0;
   55 
   56     while (count < 100) {
   57         g_shared->sem_sysv.key_id = (key_t)mwc16();
   58         g_shared->sem_sysv.sem_id =
   59             semget(g_shared->sem_sysv.key_id, 1,
   60                 IPC_CREAT | S_IRUSR | S_IWUSR);
   61         if (g_shared->sem_sysv.sem_id >= 0)
   62             break;
   63 
   64         count++;
   65     }
   66 
   67     if (g_shared->sem_sysv.sem_id >= 0) {
   68         semun_t arg;
   69 
   70         arg.val = 1;
   71         if (semctl(g_shared->sem_sysv.sem_id, 0, SETVAL, arg) == 0) {
   72             g_shared->sem_sysv.init = true;
   73             return;
   74         }
   75         /* Clean up */
   76         (void)semctl(g_shared->sem_sysv.sem_id, 0, IPC_RMID);
   77     }
   78 
   79     if (g_opt_sequential) {
   80         pr_inf("semaphore init (System V) failed: errno=%d: "
   81             "(%s), skipping semaphore stressor\n",
   82             errno, strerror(errno));
   83     } else {
   84         pr_err("semaphore init (System V) failed: errno=%d: "
   85             "(%s)\n", errno, strerror(errno));
   86         _exit(EXIT_FAILURE);
   87     }
   88 }
   89 
   90 /*
   91  *  stress_semaphore_sysv_destory()
   92  *  destroy a System V semaphore
   93  */
   94 static void stress_semaphore_sysv_deinit(void)
   95 {
   96     if (g_shared->sem_sysv.init)
   97         (void)semctl(g_shared->sem_sysv.sem_id, 0, IPC_RMID);
   98 }
   99 
  100 /*
  101  *  semaphore_sysv_thrash()
  102  *  exercise the semaphore
  103  */
  104 static void semaphore_sysv_thrash(const args_t *args)
  105 {
  106     const int sem_id = g_shared->sem_sysv.sem_id;
  107 
  108     do {
  109         int i;
  110 #if defined(HAVE_SEMTIMEDOP) && \
  111     defined(HAVE_CLOCK_GETTIME)
  112         struct timespec timeout;
  113 
  114         if (clock_gettime(CLOCK_REALTIME, &timeout) < 0) {
  115             pr_fail_dbg("clock_gettime");
  116             return;
  117         }
  118         timeout.tv_sec++;
  119 #endif
  120 
  121         for (i = 0; i < 1000; i++) {
  122             struct sembuf semwait, semsignal;
  123 
  124             semwait.sem_num = 0;
  125             semwait.sem_op = -1;
  126             semwait.sem_flg = SEM_UNDO;
  127 
  128             semsignal.sem_num = 0;
  129             semsignal.sem_op = 1;
  130             semsignal.sem_flg = SEM_UNDO;
  131 
  132 #if defined(HAVE_SEMTIMEDOP) && \
  133     defined(HAVE_CLOCK_GETTIME)
  134             if (semtimedop(sem_id, &semwait, 1, &timeout) < 0) {
  135 #else
  136             if (semop(sem_id, &semwait, 1) < 0) {
  137 #endif
  138                 if (errno == EAGAIN)
  139                     goto timed_out;
  140                 if (errno != EINTR)
  141                     pr_fail_dbg("semop wait");
  142                 break;
  143             }
  144             if (semop(sem_id, &semsignal, 1) < 0) {
  145                 if (errno != EINTR)
  146                     pr_fail_dbg("semop signal");
  147                 break;
  148             }
  149 timed_out:
  150             if (!keep_stressing())
  151                 break;
  152             inc_counter(args);
  153         }
  154 #if defined(IPC_STAT)
  155         {
  156             struct semid_ds ds;
  157             semun_t s;
  158 
  159             s.buf = &ds;
  160             if (semctl(sem_id, 0, IPC_STAT, &s) < 0)
  161                 pr_fail_dbg("semctl IPC_STAT");
  162         }
  163 #endif
  164 #if defined(SEM_STAT)
  165         {
  166             struct semid_ds ds;
  167             semun_t s;
  168 
  169             s.buf = &ds;
  170             if (semctl(sem_id, 0, SEM_STAT, &s) < 0)
  171                 pr_fail_dbg("semctl SEM_STAT");
  172         }
  173 #endif
  174 #if defined(IPC_INFO) && defined(__linux__)
  175         {
  176             struct seminfo si;
  177             semun_t s;
  178 
  179             s.__buf = &si;
  180             if (semctl(sem_id, 0, IPC_INFO, &s) < 0)
  181                 pr_fail_dbg("semctl IPC_INFO");
  182         }
  183 #endif
  184 #if defined(SEM_INFO) && defined(__linux__)
  185         {
  186             struct seminfo si;
  187             semun_t s;
  188 
  189             s.__buf = &si;
  190             if (semctl(sem_id, 0, SEM_INFO, &s) < 0)
  191                 pr_fail_dbg("semctl SEM_INFO");
  192         }
  193 #endif
  194 #if defined(GETVAL)
  195         if (semctl(sem_id, 0, GETVAL) < 0)
  196             pr_fail_dbg("semctl GETVAL");
  197 #endif
  198 #if defined(GETPID)
  199         if (semctl(sem_id, 0, GETPID) < 0)
  200             pr_fail_dbg("semctl GETPID");
  201 #endif
  202 #if defined(GETNCNT)
  203         if (semctl(sem_id, 0, GETNCNT) < 0)
  204             pr_fail_dbg("semctl GETNCNT");
  205 #endif
  206 #if defined(GEZCNT)
  207         if (semctl(sem_id, 0, GETZCNT) < 0)
  208             pr_fail_dbg("semctl GETZCNT");
  209 #endif
  210     } while (keep_stressing());
  211 }
  212 
  213 /*
  214  *  semaphore_sysv_spawn()
  215  *  spawn a process
  216  */
  217 static pid_t semaphore_sysv_spawn(const args_t *args)
  218 {
  219     pid_t pid;
  220 
  221 again:
  222     pid = fork();
  223     if (pid < 0) {
  224         if (g_keep_stressing_flag && (errno == EAGAIN))
  225             goto again;
  226         return -1;
  227     }
  228     if (pid == 0) {
  229         (void)setpgid(0, g_pgrp);
  230         stress_parent_died_alarm();
  231 
  232         semaphore_sysv_thrash(args);
  233         _exit(EXIT_SUCCESS);
  234     }
  235     (void)setpgid(pid, g_pgrp);
  236     return pid;
  237 }
  238 
  239 /*
  240  *  stress_sem_sysv()
  241  *  stress system by sem ops
  242  */
  243 static int stress_sem_sysv(const args_t *args)
  244 {
  245     pid_t pids[MAX_SEMAPHORE_PROCS];
  246     uint64_t i;
  247     uint64_t semaphore_sysv_procs = DEFAULT_SEMAPHORE_PROCS;
  248 
  249     if (!get_setting("sem-sysv-procs", &semaphore_sysv_procs)) {
  250         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  251             semaphore_sysv_procs = MAX_SEMAPHORE_PROCS;
  252         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  253             semaphore_sysv_procs = MIN_SEMAPHORE_PROCS;
  254     }
  255 
  256     if (!g_shared->sem_sysv.init) {
  257         pr_err("%s: aborting, semaphore not initialised\n", args->name);
  258         return EXIT_FAILURE;
  259     }
  260 
  261     (void)memset(pids, 0, sizeof(pids));
  262     for (i = 0; i < semaphore_sysv_procs; i++) {
  263         pids[i] = semaphore_sysv_spawn(args);
  264         if (!g_keep_stressing_flag || pids[i] < 0)
  265             goto reap;
  266     }
  267     /* Wait for termination */
  268     while (keep_stressing())
  269         (void)shim_usleep(100000);
  270 reap:
  271     for (i = 0; i < semaphore_sysv_procs; i++) {
  272         if (pids[i] > 0)
  273             (void)kill(pids[i], SIGKILL);
  274     }
  275     for (i = 0; i < semaphore_sysv_procs; i++) {
  276         if (pids[i] > 0) {
  277             int status;
  278 
  279             (void)waitpid(pids[i], &status, 0);
  280         }
  281     }
  282 
  283     return EXIT_SUCCESS;
  284 }
  285 
  286 stressor_info_t stress_sem_sysv_info = {
  287     .stressor = stress_sem_sysv,
  288     .init = stress_semaphore_sysv_init,
  289     .deinit = stress_semaphore_sysv_deinit,
  290     .class = CLASS_OS | CLASS_SCHEDULER
  291 };
  292 #else
  293 stressor_info_t stress_sem_sysv_info = {
  294     .stressor = stress_not_implemented,
  295     .class = CLASS_OS | CLASS_SCHEDULER
  296 };
  297 #endif