Thread.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include <errno.h>
00040 
00041 #include "config.h"
00042 #include "Thread.h"
00043 #include "SpinLock.h"
00044 
00045 #include "../debug/DebugUtils.h"
00046 #include "../debug/Log.h"
00047 #include "../util/CString.h"
00048 
00049 #if GOOGLE_PROFILE_ENABLED
00050 #include <google/profiler.h>
00051 #endif
00052 
00053 namespace oasys {
00054 
00055 #ifdef __win32__
00056 __declspec(thread) Thread* Thread::current_thread_ = 0;
00057 #else
00058 bool                 Thread::signals_inited_ = false;
00059 sigset_t             Thread::interrupt_sigset_;
00060 #endif
00061 
00062 bool                 Thread::start_barrier_enabled_ = false;
00063 std::vector<Thread*> Thread::threads_in_barrier_;
00064 
00065 const int            Thread::max_live_threads_;
00066 Thread*              Thread::all_threads_[max_live_threads_];
00067 SpinLock             g_all_threads_lock_;
00068 SpinLock*            Thread::all_threads_lock_ = &g_all_threads_lock_;
00069 
00070 //----------------------------------------------------------------------------
00071 void
00072 Thread::activate_start_barrier()
00073 {
00074     start_barrier_enabled_ = true;
00075     log_debug("/thread", "activating thread creation barrier");
00076 }
00077 
00078 //----------------------------------------------------------------------------
00079 void
00080 Thread::release_start_barrier()
00081 {
00082     start_barrier_enabled_ = false;
00083 
00084     log_debug("/thread",
00085               "releasing thread creation barrier -- %zu queued threads",
00086               threads_in_barrier_.size());
00087     
00088     for (size_t i = 0; i < threads_in_barrier_.size(); ++i) 
00089     {
00090         Thread* thr = threads_in_barrier_[i];
00091         thr->start();
00092     }
00093 
00094     threads_in_barrier_.clear();
00095 }
00096 
00097 //----------------------------------------------------------------------------
00098 bool
00099 Thread::id_equal(ThreadId_t a, ThreadId_t b)
00100 {
00101 #ifdef __win32__
00102     // XXX/bowei - check if comparing handles for equality is ok
00103     return a == b;
00104 #else
00105     return pthread_equal(a, b);
00106 #endif
00107 }
00108 
00109 //----------------------------------------------------------------------------
00110 Thread::Thread(const char* name, int flags)
00111     : flags_(flags)
00112 {
00113     if ((flags & CREATE_JOINABLE) && (flags & DELETE_ON_EXIT)) {
00114         flags &= ~DELETE_ON_EXIT;
00115     }
00116 
00117 #ifdef __win32__
00118     if (flags & CREATE_JOINABLE) {
00119         join_event_ = CreateEvent(0, TRUE, FALSE, 0);
00120         ASSERT(join_event_ != 0);
00121     } else {
00122         join_event_ = 0;
00123     }
00124 #endif //__win32__
00125     cstring_copy(name_, 64, name);
00126     thread_id_ = 0;
00127 }
00128 
00129 //----------------------------------------------------------------------------
00130 Thread::~Thread()
00131 {
00132 #ifdef __win32__
00133     if (join_event_ != 0) {
00134         CloseHandle(join_event_);
00135     }
00136 #endif //__win32__    
00137 }
00138 
00139 //----------------------------------------------------------------------------
00140 void
00141 Thread::start()
00142 {
00143 #ifndef __win32__
00144 
00145     // if this is the first thread, set up signals
00146     if (!signals_inited_) 
00147     {
00148         sigemptyset(&interrupt_sigset_);
00149         sigaddset(&interrupt_sigset_, INTERRUPT_SIG);
00150         signal(INTERRUPT_SIG, interrupt_signal);
00151         siginterrupt(INTERRUPT_SIG, 1);
00152         signals_inited_ = true;
00153     }
00154 
00155 #endif
00156 
00157     // check if the creation barrier is enabled
00158     if (start_barrier_enabled_) 
00159     {
00160         log_debug("/thread", "delaying start of thread %p due to barrier",
00161                   this);
00162         threads_in_barrier_.push_back(this);
00163         return;
00164     }
00165 
00166     log_debug("/thread", "starting thread %p", this);
00167 
00168 #ifdef __win32__
00169 
00170     DWORD  thread_dword_id;
00171     HANDLE h_thread = CreateThread(0, // Security attributes
00172                                    0, // default stack size
00173                                    Thread::pre_thread_run, // thread function
00174                                    this,
00175                                    // start suspended to fix some state in
00176                                    // the Thread* class before it starts running
00177                                    CREATE_SUSPENDED,       
00178                                    &thread_dword_id);
00179     
00180     ASSERT(h_thread != 0);
00181     thread_id_ = thread_dword_id;
00182 
00183     // Fix the handle on the thread
00184     ResumeThread(h_thread);
00185 #else 
00186 
00187     // XXX/bowei - Why do we retry so many times? Shouldn't we just
00188     // give up?
00189     int ntries = 0;
00190     while (pthread_create(&thread_id_, 0, Thread::pre_thread_run, this) != 0) 
00191     {
00192         if (++ntries == 10000) {
00193             PANIC("maximum thread creation attempts");
00194 #ifdef OASYS_DEBUG_MEMORY_ENABLED
00195             DbgMemInfo::debug_dump();
00196 #endif
00197         }
00198         
00199         log_err("/thread", "error in thread_id_create: %s, retrying",
00200                 strerror(errno));
00201     }
00202 
00203     // since in most cases we want detached threads, users must
00204     // explicitly request for them to be joinable
00205     if (! (flags_ & CREATE_JOINABLE)) 
00206     {
00207         pthread_detach(thread_id_);
00208     }
00209 
00210 #endif // __win32__
00211 }
00212 
00213 //----------------------------------------------------------------------------
00214 void
00215 Thread::join()
00216 {
00217     if (! (flags_ & CREATE_JOINABLE)) 
00218     {
00219         PANIC("tried to join a thread that isn't joinable -- "
00220               "need CREATE_JOINABLE flag");
00221     }
00222     
00223 #ifdef __win32__
00224     ASSERT(join_event_ != 0);
00225     DWORD ret = WaitForSingleObject(join_event_, INFINITE);
00226     (void)ret; // XXX/bowei - get rid of me
00227     ASSERT(ret != WAIT_FAILED);
00228 #else
00229     void* ignored;
00230     int err;
00231     if ((err = pthread_join(thread_id_, &ignored)) != 0) 
00232     {
00233         PANIC("error in pthread_join: %s", strerror(err));
00234     }
00235 #endif
00236 }
00237 
00238 //----------------------------------------------------------------------------
00239 void
00240 Thread::kill(int sig)
00241 {
00242 #ifdef __win32__
00243     (void)sig;
00244     NOTIMPLEMENTED;
00245 #else
00246     if (pthread_kill(thread_id_, sig) != 0) {
00247         PANIC("error in pthread_kill: %s", strerror(errno));
00248     }
00249 #endif
00250 }
00251 
00252 //----------------------------------------------------------------------------
00253 void
00254 Thread::interrupt()
00255 {
00256 #ifdef __win32__
00257     NOTIMPLEMENTED;
00258 #else
00259     log_debug("/thread", "interrupting thread %p", this);
00260     kill(INTERRUPT_SIG);
00261 #endif
00262 }
00263 
00264 //----------------------------------------------------------------------------
00265 void
00266 Thread::set_interruptable(bool interruptable)
00267 {
00268 #ifdef __win32__
00269     (void)interruptable;
00270     NOTIMPLEMENTED;
00271 #else
00272     ASSERT(Thread::current() == thread_id_);
00273     
00274     int block = (interruptable ? SIG_UNBLOCK : SIG_BLOCK);
00275     if (pthread_sigmask(block, &interrupt_sigset_, NULL) != 0) {
00276         PANIC("error in thread_id_sigmask");
00277     }
00278 #endif
00279 }
00280 
00281 
00282 //----------------------------------------------------------------------------
00283 #ifdef __win32__
00284 DWORD WINAPI 
00285 #else
00286 void*
00287 #endif
00288 Thread::pre_thread_run(void* t)
00289 {
00290     Thread* thr = static_cast<Thread*>(t);
00291 
00292 #ifdef __win32__
00293     current_thread_ = thr;
00294 #endif
00295 
00296     ThreadId_t thread_id = Thread::current();
00297     thr->thread_run(thr->name_, thread_id);
00298 
00299     return 0;
00300 }
00301 
00302 //----------------------------------------------------------------------------
00303 void
00304 Thread::interrupt_signal(int sig)
00305 {
00306     (void)sig;
00307 }
00308 
00309 //----------------------------------------------------------------------------
00310 void
00311 Thread::thread_run(const char* thread_name, ThreadId_t thread_id)
00312 {
00313     /*
00314      * The only reason we pass the name to thread_run is to make it
00315      * appear in the gdb backtrace to more easily identify the actual
00316      * thread.
00317      */
00318     (void)thread_name;
00319     
00320 #if GOOGLE_PROFILE_ENABLED
00321     ProfilerRegisterThread();
00322 #endif
00323 
00324     all_threads_lock_->lock("thread startup");
00325     for (int i = 0; i < max_live_threads_; ++i) {
00326         if (all_threads_[i] == NULL) {
00327             all_threads_[i] = this;
00328             break;
00329         }
00330     }
00331     all_threads_lock_->unlock();
00332 
00333 #ifndef __win32__    
00334     /*
00335      * There's a potential race between the starting of the new thread
00336      * and the storing of the thread id in the thread_id_ member
00337      * variable, so we can't trust that it's been written by our
00338      * spawner. So we re-write it here to make sure that it's valid
00339      * for the new thread (specifically for set_interruptable's
00340      * assertion.
00341      */
00342     thread_id_ = thread_id;
00343     set_interruptable((flags_ & INTERRUPTABLE));
00344 #endif
00345 
00346     flags_ |= STARTED;
00347     flags_ &= ~STOPPED;
00348     flags_ &= ~SHOULD_STOP;
00349 
00350     try 
00351     {
00352         run();
00353     } 
00354     catch (...) 
00355     {
00356         PANIC("unexpected exception caught from Thread::run");
00357     }
00358     
00359     flags_ |= STOPPED;
00360 
00361 #ifdef __win32__
00362     if (join_event_) {
00363         SetEvent(join_event_);
00364     }
00365 #endif //__win32__
00366 
00367     all_threads_lock_->lock("thread startup");
00368     for (int i = 0; i < max_live_threads_; ++i) {
00369         if (all_threads_[i] == this) {
00370             all_threads_[i] = NULL;
00371             break;
00372         }
00373     }
00374     all_threads_lock_->unlock();
00375     
00376     if (flags_ & DELETE_ON_EXIT) 
00377     {
00378         delete this;
00379     }
00380 
00381 #ifdef __win32__
00382 
00383     // Make sure C++ cleanup is called, which does not occur if we
00384     // call ExitThread().
00385     return;
00386 
00387 #else
00388 
00389     pthread_exit(0);
00390     NOTREACHED;
00391 
00392 #endif
00393 }
00394 
00395 } // namespace oasys

Generated on Fri Dec 22 14:48:01 2006 for DTN Reference Implementation by  doxygen 1.5.1