// tls_test.cc -- test TLS variables for gold, main function// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.// Written by Ian Lance Taylor <iant@google.com>.// 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 <cassert>#include <cstdio>#include <pthread.h>#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;voidcheck(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<Mutex_set*>(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("t12", t12());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.intmain(){// 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;}