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 #ifndef _OASYS_THREAD_H_ 00040 #define _OASYS_THREAD_H_ 00041 00042 #include "config.h" 00043 00044 #include <sys/types.h> 00045 00046 #ifdef __win32__ 00047 00048 #include <Windows.h> 00049 00050 #else 00051 00052 #include <pthread.h> 00053 #include <signal.h> 00054 00055 #ifdef HAVE_SCHED_YIELD 00056 #include <sched.h> 00057 #endif 00058 00059 #endif // __win32__ 00060 00061 #include <vector> 00062 00063 #include "../debug/DebugUtils.h" 00064 00065 namespace oasys { 00066 00067 #ifdef __win32__ 00068 typedef DWORD ThreadId_t; 00069 #else 00070 typedef pthread_t ThreadId_t; 00071 #endif 00072 00073 class SpinLock; 00074 00080 class Thread { 00081 public: 00085 enum thread_flags_t { 00088 CREATE_JOINABLE = 1 << 0, 00090 DELETE_ON_EXIT = 1 << 1, 00092 INTERRUPTABLE = 1 << 2, 00094 STARTED = 1 << 3, 00096 SHOULD_STOP = 1 << 4, 00098 STOPPED = 1 << 5, 00099 }; 00100 00101 #ifndef __win32__ 00102 00106 enum thread_signal_t { 00107 INTERRUPT_SIG = SIGURG 00108 }; 00109 #endif 00110 00114 static const int max_live_threads_ = 256; 00115 00120 static Thread* all_threads_[Thread::max_live_threads_]; 00121 00126 static SpinLock* all_threads_lock_; 00127 00135 static void activate_start_barrier(); 00136 00141 static void release_start_barrier(); 00142 00146 static bool start_barrier_enabled() { 00147 return start_barrier_enabled_; 00148 } 00149 00155 static void yield(); 00156 00166 static void spin_yield(); 00167 00174 static ThreadId_t current(); 00175 00179 static bool id_equal(ThreadId_t a, ThreadId_t b); 00180 00184 Thread(const char* name, int flags = 0); 00185 00189 virtual ~Thread(); 00190 00195 void start(); 00196 00200 void join(); 00201 00205 void kill(int sig); 00206 00214 void interrupt(); 00215 00225 void set_interruptable(bool interruptable); 00226 00234 void set_should_stop() { flags_ |= SHOULD_STOP; } 00235 00239 bool should_stop() { return ((flags_ & SHOULD_STOP) != 0); } 00240 00244 bool is_stopped() { return ((flags_ & STOPPED) != 0); } 00245 00249 bool started() { return ((flags_ & STARTED) != 0); } 00250 00254 void set_flag(thread_flags_t flag) { flags_ |= flag; } 00255 00259 void clear_flag(thread_flags_t flag) { flags_ &= ~flag; } 00260 00265 ThreadId_t thread_id() { return thread_id_; } 00266 00267 protected: 00268 #ifdef __win32__ 00270 static __declspec(thread) Thread* current_thread_; 00271 HANDLE join_event_; 00272 #endif // __win32__ 00273 00274 #ifndef __win32__ 00275 static bool signals_inited_; 00276 static sigset_t interrupt_sigset_; 00277 #endif 00278 00279 static bool start_barrier_enabled_; 00280 static std::vector<Thread*> threads_in_barrier_; 00281 00282 ThreadId_t thread_id_; 00283 int flags_; 00284 char name_[64]; 00285 00289 #ifdef __win32__ 00290 static DWORD WINAPI pre_thread_run(void* t); 00291 #else 00292 static void* pre_thread_run(void* t); 00293 #endif 00294 00298 static void interrupt_signal(int sig); 00299 00304 void thread_run(const char* thread_name, ThreadId_t thread_id); 00305 00310 virtual void run() = 0; 00311 }; 00312 00313 //--------------------------------------------------------------------------- 00314 inline ThreadId_t 00315 Thread::current() 00316 { 00317 #ifdef __win32__ 00318 return current_thread_->thread_id_; 00319 #else 00320 return pthread_self(); 00321 #endif 00322 } 00323 00324 //--------------------------------------------------------------------------- 00325 inline void 00326 Thread::yield() 00327 { 00328 #ifndef __win32__ 00329 #ifdef HAVE_THREAD_ID_YIELD 00330 thread_id_yield(); 00331 #elif HAVE_SCHED_YIELD 00332 sched_yield(); 00333 #else 00334 #error MUST EITHER HAVE THREAD_ID_YIELD OR SCHED_YIELD 00335 #endif 00336 #endif // __win32__ 00337 } 00338 00339 //--------------------------------------------------------------------------- 00340 inline void 00341 Thread::spin_yield() 00342 { 00343 // XXX/bowei: 00344 // 1-p call yield() 00345 // o.w. spin 00346 Thread::yield(); 00347 } 00348 00349 } // namespace oasys 00350 00351 #endif /* _OASYS_THREAD_H_ */