(root)/
glibc-2.38/
rt/
tst-timer4.c
       1  /* Tests for POSIX timer implementation.
       2     Copyright (C) 2004-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; see the file COPYING.LIB.  If
      17     not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <signal.h>
      21  #include <stdio.h>
      22  #include <string.h>
      23  #include <time.h>
      24  #include <unistd.h>
      25  #include <stdint.h>
      26  #if _POSIX_THREADS && defined SA_SIGINFO
      27  # include <pthread.h>
      28  
      29  # ifndef TEST_CLOCK
      30  #  define TEST_CLOCK		CLOCK_REALTIME
      31  # endif
      32  
      33  pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
      34  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
      35  
      36  timer_t timer_none, timer_sig1, timer_sig2, timer_thr1, timer_thr2;
      37  
      38  int thr1_cnt, thr1_err;
      39  union sigval thr1_sigval;
      40  struct timespec thr1_ts;
      41  
      42  static void
      43  thr1 (union sigval sigval)
      44  {
      45    pthread_mutex_lock (&lock);
      46    thr1_err = clock_gettime (TEST_CLOCK, &thr1_ts);
      47    if (thr1_cnt >= 5)
      48      {
      49        struct itimerspec it = { };
      50        thr1_err |= timer_settime (timer_thr1, 0, &it, NULL);
      51      }
      52    thr1_sigval = sigval;
      53    ++thr1_cnt;
      54    pthread_cond_signal (&cond);
      55    pthread_mutex_unlock (&lock);
      56  }
      57  
      58  int thr2_cnt, thr2_err;
      59  union sigval thr2_sigval;
      60  size_t thr2_guardsize;
      61  struct timespec thr2_ts;
      62  
      63  static void
      64  thr2 (union sigval sigval)
      65  {
      66    pthread_attr_t nattr;
      67    int err = 0;
      68    size_t guardsize = -1;
      69    int ret = pthread_getattr_np (pthread_self (), &nattr);
      70    if (ret)
      71      {
      72        errno = ret;
      73        printf ("*** pthread_getattr_np failed: %m\n");
      74        err = 1;
      75      }
      76    else
      77      {
      78        ret = pthread_attr_getguardsize (&nattr, &guardsize);
      79        if (ret)
      80          {
      81            errno = ret;
      82            printf ("*** pthread_attr_getguardsize failed: %m\n");
      83            err = 1;
      84          }
      85        if (pthread_attr_destroy (&nattr) != 0)
      86          {
      87            puts ("*** pthread_attr_destroy failed");
      88            err = 1;
      89          }
      90      }
      91    pthread_mutex_lock (&lock);
      92    thr2_err = clock_gettime (TEST_CLOCK, &thr2_ts) | err;
      93    if (thr2_cnt >= 5)
      94      {
      95        struct itimerspec it = { };
      96        thr2_err |= timer_settime (timer_thr2, 0, &it, NULL);
      97      }
      98    thr2_sigval = sigval;
      99    ++thr2_cnt;
     100    thr2_guardsize = guardsize;
     101    pthread_cond_signal (&cond);
     102    pthread_mutex_unlock (&lock);
     103  }
     104  
     105  volatile int sig1_cnt, sig1_err;
     106  volatile union sigval sig1_sigval;
     107  struct timespec sig1_ts;
     108  
     109  static void
     110  sig1_handler (int sig, siginfo_t *info, void *ctx)
     111  {
     112    int err = 0;
     113    if (sig != SIGRTMIN) err |= 1 << 0;
     114    if (info->si_signo != SIGRTMIN) err |= 1 << 1;
     115    if (info->si_code != SI_TIMER) err |= 1 << 2;
     116    if (clock_gettime (TEST_CLOCK, &sig1_ts) != 0)
     117      err |= 1 << 3;
     118    if (sig1_cnt >= 5)
     119      {
     120        struct itimerspec it = { };
     121        if (timer_settime (timer_sig1, 0, &it, NULL))
     122  	err |= 1 << 4;
     123      }
     124    sig1_err |= err;
     125    sig1_sigval = info->si_value;
     126    ++sig1_cnt;
     127  }
     128  
     129  volatile int sig2_cnt, sig2_err;
     130  volatile union sigval sig2_sigval;
     131  struct timespec sig2_ts;
     132  
     133  static void
     134  sig2_handler (int sig, siginfo_t *info, void *ctx)
     135  {
     136    int err = 0;
     137    if (sig != SIGRTMIN + 1) err |= 1 << 0;
     138    if (info->si_signo != SIGRTMIN + 1) err |= 1 << 1;
     139    if (info->si_code != SI_TIMER) err |= 1 << 2;
     140    if (clock_gettime (TEST_CLOCK, &sig2_ts) != 0)
     141      err |= 1 << 3;
     142    if (sig2_cnt >= 5)
     143      {
     144        struct itimerspec it = { };
     145        if (timer_settime (timer_sig2, 0, &it, NULL))
     146  	err |= 1 << 4;
     147      }
     148    sig2_err |= err;
     149    sig2_sigval = info->si_value;
     150    ++sig2_cnt;
     151  }
     152  
     153  /* Check if end is later or equal to start + nsec.  */
     154  static int
     155  check_ts (const char *name, const struct timespec *start,
     156  	  const struct timespec *end, long msec)
     157  {
     158    struct timespec ts = *start;
     159  
     160    ts.tv_sec += msec / 1000000;
     161    ts.tv_nsec += (msec % 1000000) * 1000;
     162    if (ts.tv_nsec >= 1000000000)
     163      {
     164        ++ts.tv_sec;
     165        ts.tv_nsec -= 1000000000;
     166      }
     167    if (end->tv_sec < ts.tv_sec
     168        || (end->tv_sec == ts.tv_sec && end->tv_nsec < ts.tv_nsec))
     169      {
     170        printf ("\
     171  *** timer %s invoked too soon: %ld.%09jd instead of expected %ld.%09jd\n",
     172  	      name, (long) end->tv_sec, (intmax_t) end->tv_nsec,
     173  	      (long) ts.tv_sec, (intmax_t) ts.tv_nsec);
     174        return 1;
     175      }
     176    else
     177      return 0;
     178  }
     179  
     180  #define TEST_FUNCTION do_test ()
     181  static int
     182  do_test (void)
     183  {
     184    int result = 0;
     185  
     186  #ifdef TEST_CLOCK_MISSING
     187    const char *missing = TEST_CLOCK_MISSING (TEST_CLOCK);
     188    if (missing != NULL)
     189      {
     190        printf ("%s missing, skipping test\n", missing);
     191        return 0;
     192      }
     193  #endif
     194  
     195    struct timespec ts;
     196    if (clock_gettime (TEST_CLOCK, &ts) != 0)
     197      {
     198        printf ("*** clock_gettime failed: %m\n");
     199        result = 1;
     200      }
     201    else
     202      printf ("clock_gettime returned timespec = { %ld, %jd }\n",
     203  	    (long) ts.tv_sec, (intmax_t) ts.tv_nsec);
     204  
     205    if (clock_getres (TEST_CLOCK, &ts) != 0)
     206      {
     207        printf ("*** clock_getres failed: %m\n");
     208        result = 1;
     209      }
     210    else
     211      printf ("clock_getres returned timespec = { %ld, %jd }\n",
     212  	    (long) ts.tv_sec, (intmax_t) ts.tv_nsec);
     213  
     214    struct sigevent ev;
     215    memset (&ev, 0x11, sizeof (ev));
     216    ev.sigev_notify = SIGEV_NONE;
     217    if (timer_create (TEST_CLOCK, &ev, &timer_none) != 0)
     218      {
     219        printf ("*** timer_create for timer_none failed: %m\n");
     220        return 1;
     221      }
     222  
     223    struct sigaction sa = { .sa_sigaction = sig1_handler,
     224  			  .sa_flags = SA_SIGINFO };
     225    sigemptyset (&sa.sa_mask);
     226    sigaction (SIGRTMIN, &sa, NULL);
     227    sa.sa_sigaction = sig2_handler;
     228    sigaction (SIGRTMIN + 1, &sa, NULL);
     229  
     230    memset (&ev, 0x22, sizeof (ev));
     231    ev.sigev_notify = SIGEV_SIGNAL;
     232    ev.sigev_signo = SIGRTMIN;
     233    ev.sigev_value.sival_ptr = &ev;
     234    if (timer_create (TEST_CLOCK, &ev, &timer_sig1) != 0)
     235      {
     236        printf ("*** timer_create for timer_sig1 failed: %m\n");
     237        return 1;
     238      }
     239  
     240    memset (&ev, 0x33, sizeof (ev));
     241    ev.sigev_notify = SIGEV_SIGNAL;
     242    ev.sigev_signo = SIGRTMIN + 1;
     243    ev.sigev_value.sival_int = 163;
     244    if (timer_create (TEST_CLOCK, &ev, &timer_sig2) != 0)
     245      {
     246        printf ("*** timer_create for timer_sig2 failed: %m\n");
     247        return 1;
     248      }
     249  
     250    memset (&ev, 0x44, sizeof (ev));
     251    ev.sigev_notify = SIGEV_THREAD;
     252    ev.sigev_notify_function = thr1;
     253    ev.sigev_notify_attributes = NULL;
     254    ev.sigev_value.sival_ptr = &ev;
     255    if (timer_create (TEST_CLOCK, &ev, &timer_thr1) != 0)
     256      {
     257        printf ("*** timer_create for timer_thr1 failed: %m\n");
     258        return 1;
     259      }
     260  
     261    pthread_attr_t nattr;
     262    if (pthread_attr_init (&nattr)
     263        || pthread_attr_setguardsize (&nattr, 0))
     264      {
     265        puts ("*** pthread_attr_t setup failed");
     266        result = 1;
     267      }
     268  
     269    memset (&ev, 0x55, sizeof (ev));
     270    ev.sigev_notify = SIGEV_THREAD;
     271    ev.sigev_notify_function = thr2;
     272    ev.sigev_notify_attributes = &nattr;
     273    ev.sigev_value.sival_int = 111;
     274    if (timer_create (TEST_CLOCK, &ev, &timer_thr2) != 0)
     275      {
     276        printf ("*** timer_create for timer_thr2 failed: %m\n");
     277        return 1;
     278      }
     279  
     280    int ret = timer_getoverrun (timer_thr1);
     281    if (ret != 0)
     282      {
     283        if (ret == -1)
     284  	printf ("*** timer_getoverrun failed: %m\n");
     285        else
     286  	printf ("*** timer_getoverrun returned %d != 0\n", ret);
     287        result = 1;
     288      }
     289  
     290    struct itimerspec it;
     291    it.it_value.tv_sec = 0;
     292    it.it_value.tv_nsec = -26;
     293    it.it_interval.tv_sec = 0;
     294    it.it_interval.tv_nsec = 0;
     295    if (timer_settime (timer_sig1, 0, &it, NULL) == 0)
     296      {
     297        puts ("*** timer_settime with negative tv_nsec unexpectedly succeeded");
     298        result = 1;
     299      }
     300    else if (errno != EINVAL)
     301      {
     302        printf ("*** timer_settime with negative tv_nsec did not fail with "
     303  	      "EINVAL: %m\n");
     304        result = 1;
     305      }
     306  
     307    it.it_value.tv_nsec = 100000;
     308    it.it_interval.tv_nsec = 1000000000;
     309    if (timer_settime (timer_sig2, 0, &it, NULL) == 0)
     310      {
     311        puts ("\
     312  *** timer_settime with tv_nsec 1000000000 unexpectedly succeeded");
     313        result = 1;
     314      }
     315    else if (errno != EINVAL)
     316      {
     317        printf ("*** timer_settime with tv_nsec 1000000000 did not fail with "
     318  	      "EINVAL: %m\n");
     319        result = 1;
     320      }
     321  
     322  #if 0
     323    it.it_value.tv_nsec = 0;
     324    it.it_interval.tv_nsec = -26;
     325    if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
     326      {
     327        printf ("\
     328  !!! timer_settime with it_value 0 it_interval invalid failed: %m\n");
     329        /* FIXME: is this mandated by POSIX?
     330        result = 1; */
     331      }
     332  
     333    it.it_interval.tv_nsec = 3000000000;
     334    if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
     335      {
     336        printf ("\
     337  !!! timer_settime with it_value 0 it_interval invalid failed: %m\n");
     338        /* FIXME: is this mandated by POSIX?
     339        result = 1; */
     340      }
     341  #endif
     342  
     343    struct timespec startts;
     344    if (clock_gettime (TEST_CLOCK, &startts) != 0)
     345      {
     346        printf ("*** clock_gettime failed: %m\n");
     347        result = 1;
     348      }
     349  
     350    it.it_value.tv_nsec = 100000000;
     351    it.it_interval.tv_nsec = 0;
     352    if (timer_settime (timer_none, 0, &it, NULL) != 0)
     353      {
     354        printf ("*** timer_settime timer_none failed: %m\n");
     355        result = 1;
     356      }
     357  
     358    it.it_value.tv_nsec = 200000000;
     359    if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
     360      {
     361        printf ("*** timer_settime timer_thr1 failed: %m\n");
     362        result = 1;
     363      }
     364  
     365    it.it_value.tv_nsec = 300000000;
     366    if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
     367      {
     368        printf ("*** timer_settime timer_thr2 failed: %m\n");
     369        result = 1;
     370      }
     371  
     372    it.it_value.tv_nsec = 400000000;
     373    if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
     374      {
     375        printf ("*** timer_settime timer_sig1 failed: %m\n");
     376        result = 1;
     377      }
     378  
     379    it.it_value.tv_nsec = 500000000;
     380    if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
     381      {
     382        printf ("*** timer_settime timer_sig2 failed: %m\n");
     383        result = 1;
     384      }
     385  
     386    pthread_mutex_lock (&lock);
     387    while (thr1_cnt == 0 || thr2_cnt == 0)
     388      pthread_cond_wait (&cond, &lock);
     389    pthread_mutex_unlock (&lock);
     390  
     391    while (sig1_cnt == 0 || sig2_cnt == 0)
     392      {
     393        ts.tv_sec = 0;
     394        ts.tv_nsec = 100000000;
     395        nanosleep (&ts, NULL);
     396      }
     397  
     398    pthread_mutex_lock (&lock);
     399  
     400    if (thr1_cnt != 1)
     401      {
     402        printf ("*** thr1 not called exactly once, but %d times\n", thr1_cnt);
     403        result = 1;
     404      }
     405    else if (thr1_err)
     406      {
     407        puts ("*** an error occurred in thr1");
     408        result = 1;
     409      }
     410    else if (thr1_sigval.sival_ptr != &ev)
     411      {
     412        printf ("*** thr1_sigval.sival_ptr %p != %p\n",
     413  	      thr1_sigval.sival_ptr, &ev);
     414        result = 1;
     415      }
     416    else if (check_ts ("thr1", &startts, &thr1_ts, 200000))
     417      result = 1;
     418  
     419    if (thr2_cnt != 1)
     420      {
     421        printf ("*** thr2 not called exactly once, but %d times\n", thr2_cnt);
     422        result = 1;
     423      }
     424    else if (thr2_err)
     425      {
     426        puts ("*** an error occurred in thr2");
     427        result = 1;
     428      }
     429    else if (thr2_sigval.sival_int != 111)
     430      {
     431        printf ("*** thr2_sigval.sival_ptr %d != 111\n", thr2_sigval.sival_int);
     432        result = 1;
     433      }
     434    else if (check_ts ("thr2", &startts, &thr2_ts, 300000))
     435      result = 1;
     436    else if (thr2_guardsize != 0)
     437      {
     438        printf ("*** thr2 guardsize %zd != 0\n", thr2_guardsize);
     439        result = 1;
     440      }
     441  
     442    pthread_mutex_unlock (&lock);
     443  
     444    if (sig1_cnt != 1)
     445      {
     446        printf ("*** sig1 not called exactly once, but %d times\n", sig1_cnt);
     447        result = 1;
     448      }
     449    else if (sig1_err)
     450      {
     451        printf ("*** errors occurred in sig1 handler %x\n", sig1_err);
     452        result = 1;
     453      }
     454    else if (sig1_sigval.sival_ptr != &ev)
     455      {
     456        printf ("*** sig1_sigval.sival_ptr %p != %p\n",
     457  	      sig1_sigval.sival_ptr, &ev);
     458        result = 1;
     459      }
     460    else if (check_ts ("sig1", &startts, &sig1_ts, 400000))
     461      result = 1;
     462  
     463    if (sig2_cnt != 1)
     464      {
     465        printf ("*** sig2 not called exactly once, but %d times\n", sig2_cnt);
     466        result = 1;
     467      }
     468    else if (sig2_err)
     469      {
     470        printf ("*** errors occurred in sig2 handler %x\n", sig2_err);
     471        result = 1;
     472      }
     473    else if (sig2_sigval.sival_int != 163)
     474      {
     475        printf ("*** sig2_sigval.sival_ptr %d != 163\n", sig2_sigval.sival_int);
     476        result = 1;
     477      }
     478    else if (check_ts ("sig2", &startts, &sig2_ts, 500000))
     479      result = 1;
     480  
     481    if (timer_gettime (timer_none, &it) != 0)
     482      {
     483        printf ("*** timer_gettime timer_none failed: %m\n");
     484        result = 1;
     485      }
     486    else if (it.it_value.tv_sec || it.it_value.tv_nsec
     487  	   || it.it_interval.tv_sec || it.it_interval.tv_nsec)
     488      {
     489        printf ("\
     490  *** timer_gettime timer_none returned { %ld.%09jd, %ld.%09jd }\n",
     491  	      (long) it.it_value.tv_sec, (intmax_t) it.it_value.tv_nsec,
     492  	      (long) it.it_interval.tv_sec, (intmax_t) it.it_interval.tv_nsec);
     493        result = 1;
     494      }
     495  
     496    if (clock_gettime (TEST_CLOCK, &startts) != 0)
     497      {
     498        printf ("*** clock_gettime failed: %m\n");
     499        result = 1;
     500      }
     501  
     502    it.it_value.tv_sec = 1;
     503    it.it_value.tv_nsec = 0;
     504    it.it_interval.tv_sec = 0;
     505    it.it_interval.tv_nsec = 100000000;
     506    if (timer_settime (timer_none, 0, &it, NULL) != 0)
     507      {
     508        printf ("*** timer_settime timer_none failed: %m\n");
     509        result = 1;
     510      }
     511  
     512    it.it_value.tv_nsec = 100000000;
     513    it.it_interval.tv_nsec = 200000000;
     514    if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
     515      {
     516        printf ("*** timer_settime timer_thr1 failed: %m\n");
     517        result = 1;
     518      }
     519  
     520    it.it_value.tv_nsec = 200000000;
     521    it.it_interval.tv_nsec = 300000000;
     522    if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
     523      {
     524        printf ("*** timer_settime timer_thr2 failed: %m\n");
     525        result = 1;
     526      }
     527  
     528    it.it_value.tv_nsec = 300000000;
     529    it.it_interval.tv_nsec = 400000000;
     530    if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
     531      {
     532        printf ("*** timer_settime timer_sig1 failed: %m\n");
     533        result = 1;
     534      }
     535  
     536    it.it_value.tv_nsec = 400000000;
     537    it.it_interval.tv_nsec = 500000000;
     538    if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
     539      {
     540        printf ("*** timer_settime timer_sig2 failed: %m\n");
     541        result = 1;
     542      }
     543  
     544    pthread_mutex_lock (&lock);
     545    while (thr1_cnt < 6 || thr2_cnt < 6)
     546      pthread_cond_wait (&cond, &lock);
     547    pthread_mutex_unlock (&lock);
     548  
     549    while (sig1_cnt < 6 || sig2_cnt < 6)
     550      {
     551        ts.tv_sec = 0;
     552        ts.tv_nsec = 100000000;
     553        nanosleep (&ts, NULL);
     554      }
     555  
     556    pthread_mutex_lock (&lock);
     557  
     558    if (thr1_err)
     559      {
     560        puts ("*** an error occurred in thr1");
     561        result = 1;
     562      }
     563    else if (check_ts ("thr1", &startts, &thr1_ts, 1100000 + 4 * 200000))
     564      result = 1;
     565  
     566    if (thr2_err)
     567      {
     568        puts ("*** an error occurred in thr2");
     569        result = 1;
     570      }
     571    else if (check_ts ("thr2", &startts, &thr2_ts, 1200000 + 4 * 300000))
     572      result = 1;
     573    else if (thr2_guardsize != 0)
     574      {
     575        printf ("*** thr2 guardsize %zd != 0\n", thr2_guardsize);
     576        result = 1;
     577      }
     578  
     579    pthread_mutex_unlock (&lock);
     580  
     581    if (sig1_err)
     582      {
     583        printf ("*** errors occurred in sig1 handler %x\n", sig1_err);
     584        result = 1;
     585      }
     586    else if (check_ts ("sig1", &startts, &sig1_ts, 1300000 + 4 * 400000))
     587      result = 1;
     588  
     589    if (sig2_err)
     590      {
     591        printf ("*** errors occurred in sig2 handler %x\n", sig2_err);
     592        result = 1;
     593      }
     594    else if (check_ts ("sig2", &startts, &sig2_ts, 1400000 + 4 * 500000))
     595      result = 1;
     596  
     597    if (timer_gettime (timer_none, &it) != 0)
     598      {
     599        printf ("*** timer_gettime timer_none failed: %m\n");
     600        result = 1;
     601      }
     602    else if (it.it_interval.tv_sec || it.it_interval.tv_nsec != 100000000)
     603      {
     604        printf ("\
     605  !!! second timer_gettime timer_none returned it_interval %ld.%09jd\n",
     606  	      (long) it.it_interval.tv_sec, (intmax_t) it.it_interval.tv_nsec);
     607        /* FIXME: For now disabled.
     608        result = 1; */
     609      }
     610  
     611    if (timer_delete (timer_none) != 0)
     612      {
     613        printf ("*** timer_delete for timer_none failed: %m\n");
     614        result = 1;
     615      }
     616  
     617    if (timer_delete (timer_sig1) != 0)
     618      {
     619        printf ("*** timer_delete for timer_sig1 failed: %m\n");
     620        result = 1;
     621      }
     622  
     623    if (timer_delete (timer_sig2) != 0)
     624      {
     625        printf ("*** timer_delete for timer_sig2 failed: %m\n");
     626        result = 1;
     627      }
     628  
     629    if (timer_delete (timer_thr1) != 0)
     630      {
     631        printf ("*** timer_delete for timer_thr1 failed: %m\n");
     632        result = 1;
     633      }
     634  
     635    if (timer_delete (timer_thr2) != 0)
     636      {
     637        printf ("*** timer_delete for timer_thr2 failed: %m\n");
     638        result = 1;
     639      }
     640    return result;
     641  }
     642  
     643  #elif defined TEST_CLOCK_MISSING
     644  /* This just ensures that any functions called in TEST_CLOCK_MISSING
     645     are not diagnosed as unused.  */
     646  # define TEST_FUNCTION (TEST_CLOCK_MISSING (TEST_CLOCK), 0)
     647  #else
     648  # define TEST_FUNCTION 0
     649  #endif
     650  
     651  #include "../test-skeleton.c"