(root)/
glibc-2.38/
nptl/
tst-attr3.c
       1  /* pthread_getattr_np test.
       2     Copyright (C) 2003-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
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the 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; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <error.h>
      21  #include <pthread.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <string.h>
      25  #include <unistd.h>
      26  
      27  #include <stackinfo.h>
      28  #include <libc-diag.h>
      29  
      30  static void *
      31  tf (void *arg)
      32  {
      33    pthread_attr_t a, *ap, a2;
      34    int err;
      35    void *result = NULL;
      36  
      37    if (arg == NULL)
      38      {
      39        ap = &a2;
      40        err = pthread_attr_init (ap);
      41        if (err)
      42  	{
      43  	  error (0, err, "pthread_attr_init failed");
      44  	  return tf;
      45  	}
      46      }
      47    else
      48      ap = (pthread_attr_t *) arg;
      49  
      50    err = pthread_getattr_np (pthread_self (), &a);
      51    if (err)
      52      {
      53        error (0, err, "pthread_getattr_np failed");
      54        result = tf;
      55      }
      56  
      57    int detachstate1, detachstate2;
      58    err = pthread_attr_getdetachstate (&a, &detachstate1);
      59    if (err)
      60      {
      61        error (0, err, "pthread_attr_getdetachstate failed");
      62        result = tf;
      63      }
      64    else
      65      {
      66        err = pthread_attr_getdetachstate (ap, &detachstate2);
      67        if (err)
      68  	{
      69  	  error (0, err, "pthread_attr_getdetachstate failed");
      70  	  result = tf;
      71  	}
      72        else if (detachstate1 != detachstate2)
      73  	{
      74  	  error (0, 0, "detachstate differs %d != %d",
      75  		 detachstate1, detachstate2);
      76  	  result = tf;
      77  	}
      78      }
      79  
      80    void *stackaddr;
      81    size_t stacksize;
      82    err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
      83    if (err)
      84      {
      85        error (0, err, "pthread_attr_getstack failed");
      86        result = tf;
      87      }
      88    else if ((void *) &a < stackaddr
      89  	   || (void *) &a >= stackaddr + stacksize)
      90      {
      91        error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack");
      92        result = tf;
      93      }
      94    else
      95      printf ("thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize,
      96  	    stacksize);
      97  
      98    size_t guardsize1, guardsize2;
      99    err = pthread_attr_getguardsize (&a, &guardsize1);
     100    if (err)
     101      {
     102        error (0, err, "pthread_attr_getguardsize failed");
     103        result = tf;
     104      }
     105    else
     106      {
     107        err = pthread_attr_getguardsize (ap, &guardsize2);
     108        if (err)
     109  	{
     110  	  error (0, err, "pthread_attr_getguardsize failed");
     111  	  result = tf;
     112  	}
     113        else if (guardsize1 != guardsize2)
     114  	{
     115  	  error (0, 0, "guardsize differs %zd != %zd",
     116  		 guardsize1, guardsize2);
     117  	  result = tf;
     118  	}
     119        else
     120  	printf ("thread guardsize %zd\n", guardsize1);
     121      }
     122  
     123    int scope1, scope2;
     124    err = pthread_attr_getscope (&a, &scope1);
     125    if (err)
     126      {
     127        error (0, err, "pthread_attr_getscope failed");
     128        result = tf;
     129      }
     130    else
     131      {
     132        err = pthread_attr_getscope (ap, &scope2);
     133        if (err)
     134  	{
     135  	  error (0, err, "pthread_attr_getscope failed");
     136  	  result = tf;
     137  	}
     138        else if (scope1 != scope2)
     139  	{
     140  	  error (0, 0, "scope differs %d != %d",
     141  		 scope1, scope2);
     142  	  result = tf;
     143  	}
     144      }
     145  
     146    int inheritsched1, inheritsched2;
     147    err = pthread_attr_getinheritsched (&a, &inheritsched1);
     148    if (err)
     149      {
     150        error (0, err, "pthread_attr_getinheritsched failed");
     151        result = tf;
     152      }
     153    else
     154      {
     155        err = pthread_attr_getinheritsched (ap, &inheritsched2);
     156        if (err)
     157  	{
     158  	  error (0, err, "pthread_attr_getinheritsched failed");
     159  	  result = tf;
     160  	}
     161        else if (inheritsched1 != inheritsched2)
     162  	{
     163  	  error (0, 0, "inheritsched differs %d != %d",
     164  		 inheritsched1, inheritsched2);
     165  	  result = tf;
     166  	}
     167      }
     168  
     169    cpu_set_t c1, c2;
     170    err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1);
     171    if (err == 0)
     172      {
     173        err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2);
     174        if (err)
     175  	{
     176  	  error (0, err, "pthread_attr_getaffinity_np failed");
     177  	  result = tf;
     178  	}
     179        else if (memcmp (&c1, &c2, sizeof (c1)))
     180  	{
     181  	  error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
     182  	  result = tf;
     183  	}
     184      }
     185  
     186    err = pthread_attr_destroy (&a);
     187    if (err)
     188      {
     189        error (0, err, "pthread_attr_destroy failed");
     190        result = tf;
     191      }
     192  
     193    if (ap == &a2)
     194      {
     195        err = pthread_attr_destroy (ap);
     196        if (err)
     197  	{
     198  	  error (0, err, "pthread_attr_destroy failed");
     199  	  result = tf;
     200  	}
     201      }
     202  
     203    return result;
     204  }
     205  
     206  
     207  static int
     208  do_test (void)
     209  {
     210    int result = 0;
     211    pthread_attr_t a;
     212    cpu_set_t c1, c2;
     213  
     214    int err = pthread_attr_init (&a);
     215    if (err)
     216      {
     217        error (0, err, "pthread_attr_init failed");
     218        result = 1;
     219      }
     220  
     221    err = pthread_attr_getaffinity_np (&a, sizeof (c1), &c1);
     222    if (err && err != ENOSYS)
     223      {
     224        error (0, err, "pthread_attr_getaffinity_np failed");
     225        result = 1;
     226      }
     227  
     228    err = pthread_attr_destroy (&a);
     229    if (err)
     230      {
     231        error (0, err, "pthread_attr_destroy failed");
     232        result = 1;
     233      }
     234  
     235    err = pthread_getattr_np (pthread_self (), &a);
     236    if (err)
     237      {
     238        error (0, err, "pthread_getattr_np failed");
     239        result = 1;
     240      }
     241  
     242    int detachstate;
     243    err = pthread_attr_getdetachstate (&a, &detachstate);
     244    if (err)
     245      {
     246        error (0, err, "pthread_attr_getdetachstate failed");
     247        result = 1;
     248      }
     249    else if (detachstate != PTHREAD_CREATE_JOINABLE)
     250      {
     251        error (0, 0, "initial thread not joinable");
     252        result = 1;
     253      }
     254  
     255    void *stackaddr;
     256    size_t stacksize;
     257    err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
     258    if (err)
     259      {
     260        error (0, err, "pthread_attr_getstack failed");
     261        result = 1;
     262      }
     263    else if ((void *) &a < stackaddr
     264  	   || (void *) &a >= stackaddr + stacksize)
     265      {
     266        error (0, 0, "pthread_attr_getstack returned range does not cover main's stack");
     267        result = 1;
     268      }
     269    else
     270      printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr,
     271  	    stackaddr + stacksize, stacksize);
     272  
     273    size_t guardsize;
     274    err = pthread_attr_getguardsize (&a, &guardsize);
     275    if (err)
     276      {
     277        error (0, err, "pthread_attr_getguardsize failed");
     278        result = 1;
     279      }
     280    else if (guardsize != 0)
     281      {
     282        error (0, 0, "pthread_attr_getguardsize returned %zd != 0",
     283  	     guardsize);
     284        result = 1;
     285      }
     286  
     287    int scope;
     288    err = pthread_attr_getscope (&a, &scope);
     289    if (err)
     290      {
     291        error (0, err, "pthread_attr_getscope failed");
     292        result = 1;
     293      }
     294    else if (scope != PTHREAD_SCOPE_SYSTEM)
     295      {
     296        error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM",
     297  	     scope);
     298        result = 1;
     299      }
     300  
     301    int inheritsched;
     302    err = pthread_attr_getinheritsched (&a, &inheritsched);
     303    if (err)
     304      {
     305        error (0, err, "pthread_attr_getinheritsched failed");
     306        result = 1;
     307      }
     308    else if (inheritsched != PTHREAD_INHERIT_SCHED)
     309      {
     310        error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED",
     311  	     inheritsched);
     312        result = 1;
     313      }
     314  
     315    err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1);
     316    if (err == 0)
     317      {
     318        err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2);
     319        if (err)
     320  	{
     321  	  error (0, err, "pthread_attr_getaffinity_np failed");
     322  	  result = 1;
     323  	}
     324        else if (memcmp (&c1, &c2, sizeof (c1)))
     325  	{
     326  	  error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
     327  	  result = 1;
     328  	}
     329      }
     330  
     331    err = pthread_attr_destroy (&a);
     332    if (err)
     333      {
     334        error (0, err, "pthread_attr_destroy failed");
     335        result = 1;
     336      }
     337  
     338    pthread_t th;
     339    err = pthread_create (&th, NULL, tf, NULL);
     340    if (err)
     341      {
     342        error (0, err, "pthread_create #1 failed");
     343        result = 1;
     344      }
     345    else
     346      {
     347        void *ret;
     348        err = pthread_join (th, &ret);
     349        if (err)
     350  	{
     351  	  error (0, err, "pthread_join #1 failed");
     352  	  result = 1;
     353  	}
     354        else if (ret != NULL)
     355  	result = 1;
     356      }
     357  
     358    err = pthread_attr_init (&a);
     359    if (err)
     360      {
     361        error (0, err, "pthread_attr_init failed");
     362        result = 1;
     363      }
     364  
     365    DIAG_PUSH_NEEDS_COMMENT;
     366  #if __GNUC_PREREQ (7, 0)
     367    /* GCC 8 warns about aliasing of the restrict-qualified arguments
     368       passed &a.  Since pthread_create does not dereference its fourth
     369       argument, this aliasing, which is deliberate in this test, cannot
     370       in fact cause problems.  */
     371    DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict");
     372  #endif
     373    err = pthread_create (&th, &a, tf, &a);
     374    DIAG_POP_NEEDS_COMMENT;
     375    if (err)
     376      {
     377        error (0, err, "pthread_create #2 failed");
     378        result = 1;
     379      }
     380    else
     381      {
     382        void *ret;
     383        err = pthread_join (th, &ret);
     384        if (err)
     385  	{
     386  	  error (0, err, "pthread_join #2 failed");
     387  	  result = 1;
     388  	}
     389        else if (ret != NULL)
     390  	result = 1;
     391      }
     392  
     393    err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE));
     394    if (err)
     395      {
     396        error (0, err, "pthread_attr_setguardsize failed");
     397        result = 1;
     398      }
     399  
     400    DIAG_PUSH_NEEDS_COMMENT;
     401  #if __GNUC_PREREQ (7, 0)
     402    /* GCC 8 warns about aliasing of the restrict-qualified arguments
     403       passed &a.  Since pthread_create does not dereference its fourth
     404       argument, this aliasing, which is deliberate in this test, cannot
     405       in fact cause problems.  */
     406    DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict");
     407  #endif
     408    err = pthread_create (&th, &a, tf, &a);
     409    DIAG_POP_NEEDS_COMMENT;
     410    if (err)
     411      {
     412        error (0, err, "pthread_create #3 failed");
     413        result = 1;
     414      }
     415    else
     416      {
     417        void *ret;
     418        err = pthread_join (th, &ret);
     419        if (err)
     420  	{
     421  	  error (0, err, "pthread_join #3 failed");
     422  	  result = 1;
     423  	}
     424        else if (ret != NULL)
     425  	result = 1;
     426      }
     427  
     428    err = pthread_attr_destroy (&a);
     429    if (err)
     430      {
     431        error (0, err, "pthread_attr_destroy failed");
     432        result = 1;
     433      }
     434  
     435    return result;
     436  }
     437  
     438  #define TEST_FUNCTION do_test ()
     439  #include "../test-skeleton.c"