qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

signals.c (3262B)


      1 /*
      2  * linux-user signal handling tests.
      3  *
      4  * Copyright (c) 2021 Linaro Ltd
      5  *
      6  * SPDX-License-Identifier: GPL-2.0-or-later
      7  */
      8 
      9 #include <stdarg.h>
     10 #include <stdint.h>
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #include <unistd.h>
     14 #include <errno.h>
     15 #include <pthread.h>
     16 #include <string.h>
     17 #include <signal.h>
     18 #include <time.h>
     19 #include <sys/time.h>
     20 
     21 static void error1(const char *filename, int line, const char *fmt, ...)
     22 {
     23     va_list ap;
     24     va_start(ap, fmt);
     25     fprintf(stderr, "%s:%d: ", filename, line);
     26     vfprintf(stderr, fmt, ap);
     27     fprintf(stderr, "\n");
     28     va_end(ap);
     29     exit(1);
     30 }
     31 
     32 static int __chk_error(const char *filename, int line, int ret)
     33 {
     34     if (ret < 0) {
     35         error1(filename, line, "%m (ret=%d, errno=%d/%s)",
     36                ret, errno, strerror(errno));
     37     }
     38     return ret;
     39 }
     40 
     41 #define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
     42 
     43 #define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
     44 
     45 /*
     46  * Thread handling
     47  */
     48 typedef struct ThreadJob ThreadJob;
     49 
     50 struct ThreadJob {
     51     int number;
     52     int sleep;
     53     int count;
     54 };
     55 
     56 static pthread_t *threads;
     57 static int max_threads = 10;
     58 __thread int signal_count;
     59 int total_signal_count;
     60 
     61 static void *background_thread_func(void *arg)
     62 {
     63     ThreadJob *job = (ThreadJob *) arg;
     64 
     65     printf("thread%d: started\n", job->number);
     66     while (total_signal_count < job->count) {
     67         usleep(job->sleep);
     68     }
     69     printf("thread%d: saw %d alarms from %d\n", job->number,
     70            signal_count, total_signal_count);
     71     return NULL;
     72 }
     73 
     74 static void spawn_threads(void)
     75 {
     76     int i;
     77     threads = calloc(sizeof(pthread_t), max_threads);
     78 
     79     for (i = 0; i < max_threads; i++) {
     80         ThreadJob *job = calloc(sizeof(ThreadJob), 1);
     81         job->number = i;
     82         job->sleep = i * 1000;
     83         job->count = i * 100;
     84         pthread_create(threads + i, NULL, background_thread_func, job);
     85     }
     86 }
     87 
     88 static void close_threads(void)
     89 {
     90     int i;
     91     for (i = 0; i < max_threads; i++) {
     92         pthread_join(threads[i], NULL);
     93     }
     94     free(threads);
     95     threads = NULL;
     96 }
     97 
     98 static void sig_alarm(int sig, siginfo_t *info, void *puc)
     99 {
    100     if (sig != SIGRTMIN) {
    101         error("unexpected signal");
    102     }
    103     signal_count++;
    104     __atomic_fetch_add(&total_signal_count, 1, __ATOMIC_SEQ_CST);
    105 }
    106 
    107 static void test_signals(void)
    108 {
    109     struct sigaction act;
    110     struct itimerspec it;
    111     timer_t tid;
    112     struct sigevent sev;
    113 
    114     /* Set up SIG handler */
    115     act.sa_sigaction = sig_alarm;
    116     sigemptyset(&act.sa_mask);
    117     act.sa_flags = SA_SIGINFO;
    118     chk_error(sigaction(SIGRTMIN, &act, NULL));
    119 
    120     /* Create POSIX timer */
    121     sev.sigev_notify = SIGEV_SIGNAL;
    122     sev.sigev_signo = SIGRTMIN;
    123     sev.sigev_value.sival_ptr = &tid;
    124     chk_error(timer_create(CLOCK_REALTIME, &sev, &tid));
    125 
    126     it.it_interval.tv_sec = 0;
    127     it.it_interval.tv_nsec = 1000000;
    128     it.it_value.tv_sec = 0;
    129     it.it_value.tv_nsec = 1000000;
    130     chk_error(timer_settime(tid, 0, &it, NULL));
    131 
    132     spawn_threads();
    133 
    134     do {
    135         usleep(1000);
    136     } while (total_signal_count < 2000);
    137 
    138     printf("shutting down after: %d signals\n", total_signal_count);
    139 
    140     close_threads();
    141 
    142     chk_error(timer_delete(tid));
    143 }
    144 
    145 int main(int argc, char **argv)
    146 {
    147     test_signals();
    148     return 0;
    149 }