|  | /* pthread_getattr_np test. | 
|  | Copyright (C) 2003-2016 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" |