| /* pthread_getattr_np test. |
| Copyright (C) 2003-2014 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| The GNU C Library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library; if not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include <errno.h> |
| #include <error.h> |
| #include <pthread.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include <stackinfo.h> |
| |
| static void * |
| tf (void *arg) |
| { |
| pthread_attr_t a, *ap, a2; |
| int err; |
| void *result = NULL; |
| |
| if (arg == NULL) |
| { |
| ap = &a2; |
| err = pthread_attr_init (ap); |
| if (err) |
| { |
| error (0, err, "pthread_attr_init failed"); |
| return tf; |
| } |
| } |
| else |
| ap = (pthread_attr_t *) arg; |
| |
| err = pthread_getattr_np (pthread_self (), &a); |
| if (err) |
| { |
| error (0, err, "pthread_getattr_np failed"); |
| result = tf; |
| } |
| |
| int detachstate1, detachstate2; |
| err = pthread_attr_getdetachstate (&a, &detachstate1); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getdetachstate failed"); |
| result = tf; |
| } |
| else |
| { |
| err = pthread_attr_getdetachstate (ap, &detachstate2); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getdetachstate failed"); |
| result = tf; |
| } |
| else if (detachstate1 != detachstate2) |
| { |
| error (0, 0, "detachstate differs %d != %d", |
| detachstate1, detachstate2); |
| result = tf; |
| } |
| } |
| |
| void *stackaddr; |
| size_t stacksize; |
| err = pthread_attr_getstack (&a, &stackaddr, &stacksize); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getstack failed"); |
| result = tf; |
| } |
| else if ((void *) &a < stackaddr |
| || (void *) &a >= stackaddr + stacksize) |
| { |
| error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack"); |
| result = tf; |
| } |
| else |
| printf ("thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize, |
| stacksize); |
| |
| size_t guardsize1, guardsize2; |
| err = pthread_attr_getguardsize (&a, &guardsize1); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getguardsize failed"); |
| result = tf; |
| } |
| else |
| { |
| err = pthread_attr_getguardsize (ap, &guardsize2); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getguardsize failed"); |
| result = tf; |
| } |
| else if (guardsize1 != guardsize2) |
| { |
| error (0, 0, "guardsize differs %zd != %zd", |
| guardsize1, guardsize2); |
| result = tf; |
| } |
| else |
| printf ("thread guardsize %zd\n", guardsize1); |
| } |
| |
| int scope1, scope2; |
| err = pthread_attr_getscope (&a, &scope1); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getscope failed"); |
| result = tf; |
| } |
| else |
| { |
| err = pthread_attr_getscope (ap, &scope2); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getscope failed"); |
| result = tf; |
| } |
| else if (scope1 != scope2) |
| { |
| error (0, 0, "scope differs %d != %d", |
| scope1, scope2); |
| result = tf; |
| } |
| } |
| |
| int inheritsched1, inheritsched2; |
| err = pthread_attr_getinheritsched (&a, &inheritsched1); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getinheritsched failed"); |
| result = tf; |
| } |
| else |
| { |
| err = pthread_attr_getinheritsched (ap, &inheritsched2); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getinheritsched failed"); |
| result = tf; |
| } |
| else if (inheritsched1 != inheritsched2) |
| { |
| error (0, 0, "inheritsched differs %d != %d", |
| inheritsched1, inheritsched2); |
| result = tf; |
| } |
| } |
| |
| cpu_set_t c1, c2; |
| err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1); |
| if (err == 0) |
| { |
| err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getaffinity_np failed"); |
| result = tf; |
| } |
| else if (memcmp (&c1, &c2, sizeof (c1))) |
| { |
| error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); |
| result = tf; |
| } |
| } |
| |
| err = pthread_attr_destroy (&a); |
| if (err) |
| { |
| error (0, err, "pthread_attr_destroy failed"); |
| result = tf; |
| } |
| |
| if (ap == &a2) |
| { |
| err = pthread_attr_destroy (ap); |
| if (err) |
| { |
| error (0, err, "pthread_attr_destroy failed"); |
| result = tf; |
| } |
| } |
| |
| return result; |
| } |
| |
| |
| static int |
| do_test (void) |
| { |
| int result = 0; |
| pthread_attr_t a; |
| cpu_set_t c1, c2; |
| |
| int err = pthread_attr_init (&a); |
| if (err) |
| { |
| error (0, err, "pthread_attr_init failed"); |
| result = 1; |
| } |
| |
| err = pthread_attr_getaffinity_np (&a, sizeof (c1), &c1); |
| if (err && err != ENOSYS) |
| { |
| error (0, err, "pthread_attr_getaffinity_np failed"); |
| result = 1; |
| } |
| |
| err = pthread_attr_destroy (&a); |
| if (err) |
| { |
| error (0, err, "pthread_attr_destroy failed"); |
| result = 1; |
| } |
| |
| err = pthread_getattr_np (pthread_self (), &a); |
| if (err) |
| { |
| error (0, err, "pthread_getattr_np failed"); |
| result = 1; |
| } |
| |
| int detachstate; |
| err = pthread_attr_getdetachstate (&a, &detachstate); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getdetachstate failed"); |
| result = 1; |
| } |
| else if (detachstate != PTHREAD_CREATE_JOINABLE) |
| { |
| error (0, 0, "initial thread not joinable"); |
| result = 1; |
| } |
| |
| void *stackaddr; |
| size_t stacksize; |
| err = pthread_attr_getstack (&a, &stackaddr, &stacksize); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getstack failed"); |
| result = 1; |
| } |
| else if ((void *) &a < stackaddr |
| || (void *) &a >= stackaddr + stacksize) |
| { |
| error (0, 0, "pthread_attr_getstack returned range does not cover main's stack"); |
| result = 1; |
| } |
| else |
| printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr, |
| stackaddr + stacksize, stacksize); |
| |
| size_t guardsize; |
| err = pthread_attr_getguardsize (&a, &guardsize); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getguardsize failed"); |
| result = 1; |
| } |
| else if (guardsize != 0) |
| { |
| error (0, 0, "pthread_attr_getguardsize returned %zd != 0", |
| guardsize); |
| result = 1; |
| } |
| |
| int scope; |
| err = pthread_attr_getscope (&a, &scope); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getscope failed"); |
| result = 1; |
| } |
| else if (scope != PTHREAD_SCOPE_SYSTEM) |
| { |
| error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM", |
| scope); |
| result = 1; |
| } |
| |
| int inheritsched; |
| err = pthread_attr_getinheritsched (&a, &inheritsched); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getinheritsched failed"); |
| result = 1; |
| } |
| else if (inheritsched != PTHREAD_INHERIT_SCHED) |
| { |
| error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED", |
| inheritsched); |
| result = 1; |
| } |
| |
| err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1); |
| if (err == 0) |
| { |
| err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2); |
| if (err) |
| { |
| error (0, err, "pthread_attr_getaffinity_np failed"); |
| result = 1; |
| } |
| else if (memcmp (&c1, &c2, sizeof (c1))) |
| { |
| error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); |
| result = 1; |
| } |
| } |
| |
| err = pthread_attr_destroy (&a); |
| if (err) |
| { |
| error (0, err, "pthread_attr_destroy failed"); |
| result = 1; |
| } |
| |
| pthread_t th; |
| err = pthread_create (&th, NULL, tf, NULL); |
| if (err) |
| { |
| error (0, err, "pthread_create #1 failed"); |
| result = 1; |
| } |
| else |
| { |
| void *ret; |
| err = pthread_join (th, &ret); |
| if (err) |
| { |
| error (0, err, "pthread_join #1 failed"); |
| result = 1; |
| } |
| else if (ret != NULL) |
| result = 1; |
| } |
| |
| err = pthread_attr_init (&a); |
| if (err) |
| { |
| error (0, err, "pthread_attr_init failed"); |
| result = 1; |
| } |
| |
| err = pthread_create (&th, &a, tf, &a); |
| if (err) |
| { |
| error (0, err, "pthread_create #2 failed"); |
| result = 1; |
| } |
| else |
| { |
| void *ret; |
| err = pthread_join (th, &ret); |
| if (err) |
| { |
| error (0, err, "pthread_join #2 failed"); |
| result = 1; |
| } |
| else if (ret != NULL) |
| result = 1; |
| } |
| |
| err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE)); |
| if (err) |
| { |
| error (0, err, "pthread_attr_setguardsize failed"); |
| result = 1; |
| } |
| |
| err = pthread_create (&th, &a, tf, &a); |
| if (err) |
| { |
| error (0, err, "pthread_create #3 failed"); |
| result = 1; |
| } |
| else |
| { |
| void *ret; |
| err = pthread_join (th, &ret); |
| if (err) |
| { |
| error (0, err, "pthread_join #3 failed"); |
| result = 1; |
| } |
| else if (ret != NULL) |
| result = 1; |
| } |
| |
| err = pthread_attr_destroy (&a); |
| if (err) |
| { |
| error (0, err, "pthread_attr_destroy failed"); |
| result = 1; |
| } |
| |
| return result; |
| } |
| |
| #define TEST_FUNCTION do_test () |
| #include "../test-skeleton.c" |