(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cond8.c
       1  /* Copyright (C) 2003-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library 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 GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <pthread.h>
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <time.h>
      23  #include <sys/time.h>
      24  
      25  
      26  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
      27  static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
      28  
      29  static pthread_barrier_t bar;
      30  
      31  
      32  static void
      33  ch (void *arg)
      34  {
      35    int e = pthread_mutex_lock (&mut);
      36    if (e == 0)
      37      {
      38        puts ("mutex not locked at all by cond_wait");
      39        exit (1);
      40      }
      41  
      42    if (e != EDEADLK)
      43      {
      44        puts ("no deadlock error signaled");
      45        exit (1);
      46      }
      47  
      48    if (pthread_mutex_unlock (&mut) != 0)
      49      {
      50        puts ("ch: cannot unlock mutex");
      51        exit (1);
      52      }
      53  
      54    puts ("ch done");
      55  }
      56  
      57  
      58  static void *
      59  tf1 (void *p)
      60  {
      61    int err;
      62  
      63    if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
      64        || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
      65      {
      66        puts ("cannot set cancellation options");
      67        exit (1);
      68      }
      69  
      70    err = pthread_mutex_lock (&mut);
      71    if (err != 0)
      72      {
      73        puts ("child: cannot get mutex");
      74        exit (1);
      75      }
      76  
      77    err = pthread_barrier_wait (&bar);
      78    if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
      79      {
      80        printf ("barrier_wait returned %d\n", err);
      81        exit (1);
      82      }
      83  
      84    puts ("child: got mutex; waiting");
      85  
      86    pthread_cleanup_push (ch, NULL);
      87  
      88    pthread_cond_wait (&cond, &mut);
      89  
      90    pthread_cleanup_pop (0);
      91  
      92    puts ("child: cond_wait should not have returned");
      93  
      94    return NULL;
      95  }
      96  
      97  
      98  static void *
      99  tf2 (void *p)
     100  {
     101    int err;
     102  
     103    if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
     104        || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
     105      {
     106        puts ("cannot set cancellation options");
     107        exit (1);
     108      }
     109  
     110    err = pthread_mutex_lock (&mut);
     111    if (err != 0)
     112      {
     113        puts ("child: cannot get mutex");
     114        exit (1);
     115      }
     116  
     117    err = pthread_barrier_wait (&bar);
     118    if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
     119      {
     120        printf ("barrier_wait returned %d\n", err);
     121        exit (1);
     122      }
     123  
     124    puts ("child: got mutex; waiting");
     125  
     126    pthread_cleanup_push (ch, NULL);
     127  
     128    /* Current time.  */
     129    struct timeval tv;
     130    (void) gettimeofday (&tv, NULL);
     131    /* +1000 seconds in correct format.  */
     132    struct timespec ts;
     133    TIMEVAL_TO_TIMESPEC (&tv, &ts);
     134    ts.tv_sec += 1000;
     135  
     136    pthread_cond_timedwait (&cond, &mut, &ts);
     137  
     138    pthread_cleanup_pop (0);
     139  
     140    puts ("child: cond_wait should not have returned");
     141  
     142    return NULL;
     143  }
     144  
     145  
     146  static int
     147  do_test (void)
     148  {
     149    pthread_t th;
     150    int err;
     151  
     152    printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
     153  
     154    puts ("parent: get mutex");
     155  
     156    err = pthread_barrier_init (&bar, NULL, 2);
     157    if (err != 0)
     158      {
     159        puts ("parent: cannot init barrier");
     160        exit (1);
     161      }
     162  
     163    puts ("parent: create child");
     164  
     165    err = pthread_create (&th, NULL, tf1, NULL);
     166    if (err != 0)
     167      {
     168        puts ("parent: cannot create thread");
     169        exit (1);
     170      }
     171  
     172    puts ("parent: wait for child to lock mutex");
     173  
     174    err = pthread_barrier_wait (&bar);
     175    if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
     176      {
     177        puts ("parent: cannot wait for barrier");
     178        exit (1);
     179      }
     180  
     181    err = pthread_mutex_lock (&mut);
     182    if (err != 0)
     183      {
     184        puts ("parent: mutex_lock failed");
     185        exit (1);
     186      }
     187  
     188    err = pthread_mutex_unlock (&mut);
     189    if (err != 0)
     190      {
     191        puts ("parent: mutex_unlock failed");
     192        exit (1);
     193      }
     194  
     195    if (pthread_cancel (th) != 0)
     196      {
     197        puts ("cannot cancel thread");
     198        exit (1);
     199      }
     200  
     201    void *r;
     202    err = pthread_join (th, &r);
     203    if (err != 0)
     204      {
     205        puts ("parent: failed to join");
     206        exit (1);
     207      }
     208  
     209    if (r != PTHREAD_CANCELED)
     210      {
     211        puts ("child hasn't been canceled");
     212        exit (1);
     213      }
     214  
     215  
     216  
     217    puts ("parent: create 2nd child");
     218  
     219    err = pthread_create (&th, NULL, tf2, NULL);
     220    if (err != 0)
     221      {
     222        puts ("parent: cannot create thread");
     223        exit (1);
     224      }
     225  
     226    puts ("parent: wait for child to lock mutex");
     227  
     228    err = pthread_barrier_wait (&bar);
     229    if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
     230      {
     231        puts ("parent: cannot wait for barrier");
     232        exit (1);
     233      }
     234  
     235    err = pthread_mutex_lock (&mut);
     236    if (err != 0)
     237      {
     238        puts ("parent: mutex_lock failed");
     239        exit (1);
     240      }
     241  
     242    err = pthread_mutex_unlock (&mut);
     243    if (err != 0)
     244      {
     245        puts ("parent: mutex_unlock failed");
     246        exit (1);
     247      }
     248  
     249    if (pthread_cancel (th) != 0)
     250      {
     251        puts ("cannot cancel thread");
     252        exit (1);
     253      }
     254  
     255    err = pthread_join (th, &r);
     256    if (err != 0)
     257      {
     258        puts ("parent: failed to join");
     259        exit (1);
     260      }
     261  
     262    if (r != PTHREAD_CANCELED)
     263      {
     264        puts ("child hasn't been canceled");
     265        exit (1);
     266      }
     267  
     268    puts ("done");
     269  
     270    return 0;
     271  }
     272  
     273  
     274  #define TEST_FUNCTION do_test ()
     275  #include "../test-skeleton.c"