thread.C
上传用户:shtangtang
上传日期:2007-01-04
资源大小:167k
文件大小:13k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. //
  2. // Copyright (c) 1999
  3. //
  4. // A C++ implementation of posix threads, using Linux clone system
  5. // calls.
  6. //
  7. // The implementation is identical to the implementation found in
  8. // the linuxthreads package, except that each thread is an object
  9. // here.
  10. //
  11. #include "Config.h"
  12. #undef __THREADS_MAIN
  13. #include "thread.h"
  14. #include "thread_lists.h"
  15. #include "thread_signal_num.h"
  16. #include "thread_cond.h"
  17. #include "shared.h"
  18. extern "C" {
  19. #   include <errno.h>
  20. #   include <unistd.h>
  21. #   include <mcheck.h>
  22. #   include "cloning.h"
  23. };
  24. struct p_arg {
  25.   pthread *_pthread;
  26.   void *_arg;
  27. };
  28. void __program_on_exit(int, void *);
  29. static void __sig_terminate(int);
  30. /**
  31.  * This class is for the definiton of the main in a program.  When
  32.  * program starts, it has its own pid which is different from all
  33.  * threads created afterwards.  The thread manager, must also know
  34.  * about this pid in its lists, for the main routine to be able
  35.  * to perform certain functions, such as join with other threads.
  36.  *
  37.  * This class is provided for this purpose, and will only be
  38.  * implemented in the resulting program, and does not reside in
  39.  * the library.
  40.  *
  41.  * @short The main program thread.
  42.  * @author Orn Hansen <oe.hansen@gamma.telenordia.se>
  43.  */
  44. class __program : public pthread {
  45.  public:
  46.   __program() : pthread(getpid())
  47.     {
  48.       struct sigaction sa;
  49.       // The following signals will terminate the program,
  50.       // we make sure, that they will also remove shared
  51.       // memory page references, on exit.
  52.       sa.sa_handler = __sig_terminate;
  53.       sigemptyset(&sa.sa_mask);
  54.       sigaction(s_terminate, &sa, NULL);
  55.       sigaction(s_kill, &sa, NULL);
  56.       sigaction(s_abort, &sa, NULL);
  57.       sigaction(s_quit, &sa, NULL);
  58.       sigaction(s_interrupt, &sa, NULL);
  59.       sigaction(s_bus_err, &sa, NULL);
  60.       sigaction(s_fpe, &sa, NULL);
  61.       on_exit( __program_on_exit,(void *)0 );
  62.     };
  63.   ~__program()
  64.     {
  65.     }
  66.   void cleanup()
  67.     {
  68.       thread_list::iterator i = thread_list::__threads.begin();
  69.       for( ;i!=thread_list::__threads.end();i++ )
  70. if ( getpid() != (*i)->id() && 
  71.     !(*i)->detached() && !(*i)->canceled() && !(*i)->terminated() ) {
  72.   (*i)->set(cancel_enable);
  73.   (*i)->set(cancel_asynchronous);
  74.   (*i)->cancel();
  75. }
  76.       shared_mem::share.cleanup();
  77.     };
  78.   int thread(void *) { return 0; };
  79. };
  80. shared_mem shared_mem::share;
  81. thread_list thread_list::__waiting_s;  // threads waiting for SIG_RESET
  82. thread_list thread_list::__threads;    // threads active.
  83. __program __main_program_thread;
  84. void __program_on_exit(int p_retcode, void *p_arg)
  85. {
  86.   __main_program_thread.cleanup();
  87. }
  88. //
  89. // Global signal handler, for those signals that will
  90. // terminate the application.
  91. static void __sig_terminate(int __sig)
  92. {
  93. #ifdef DEBUG
  94.   cout << "terminating signal " << __sig << endl;
  95. #endif
  96.   exit(-1);
  97. }
  98. //
  99. // Global signal handler, for SIGUSR1 which in our case is
  100. // PTHREAD_SIG_RESET.  The thread, that owns the signal handler
  101. // is signalled and removed from the list.
  102. static void __sig_handler(int _sig)
  103. {
  104.   thread_list::iterator i = thread_list::__waiting_s.locate(getpid());
  105.   if (i != thread_list::__waiting_s.end()) {
  106.     (*i)->signal(_sig);
  107.     thread_list::__waiting_s.erase(i);
  108.   }
  109. }
  110. //
  111. // Global signal handler, for SIGUSR2 which in our case is
  112. // PTHREAD_SIG_CANCEL.  The thread is checked, if cancel is
  113. // enabled and active.  If so, the thread is stopped on an
  114. // asynchronous cancel type, or a jump made to the users
  115. // specified jump location.
  116. static void __sig_cancel(int _sig)
  117. {
  118.   pthread *th = thread_list::__threads.self();
  119.   if (th != 0) {
  120.     if (th->canceled() && th->cancelstate() == pthread::cancel_enable) {
  121.       if (th->canceltype() == pthread::cancel_asynchronous)
  122. th->exit(PTHREAD_CANCELED);
  123.       th->jump(pthread::cancel_jmp);
  124.     }
  125.   }
  126. }
  127. //
  128. // A function to initialize th signal handlers, for each
  129. // thread.
  130. void __signal_init()
  131. {
  132.   struct sigaction sa;
  133.   sa.sa_handler = __sig_handler;
  134.   sigemptyset(&sa.sa_mask);
  135.   sa.sa_flags = SA_RESTART;
  136.   sigaction(PTHREAD_SIG_RESTART, &sa, NULL);
  137.   sa.sa_handler = __sig_cancel;
  138.   sa.sa_flags = 0;
  139.   sigaction(PTHREAD_SIG_CANCEL, &sa, NULL);
  140. }
  141. //
  142. // This routine, is called directly from __clone() system
  143. // call.  It initalizes the thread, and calls the pthread.thread()
  144. // function, with the given argument.
  145. static int __routine(void *_arg)
  146. {
  147.   p_arg *ap;
  148.   pthread *_p;
  149.   int retcode;
  150.   ap = (p_arg *)_arg;
  151.   _p = ap->_pthread;
  152.   _arg = ap->_arg;
  153.   delete ap;
  154.   __signal_init();
  155.   retcode = _p->thread(_arg);
  156.   _p->exit( retcode );
  157.   /* we never get to this point */
  158.   return 0;
  159. }
  160. //
  161. // class pthread
  162. //
  163. // This class is thought as a superclass to each thread, that is
  164. // wanted in a program.
  165. //
  166. // default constructor.
  167. //
  168. // create a cloned process, and mark it with 0 as argument.
  169. pthread::pthread()
  170. {
  171.   invoke((void *)0);
  172. }
  173. //
  174. // constructor - with argument
  175. //
  176. // create a cloned process, and pass to it the pointer given
  177. // as argument.
  178. pthread::pthread(void *_arg)
  179. {
  180.   invoke(_arg);
  181. }
  182. //
  183. // constructor - with a process id.
  184. //
  185. // create a thread description of the process, given by id, if
  186. // it doesn't already exist on the threads list.
  187. pthread::pthread(int _id)
  188. {
  189.   if (thread_list::__threads.locate(_id) != thread_list::__threads.end())
  190.     return;
  191.   varinit();
  192.   p_id = _id;
  193.   p_sp = 0;
  194.   __signal_init();
  195.   thread_list::__threads.push_back(this);
  196. }
  197. //
  198. // varinit - private
  199. //
  200. // initialize the variables associated with the class with
  201. // default values.
  202. void pthread::varinit()
  203. {
  204.   p_attributes.a_scope = attributes::process_private;
  205.   p_attributes.a_state = attributes::attr_joinable;
  206.   p_id          = -1;
  207.   p_errno       = 0;
  208.   p_priority    = 0;
  209.   p_signal      = 0;
  210.   p_joining     = 0;
  211.   p_retval      = (void *)0;
  212.   p_retcode     = 0;
  213.   p_cancelstate = cancel_enable;
  214.   p_canceltype  = cancel_asynchronous;
  215.   p_canceled    = false;
  216.   p_terminated  = false;
  217.   p_exited      = false;
  218. }
  219. //
  220. // invoke - private
  221. //
  222. // create a stack for the thread and call the clone function with
  223. // __routine() as the starting point.
  224. void pthread::invoke(void *_arg)
  225. {
  226.   p_arg *ap;
  227.   varinit();
  228.   ap       = new p_arg; 
  229.   p_sp = new char[ 4*PAGE_SIZE ];
  230.   if ( p_sp ) {
  231.     ap->_pthread = this;
  232.     ap->_arg = _arg;
  233.     p_id = do_clone(__routine, (void *)ap, (void **)&p_sp);
  234.     if ( p_id < 0 )
  235.       error( EACCES );
  236.   } else
  237.     error( ENOMEM );
  238.   thread_list::__threads.push_back(this);
  239. }
  240. //
  241. // destructor
  242. //
  243. // if the process is running, terminate it.  then free memory and
  244. // remove it from the list of threads.
  245. pthread::~pthread()
  246. {
  247.   if ( !terminated() ) {
  248.     cancel();
  249.     while( !terminated() )
  250.       __sched_yield();
  251.   }
  252.   thread_list::__threads.remove( p_id );
  253.   thread_list::__waiting_s.remove( p_id );
  254.   if ( p_sp )
  255.     delete p_sp;
  256. }
  257. //
  258. // retcode
  259. //
  260. // returns with the return code, that was set by the system.
  261. int pthread::retcode()
  262. {
  263.   return p_retcode;
  264. }
  265. //
  266. // detached
  267. //
  268. // return if the thread is detached, or joinable.
  269. bool pthread::detached() const
  270. {
  271.   return p_attributes.a_state == attributes::attr_detached;
  272. }
  273. //
  274. // joinable
  275. //
  276. // the opposite of detached.
  277. bool pthread::joinable() const
  278. {
  279.   return p_attributes.a_state == attributes::attr_joinable;
  280. }
  281. //
  282. // restart
  283. //
  284. // send a restart signal to the process associated with this thread.
  285. void pthread::restart()
  286. {
  287.   kill(p_id, PTHREAD_SIG_RESTART);
  288. }
  289. //
  290. // suspend
  291. //
  292. // suspend the process, until a restart signal is received.
  293. //
  294. // the thread suspended, is the thread associated with the
  295. // calling process.
  296. void pthread::suspend()
  297. {
  298.   pthread *th = thread_list::__threads.self();
  299.   sigset_t mask;
  300.   if (th != NULL) {
  301.     thread_list::__waiting_s.push_back(th);
  302.     sigprocmask(SIG_SETMASK, NULL, &mask);
  303.     sigdelset(&mask, PTHREAD_SIG_RESTART);
  304.     do {
  305.       th->signal(0);
  306.       sigsuspend(&mask);
  307.     } while(th->signal() != PTHREAD_SIG_RESTART);
  308.   }
  309. }
  310. //
  311. // suspend_with_cancelation
  312. //
  313. // suspend the thread, associated with the calling process
  314. // until a signal is received or it is canceled.
  315. void pthread::suspend_with_cancelation()
  316. {
  317.   pthread *th = thread_list::__threads.self();
  318.   sigset_t mask;
  319.   sigjmp_buf jmpbuf;
  320.   if (th != NULL) {
  321.     thread_list::__waiting_s.push_back(th);
  322.     sigprocmask(SIG_SETMASK, NULL, &mask);
  323.     sigdelset(&mask, PTHREAD_SIG_RESTART);
  324.     if (sigsetjmp(jmpbuf, 0) == 0) {
  325.       th->set(pthread::cancel_jmp, &jmpbuf);
  326.       if (!(th->canceled() && th->cancelstate() == pthread::cancel_enable)) {
  327. do {
  328.   th->signal(0);
  329.   sigsuspend(&mask);
  330. } while(th->signal() != PTHREAD_SIG_RESTART);
  331.       }
  332.       th->set(pthread::cancel_jmp, 0);
  333.     } else {
  334.       sigaddset(&mask, PTHREAD_SIG_RESTART);
  335.       sigprocmask(SIG_SETMASK, &mask, NULL);
  336.     }
  337.   }
  338. }
  339. //
  340. // signal
  341. //
  342. // set the p_signal variable to the given value.  Can only be
  343. // done if called from the process that the thread is associated
  344. // with. If called from a different process, the given signal
  345. // is sent to the process.
  346. int pthread::signal(int _sig)
  347. {
  348.   if (getpid() == p_id)
  349.     p_signal = _sig;
  350.   else
  351.     kill(p_id,_sig);
  352.   return signal();
  353. }
  354. //
  355. // cancel
  356. //
  357. // send a cancel signal to the process assiated with thread. Setting
  358. // the cancelation flag.
  359. void pthread::cancel()
  360. {
  361.   set(pthread::set_canceled, true);
  362.   kill(p_id, PTHREAD_SIG_CANCEL);
  363. }
  364. //
  365. // running
  366. //
  367. // return a true value, if the process associated with the thread
  368. // can be found on the schedulers list.
  369. bool pthread::running()
  370. {
  371.   return (sched_getscheduler(p_id) != -1);
  372. }
  373. //
  374. // exit
  375. //
  376. // perform an exit of the process.  This means marking it as
  377. // terminated and signalling any processes that are joining on
  378. // it.
  379. void pthread::exit(void *_rval)
  380. {
  381.   int joining = 0;
  382.   if (getpid() == p_id) {
  383.     p_canceled   = false;
  384.     p_spinlock.acquire();
  385.     p_retval     = _rval;
  386.     p_terminated = true;
  387.     joining          = p_joining;
  388.     p_spinlock.release();
  389.     if (joining)
  390.       thread_list::__threads.restart(joining);
  391.     _exit(0);
  392.   }
  393. }
  394. //
  395. // exit
  396. //
  397. // perform an exit of the process.  This means marking it as
  398. // terminated and signalling any processes that are joining on
  399. // it.
  400. void pthread::exit(int _retcode)
  401. {
  402.   int joining = 0;
  403.   if (getpid() == p_id) {
  404.     p_canceled   = false;
  405.     p_spinlock.acquire();
  406.     p_retcode    = _retcode;
  407.     p_terminated = true;
  408.     joining          = p_joining;
  409.     p_spinlock.release();
  410.     if (joining)
  411.       thread_list::__threads.restart(joining);
  412.     _exit( _retcode );
  413.   }
  414. }
  415. //
  416. // set - booleans
  417. //
  418. // set any of the boolean values, terminated exited canceled or
  419. // detached.
  420. void pthread::set(booleans _set, bool _val)
  421. {
  422.   switch(_set) {
  423.   case pthread::set_terminated:
  424.     p_terminated = _val;
  425.     break;
  426.   case pthread::set_detached:
  427.     if ( _val )
  428.       p_attributes.a_state = attributes::attr_detached;
  429.     else
  430.       p_attributes.a_state = attributes::attr_joinable;
  431.     break;
  432.   case pthread::set_exited:
  433.     p_exited = _val;
  434.     break;
  435.   case pthread::set_canceled:
  436.     p_canceled = _val;
  437.     break;
  438.   case pthread::set_private:
  439.     break;
  440.   }
  441. }
  442. //
  443. // set - jumps
  444. //
  445. // set the signalling jumps, signal or cancel.  
  446. void pthread::set(jumps _typ, sigjmp_buf *_jbuf)
  447. {
  448.   switch(_typ) {
  449.   case cancel_jmp:
  450.     p_cancel_jmp = _jbuf;
  451.     break;
  452.   case signal_jmp:
  453.     p_signal_jmp = _jbuf;
  454.     break;
  455.   }
  456. }
  457. //
  458. // join
  459. //
  460. // suspend the calling process (thread), until the thread
  461. // owning the call has terminated.
  462. int pthread::join()
  463. {
  464.   thread_list::iterator i = thread_list::__threads.locate(getpid());
  465.   if ( p_id == getpid() )
  466.     return EDEADLK;
  467.   if ( i == thread_list::__threads.end() )
  468.     return ESRCH;
  469.   if ( detached() || joining() != 0 || !joinable() )
  470.     return EINVAL;
  471.   if (!terminated()) {
  472.     joining(getpid());
  473.     (*i)->suspend_with_cancelation();
  474.     if (canceled() && cancelstate() == pthread::cancel_enable) {
  475.       joining(0);
  476.       exit(PTHREAD_CANCELED);
  477.     }
  478.   }
  479.   return 0;
  480. }
  481. //
  482. // jump
  483. //
  484. // do a jump, to either signal or cancel locations.  If they
  485. // are specified.
  486. void pthread::jump(jumps _typ)
  487. {
  488.   sigjmp_buf *jmp_buf = 0;
  489.   switch(_typ) {
  490.   case cancel_jmp:
  491.     jmp_buf = p_cancel_jmp;
  492.     break;
  493.   case signal_jmp:
  494.     jmp_buf = p_signal_jmp;
  495.     break;
  496.   }
  497.   if (jmp_buf != 0)
  498.     siglongjmp(*jmp_buf, 1);
  499. }
  500. //
  501. // set_project
  502. //
  503. // This is a way for the user to communicate with the
  504. // shared memory control.
  505. void pthread::set_project(const char *p_name)
  506. {
  507.   shared_mem::share.change_proj( p_name );
  508. }
  509. //
  510. // set_permission
  511. //
  512. // Set the project permission attributes.
  513. void pthread::set_permission(int p_perm)
  514. {
  515.   shared_mem::share.change_perm( p_perm );
  516. }
  517. //
  518. // shalloc
  519. //
  520. // allocate shared memory
  521. void *pthread::shalloc(size_t p_size)
  522. {
  523.   return shared_mem::share.alloc(p_size, 0);
  524. }
  525. //
  526. // shdealloc
  527. //
  528. // deallocate shared memory
  529. void pthread::shdealloc(void *p_ptr)
  530. {
  531.   shared_mem::share.dealloc(p_ptr);
  532. }