00001 // Made by Fred, for Coen445. 00002 // Last modifications: 30/Oct/2000 2:14:41am 00003 // LGPL licensed. 00004 00005 #ifndef __J2K__PThread_HPP__ 00006 #define __J2K__PThread_HPP__ 00007 00008 #include <j2k/Fred/Standard.hpp> 00009 #include <j2k/Fred/Error/JErrorController.hpp> 00010 #include <pthread.h> 00011 00012 // #include <process.h> 00013 00014 #include <sched.h> 00015 00016 #include <time.h> 00017 #include <signal.h> 00018 #include <sys/types.h> 00019 00020 #include <j2k/445/Posix/Mutex.hpp> 00021 00022 #define pid_t pthread_t 00023 00024 /************************************************************************* 00025 ** FILE NAME : <j2k/445/Posix/PThread.hpp> ** 00026 ** CLASS NAME : PThread ** 00027 ** DESCRIPTION : This class allows the creation of Generic Thread ** 00028 ** which takes care of the internals ** 00029 ** of the PThread features. Any other subsequent ** 00030 ** classes can use this thread, or can appear as thread ** 00031 ** just by inheriting from this basic class. ** 00032 *************************************************************************/ 00033 00034 // Default Arguments 00035 #define DEFAULT_STACK 4096 00036 #define DEFAULT_ALGO SCHED_RR 00037 #define DEFAULT_PRIO 12 00038 #define DEFAULT_NODE 0 00039 00040 #define INVALID_PID ((unsigned)(-1)) 00041 00042 // What is it ?! 0 00043 #define DEFAULT_POLICY 0 00044 00045 // Alias for Scheduling Schemes 00046 #define S_FIFO SCHED_FIFO 00047 #define S_ROUND_ROBIN SCHED_RR 00048 #define S_ADAPTIVE SCHED_OTHER 00049 00050 // Message Passing Values 00051 #define MSG_NONE 0 00052 #define MSG_STOP 1 00053 #define MSG_REFRESH 2 00054 #define MSG_YIELD 3 00055 #define MSG_PRINT 4 00056 #define MSG_FUNCTION 5 00057 00058 00059 /************************************************************** 00060 *************************************************************** 00061 *** Attribute Default Value *** 00062 *** ========= ============= *** 00063 *** detachstate PTHREAD_CREATE_JOINABLE *** 00064 *** schedpolicy PTHREAD_INHERIT_SCHED *** 00065 *** schedparam Inherited from parent thread *** 00066 *** contentionscope PTHREAD_SCOPE_SYSTEM *** 00067 *** stacksize 4096 *** 00068 *** stackaddr NULL *** 00069 *************************************************************** 00070 **************************************************************/ 00071 00072 /************************************************************** 00073 *************************************************************** 00074 *** *** 00075 *** typedef struct { *** 00076 *** int detachstate; *** 00077 *** int schedpolicy; *** 00078 *** struct sched_param schedparam; *** 00079 *** int inheritsched; *** 00080 *** int scope; *** 00081 *** } pthread_attr_t; *** 00082 *** *** 00083 *************************************************************** 00084 **************************************************************/ 00085 00086 class PThread { 00087 // MC_SerializeHeader() 00088 00089 public: 00090 00091 // Default Constructor 00092 // inline PThread(); 00093 inline PThread( BOOL autostart = FALSE, BOOL autojoin = FALSE ); 00094 00095 // Destructor 00096 inline virtual ~PThread(); 00097 00098 private: 00099 // VERIFY THOSE ! 00100 // Copy Constructor 00101 inline PThread( const PThread& src ); 00102 00103 // Assign Operator 00104 inline const PThread& operator=( const PThread& src ); 00105 00106 public: 00107 00108 /****************************************************************** 00109 ******************************************************************* 00110 *** *** 00111 *** Detach state: *** 00112 *** *** 00113 *** PTHREAD_CREATE_JOINABLE == 0 (DEFAULT ) *** 00114 *** Thread is created in a joinable state. (default) *** 00115 *** *** 00116 *** PTHREAD_CREATE_DETACHED != 0 *** 00117 *** Thread is created in a detached state. *** 00118 *** *** 00119 ******************************************************************* 00120 ******************************************************************/ 00121 00122 inline int getDetachState(); 00123 inline void setDetachState( int state ); 00124 00125 /****************************************************************** 00126 ******************************************************************* 00127 *** *** 00128 *** If guardsize is 0, threads created with attr have *** 00129 *** no guard area; otherwise, a guard area of at least *** 00130 *** guardsize bytes is provided. The default guardsize *** 00131 *** can be found using the _SC_PAGESIZE constant *** 00132 *** in a call to sysconf(). *** 00133 *** *** 00134 *** The guardsize attribute controls the size of the guard *** 00135 *** area for the thread's stack. This guard area helps *** 00136 *** protect against stack overflows; guardsize bytes *** 00137 *** of extra memory is allocated at the overflow end *** 00138 *** of the stack. If a thread overflows into this buffer *** 00139 *** it receives a SIGSEGV signal. *** 00140 *** *** 00141 *** The guardsize attribute is provided because: *** 00142 *** *** 00143 *** - Stack overflow protection can waste system resources. *** 00144 *** An application that creates many threads can save *** 00145 *** system resources by turning off guard areas *** 00146 *** if it trusts its threads not to overflow the stack. *** 00147 *** *** 00148 *** - When threads allocate large objects on the stack, *** 00149 *** a large guardsize is required to detect stack overflows. *** 00150 *** *** 00151 *** *** 00152 *** NOTICE: *** 00153 *** ======= *** 00154 *** *** 00155 *** If the caller is providing a stack *** 00156 *** (using attr's stackaddr attribute; *** 00157 *** see pthread_attr_setstackaddr()), *** 00158 *** the guardsize is ignored and there's no stack overflow *** 00159 *** protection for that thread. *** 00160 *** *** 00161 *** The guardsize argument is completely ignored *** 00162 *** when using a physical mode memory manager. *** 00163 *** *** 00164 ******************************************************************* 00165 ******************************************************************/ 00166 00167 inline size_t getGuardSize(); 00168 inline void setGuardSize( size_t sz ); 00169 00170 /****************************************************************** 00171 ******************************************************************* 00172 *** *** 00173 *** Get thread inherit scheduling attribute *** 00174 *** *** 00175 *** The inherit scheduling attribute determines *** 00176 *** whether a thread inherits the scheduling *** 00177 *** policy of its parent. *** 00178 *** *** 00179 ******************************************************************* 00180 ******************************************************************/ 00181 00182 inline int getInheritSched(); 00183 00184 /****************************************************************** 00185 ******************************************************************* 00186 *** *** 00187 *** Set thread inherit scheduling attribute *** 00188 *** *** 00189 *** PTHREAD_INHERIT_SCHED ( DEFAULT ) *** 00190 *** Thread inherits the scheduling policy of parent thread. *** 00191 *** *** 00192 *** PTHREAD_EXPLICIT_SCHED *** 00193 *** Thread has the scheduling policy specified in attr. *** 00194 *** *** 00195 ******************************************************************* 00196 ******************************************************************/ 00197 00198 inline void setInheritSched( int sched ); 00199 00200 00201 // This is to be ajusted with maybe a sched_param class !? 00202 inline sched_param* getSchedParam(); 00203 00204 /****************************************************************** 00205 ******************************************************************* 00206 *** *** 00207 *** Get thread scheduling parameters *** 00208 *** *** 00209 *** sched_priority *** 00210 *** Inherited from parent thread ( DEFAULT ) *** 00211 *** *** 00212 *** The thread scheduling parameters are only used *** 00213 *** if you have set the thread inherit scheduling *** 00214 *** attribute to PTHREAD_EXPLICIT_SCHED *** 00215 *** using pthread_attr_setinheritsched(). *** 00216 *** *** 00217 ******************************************************************* 00218 ******************************************************************/ 00219 00220 00221 inline void setSchedParam( sched_param* param ); 00222 00223 // Get thread scheduling policy attribute 00224 inline int getSchedPolicy(); 00225 00226 /****************************************************************** 00227 ******************************************************************* 00228 *** *** 00229 *** Sets the thread scheduling policy attribute *** 00230 *** in the thread attribute object attr to policy. *** 00231 *** *** 00232 *** The thread scheduling policy attribute can have *** 00233 *** the following values on QNX/Neutrino: *** 00234 *** *** 00235 *** SCHED_FIFO First-In First-Out scheduling. *** 00236 *** SCHED_RR Round-Robin scheduling. *** 00237 *** SCHED_OTHER Currently the same as SCHED_RR. *** 00238 *** SCHED_NOCHANGE Don't change the policy. *** 00239 *** *** 00240 *** The policy attribute is only used if you have set *** 00241 *** the thread inherit scheduling attribute *** 00242 *** to PTHREAD_EXPLICIT_SCHED using *** 00243 *** pthread_attr_setinheritsched(). *** 00244 *** *** 00245 ******************************************************************* 00246 ******************************************************************/ 00247 00248 inline void setSchedPolicy( int policy ); 00249 00250 /****************************************************************** 00251 ******************************************************************* 00252 *** *** 00253 *** Sets the thread contention scope attribute *** 00254 *** *** 00255 *** PTHREAD_SCOPE_SYSTEM (DEFAULT and ONLY VALUE) *** 00256 *** All threads are scheduled together. *** 00257 *** *** 00258 ******************************************************************* 00259 ******************************************************************/ 00260 00261 inline int getScope(); 00262 inline void setScope( int scope ); 00263 00264 /****************************************************************** 00265 ******************************************************************* 00266 *** *** 00267 *** Sets the thread stack address attribute *** 00268 *** *** 00269 *** The default value for the thread stack address attribute *** 00270 *** is NULL. A thread created with a NULL stack address *** 00271 *** attribute will have a stack dynamically allocated *** 00272 *** by the system of minimum size PTHREAD_STACK_MIN. *** 00273 *** The allocated stack will be reclaimed when the thread *** 00274 *** terminates. If a stack is allocated by the user then *** 00275 *** it must be released by the user. *** 00276 *** *** 00277 *** For QNX/Neutrino, PTHREAD_STACK_MIN is enough memory *** 00278 *** to run a thread that does nothing ! *** 00279 *** *** 00280 ******************************************************************* 00281 ******************************************************************/ 00282 00283 inline void* getStackAddress(); 00284 inline void setStackAddress( void* addr ); 00285 00286 /****************************************************************** 00287 ******************************************************************* 00288 *** *** 00289 *** The stacksize must be larger than PTHREAD_STACK_MIN, *** 00290 *** which is the default value. *** 00291 *** *** 00292 ******************************************************************* 00293 ******************************************************************/ 00294 00295 inline size_t getStackSize(); 00296 inline void setStackSize( size_t sz ); 00297 00298 /****************************************************************** 00299 ******************************************************************* 00300 *** *** 00301 *** This function request that the the thread be cancelled *** 00302 *** (terminated). The cancellation type and state of the *** 00303 *** target determine when the cancellation takes effect. *** 00304 *** *** 00305 *** When the cancellation is acted on, the target's *** 00306 *** cancellation cleanup handlers are called. *** 00307 *** *** 00308 *** When the last cancellation cleanup handler returns, *** 00309 *** the data destructor function is called, once this *** 00310 *** is done the thread is terminated. *** 00311 *** *** 00312 *** The cancellation processing in the target thread runs *** 00313 *** asynchronously with respect to the calling thread. *** 00314 *** *** 00315 ******************************************************************* 00316 ******************************************************************/ 00317 00318 // Cancel thread 00319 inline void cancel(); 00320 00321 inline void create( const pthread_attr_t* attr = NULL ); 00322 00323 inline void detach(); 00324 00325 inline const BOOL operator==( const PThread& right ); 00326 inline const BOOL operator!=( const PThread& right ); 00327 00328 inline void terminate( void* ptr = NULL ); 00329 00330 // Get the level of thread concurrency 00331 inline int getConcurrency(); 00332 00333 // Get thread scheduling parameters 00334 inline sched_param* getSchedParam( int* policy ); 00335 00336 // Get thread specific key data value 00337 inline void* getKey( pthread_key_t key ); 00338 00339 // Join thread 00340 inline void join( void** value_ptr = NULL ); 00341 00342 // Send a signal to a thread 00343 inline void kill( int sig ); 00344 00345 // Dynamic package initialization 00346 inline void dynamicPackageInit( void (*init_routine)(void) = NULL ); 00347 00348 // Get calling thread's ID 00349 inline pid_t getPID(); 00350 00351 // Set the concurrency level for a thread 00352 inline void setConcurrencyLevel( int new_level ); 00353 00354 // Set thread specific key data value 00355 inline void setKeyValue( pthread_key_t key, const void* value ); 00356 00357 // Examine and change blocked signals 00358 inline sigset_t* changeBlockedSignals( int how, const sigset_t* set ); 00359 00360 // Test thread cancellation 00361 inline void testCancellation(); 00362 00363 00364 // Implement this, when deriving the class. 00365 // It should be overriden by it's children... 00366 virtual void run() = 0; 00367 00368 // Callback can only call STATIC functions ! 00369 // ========================================= 00370 // This routine is a stub which will call 00371 // the run() routine given the class instance 00372 // as the void pointer argument. 00373 00374 static void* PThread::Wrapper( void* ptrThis ) 00375 { 00376 PThread* me = (PThread*)ptrThis; 00377 00378 guard.lock(); 00379 log_start_count++; 00380 guard.unlock(); 00381 00382 // Call the derived classes version, since the function 00383 // run is implemented by it's children 00384 me->run(); 00385 00386 guard.lock(); 00387 log_stop_count++; 00388 guard.unlock(); 00389 00390 // run() should contain an Infinite Loop, i.e. for(;;) { ... } 00391 // Exit beautifully, just in case there is no infinite loop. 00392 00393 me->pid = (unsigned)(-1); 00394 pthread_exit( NULL ); 00395 00396 return NULL; 00397 } 00398 00399 virtual void start(); 00400 inline void start( size_t, int, int, int ); 00401 00402 /* 00403 size_t stack_size = DEFAULT_STACK, 00404 int alg = DEFAULT_ALGO, 00405 int prio = DEFAULT_PRIO, 00406 int policy = DEFAULT_POLICY ); 00407 */ 00408 00409 inline void yield(); 00410 inline void refresh(); 00411 inline void stop(); 00412 inline void exit(); 00413 00414 inline BOOL isStarted(); 00415 00416 // Get Initial Starting values 00417 inline size_t getStack() { return start_stack; } 00418 inline int getStartAlgo() { return start_algo; } 00419 inline int getStartPriority() { return start_prio; } 00420 inline int getStartPolicy() { return start_policy; } 00421 00422 // Get, Set, Reset Priority and Scheduling Schemes 00423 inline int getPriority(); 00424 inline void setPriority( int prio ); 00425 inline void resetPriority(); 00426 00427 inline int getScheduler(); 00428 inline void setScheduler( int sched ); 00429 inline void setScheduler( int sched, const sched_param* param ); 00430 00431 inline void resetScheduler(); 00432 00433 // Set thread scheduling parameters 00434 inline sched_param* getSchedulerParam(); 00435 inline void setSchedulerParam( int policy, const sched_param* param = NULL ); 00436 inline void resetSchedulerParam(); 00437 00438 00439 // Get calling thread's ID 00440 inline pthread_t PThread::getSelf(); 00441 00442 // Set a thread's cancellation state 00443 inline int setCancelState( int new_state ); 00444 00445 // Set a thread's cancellation type 00446 inline int setCancelType( int new_type ); 00447 00448 inline int enableCancel(); 00449 inline int disableCancel(); 00450 00451 inline void setCocurrencyLevel( int new_level ); 00452 00453 // Polling for termination request function 00454 // ======================================== 00455 // A termination request will only work, 00456 // if the thread executive checks the term 00457 // request state using this method. 00458 // Returns TRUE, if a call to request_termination 00459 // has been made against this thread object instance. 00460 00461 BOOL poll_termrequest(); 00462 void request_termination(); 00463 00464 00465 public: 00466 00467 // Overall thread helper methods. 00468 // These make it easier to coordinate termination 00469 // as the total number of threads versus the 00470 // number of currently running threads can be 00471 // retrieved. 00472 // 00473 // Upon failure, these routines return 00474 // the unsigned value of 0xFFFFFFFF. 00475 00476 static ULONG get_create_count(); 00477 static ULONG get_delete_count(); 00478 static ULONG get_start_count(); 00479 static ULONG get_stop_count(); 00480 00481 protected: 00482 00483 BOOL termination_requested; 00484 00485 // Keeping track of what's happening... 00486 // ==================================== 00487 // This class keeps track of the number 00488 // of instances created and deleted. 00489 // It also, provides mechanisms for tracking 00490 // the number of instances stopped or started. 00491 00492 static ULONG log_create_count; 00493 static ULONG log_delete_count; 00494 static ULONG log_start_count; 00495 static ULONG log_stop_count; 00496 00497 // Obligatory mutual exclusion guard 00498 // against bad behavior such as race conditions, etc. 00499 static PThread_Mutex PThread::guard; 00500 00501 protected: 00502 // So, children can access easily the PID 00503 pid_t pid; 00504 ULONG threadNo; 00505 pthread_attr_t attr; 00506 00507 // Private, since only used by Reset and Restart functions 00508 private: 00509 sched_param* start_param; 00510 size_t start_stack; 00511 int start_algo; 00512 int start_prio; 00513 int start_policy; 00514 00515 BOOL isDetached; 00516 00517 }; 00518 00519 #endif