// tls_test.cc -- test TLS variables for gold, main function // Copyright 2006, 2007, 2008 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // This program 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 General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, // MA 02110-1301, USA. // This is the main function for the TLS test. See tls_test.cc for // more information. #include #include #include #include "tls_test.h" // We make these macros so the assert() will give useful line-numbers. #define safe_lock(muptr) \ do \ { \ int err = pthread_mutex_lock(muptr); \ assert(err == 0); \ } \ while (0) #define safe_unlock(muptr) \ do \ { \ int err = pthread_mutex_unlock(muptr); \ assert(err == 0); \ } \ while (0) struct Mutex_set { pthread_mutex_t mutex1; pthread_mutex_t mutex2; pthread_mutex_t mutex3; }; Mutex_set mutexes1 = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }; Mutex_set mutexes2 = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER } ; bool failed = false; void check(const char* name, bool val) { if (!val) { fprintf(stderr, "Test %s failed\n", name); failed = true; } } // The body of the thread function. This gets a lock on the first // mutex, runs the tests, and then unlocks the second mutex. Then it // locks the third mutex, and the runs the verification test again. void* thread_routine(void* arg) { Mutex_set* pms = static_cast(arg); // Lock the first mutex. if (pms) safe_lock(&pms->mutex1); // Run the tests. check("t1", t1()); check("t2", t2()); check("t3", t3()); check("t4", t4()); f5b(f5a()); check("t5", t5()); f6b(f6a()); check("t6", t6()); check("t8", t8()); check("t9", t9()); f10b(f10a()); check("t10", t10()); check("t11", t11() != 0); check("t_last", t_last()); // Unlock the second mutex. if (pms) safe_unlock(&pms->mutex2); // Lock the third mutex. if (pms) safe_lock(&pms->mutex3); check("t_last", t_last()); return 0; } // The main function. int main() { // First, as a sanity check, run through the tests in the "main" thread. thread_routine(0); // Set up the mutex locks. We want the first thread to start right // away, tell us when it is done with the first part, and wait for // us to release it. We want the second thread to wait to start, // tell us when it is done with the first part, and wait for us to // release it. safe_lock(&mutexes1.mutex2); safe_lock(&mutexes1.mutex3); safe_lock(&mutexes2.mutex1); safe_lock(&mutexes2.mutex2); safe_lock(&mutexes2.mutex3); pthread_t thread1; int err = pthread_create(&thread1, NULL, thread_routine, &mutexes1); assert(err == 0); pthread_t thread2; err = pthread_create(&thread2, NULL, thread_routine, &mutexes2); assert(err == 0); // Wait for the first thread to complete the first part. safe_lock(&mutexes1.mutex2); // Tell the second thread to start. safe_unlock(&mutexes2.mutex1); // Wait for the second thread to complete the first part. safe_lock(&mutexes2.mutex2); // Tell the first thread to continue and finish. safe_unlock(&mutexes1.mutex3); // Wait for the first thread to finish. void* thread_val; err = pthread_join(thread1, &thread_val); assert(err == 0); assert(thread_val == 0); // Tell the second thread to continue and finish. safe_unlock(&mutexes2.mutex3); // Wait for the second thread to finish. err = pthread_join(thread2, &thread_val); assert(err == 0); assert(thread_val == 0); // All done. return failed ? 1 : 0; }