⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.c

📁 用c++包装好的线程库,直接拿来使用,提高效率.
💻 C
📖 第 1 页 / 共 2 页
字号:
//// Copyright (c) 1999//// A C++ implementation of posix threads, using Linux clone system// calls.//// The implementation is identical to the implementation found in// the linuxthreads package, except that each thread is an object// here.//#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "thread.h"#include "threads/exception.h"#include "threads/signal_num.h"#include "threads/cond.h"#include "threads/stack.h"#include "shared.h"#include "thread_lists.h"#include "sig_handler.h"#include <cstdlib>#include <cerrno>extern "C" {#   include <unistd.h>#   include <sys/ioctl.h>#   include <sys/types.h>#   include <sys/wait.h>#   include "cloning.h"};// We're hard coding this here, to ensure that stack sizes won't be// located with faulty sizes.namespace cpp_threads {  template class signalling<Pthread>;  struct process_arg {    Pthread   *s_pthread;    void      *s_arg;    Semaphore *s_sem;  };  void __program_on_exit(int, void *);  SharedMemory SharedMemory::share;  ThreadList ThreadList::__waiting_s;  // threads waiting for SIG_RESET  ThreadList ThreadList::__threads;    // threads active.  /**   * This class is for the definiton of the main in a program.  When   * program starts, it has its own pid which is different from all   * threads created afterwards.  The thread manager, must also know   * about this pid in its lists, for the main routine to be able   * to perform certain functions, such as join with other threads.   *   * This class is provided for this purpose, and will only be   * implemented in the resulting program, and does not reside in   * the library.   *   * @short The main program thread.   * @author Orn Hansen <oe.hansen@gamma.telenordia.se>   */  class __program : public Pthread {  public:    __program() : Pthread(getpid())    {      on_exit( program_on_exit,(void *)0 );    }    ~__program()    {      Pthread::debug("main program destroyed");      sys::exit(retcode());    }    static void program_on_exit(int, void *);    int thread(void *) { return 0; };  };  //  // This is a static reference pointer to the main  // program.  __program __main_program_thread;  void __program::program_on_exit(int retcode_p, void *arg_p)  {    if( getpid() == __main_program_thread.id() ) {      Pthread::debug("__program_on_exit(%d,%x)",retcode_p,arg_p);      __main_program_thread.cleanup();    }  }  //  // Global signal handler, for those signals that will  // terminate the application.  void Pthread::sig_terminate(int sig_p)  {    Pthread *th = ThreadList::__threads.self();    Pthread::debug("terminating signal %d",sig_p);    if( th )      th->exit(-1);    else      sys::exit(-1);  }  //  // Global signal handler, that is used to delete all child  // processes from the list.  void Pthread::sig_childexit(int sig_p)  {    Pthread *th;    int stat,pid;    while( true ) {      pid = wait3( &stat,__WCLONE|WNOHANG|WUNTRACED,0 );      Pthread::debug("s_child from %d",pid);      if( pid > 0 ) {	th = ThreadList::__threads.ptr(pid);	if( th ) {	  if( WIFEXITED(stat) )	    th->state( Pthread::p_exited_e );	  else if( WIFSIGNALED(stat) )	    th->state( Pthread::p_terminated_e );	  else if( WIFSTOPPED(stat) ) {	    th->state( Pthread::p_terminated_e );	    Pthread::debug(" - Stopped by signal %d",WSTOPSIG(stat));	  } else	    continue;	  ThreadList::__threads.remove(pid);	}      } else	break;    }  }  //  // Global signal handler, for SIGUSR1 which in our case is  // CPPTHREAD_SIG_RESET.  The thread, that owns the signal handler  // is signalled and removed from the list.  void Pthread::sig_handler(int sig_p)  {    Pthread *th = ThreadList::__threads.self();    if ( th ) {      if( th->isSet(Pthread::signal_jmp_e) ) {	Pthread::debug("jumping jack flash");	th->jump( Pthread::signal_jmp_e );      } else {	Pthread::debug("reset signal");	th->signal(sig_p);	ThreadList::__waiting_s.remove(th->id());      }    }  }  //  // Global signal handler, for SIGUSR2 which in our case is  // CPPTHREAD_SIG_CANCEL.  The thread is checked, if cancel is  // enabled and active.  If so, the thread is stopped on an  // asynchronous cancel type, or a jump made to the users  // specified jump location.  void Pthread::sig_cancel(int sig_p)  {    Pthread *th = ThreadList::__threads.self();        if ( th ) {      Pthread::debug("cancel");      if (th->canceled() && th->cancelstate() == Pthread::cancel_enable_e) {	if (th->canceltype() == Pthread::cancel_asynchronous_e)	  th->exit( CPPTHREAD_CANCELED );	th->jump( Pthread::cancel_jmp_e );      }    } else      Pthread::debug("No such thread");  }  //  // Stop or suspend a running process... done from an outside  // process.  void Pthread::sig_stop(int sig_p)  {    Pthread *th = ThreadList::__threads.self();    if ( th ) {      Pthread::debug("__sig_stop");      th->suspend();    }  }  //  // A function to initialize the signal handlers, for each  // thread.  void Pthread::signal_init()  {    sigset_t mask;    struct sigaction sa;    Pthread::debug("__signal_init()");    sigemptyset(&mask);    sigaddset(&mask,s_continue);    sigprocmask(SIG_SETMASK,&mask,0);    sa.sa_handler = sig_handler;    sigemptyset(&sa.sa_mask);    sa.sa_flags = SA_RESTART;    sigaddset(&sa.sa_mask,s_child);    sys::sigaction(CPPTHREAD_SIG_RESTART, &sa, NULL);    sa.sa_handler = sig_cancel;    sys::sigaction(s_quit, &sa, NULL);    sa.sa_handler = sig_stop;    sys::sigaction(s_keyboard, &sa, NULL);    sa.sa_handler = sig_terminate;    sigemptyset(&sa.sa_mask);    if( CPPTHREAD_SIG_CANCEL != s_quit )      sys::sigaction(s_quit, &sa, NULL);    sys::sigaction(s_bus_err, &sa, NULL);    sys::sigaction(s_fpe, &sa, NULL);    sys::sigaction(s_terminate, &sa, NULL);    sys::sigaction(s_hangup, &sa, NULL);    sys::sigaction(s_abort, &sa, NULL);    sys::sigaction(s_interrupt, &sa, NULL);    sa.sa_handler = sig_childexit;    sys::sigaction(s_child, &sa, NULL);  }  //  // This routine, is called directly from __clone() system  // call.  It initalizes the thread, and calls the Pthread.thread()  // function, with the given argument.  int Pthread::__routine(void *arg_p)  {    process_arg *ap;    Pthread *p;    Semaphore *sem;    int retcode;    ap    = (process_arg *)arg_p;    p     = ap->s_pthread;    arg_p = ap->s_arg;    sem   = ap->s_sem;    delete ap;    while( ThreadList::__threads.self() == 0 )      sched_yield();    if ( sem ) {      sem->wait();      // A class may post to the Semaphore, as the last operation      // in the constructor.  By yeilding twice, perhaps a usleep ?      // should provide enough time for the constructor to finish.      sched_yield();      sched_yield();    }    p->state( Pthread::p_running_e );    p->schedule( p->_attributes );    retcode = p->thread(arg_p);    Pthread::debug("return(%d)",retcode);    p->exit( retcode );    /* we never get to this point */    return 0;  }  //  // class Pthread  //  // This class is thought as a superclass to each thread, that is  // wanted in a program.  //  // default constructor.  //  // create a cloned process, and mark it with 0 as argument.  Pthread::Pthread(Semaphore *sem_p,size_t stackPages_p)  {    invoke((void *)0,sem_p,stackPages_p);  }  //  // constructor - with argument  //  // create a cloned process, and pass to it the pointer given  // as argument.  Pthread::Pthread(void *arg_p,Semaphore* sem_p,size_t stackPages_p)  {    invoke(arg_p,sem_p,stackPages_p);  }  //  // constructor - with a process id.  //  // create a thread description of the process, given by id, if  // it doesn't already exist on the threads list.  Pthread::Pthread(int id_p)  {    if ( ThreadList::__threads.ptr(id_p) )      return;    Pthread::debug("envelope %d",id_p);    varinit();    _tid  = id_p;    _ppid = getppid();    _sp   = 0;    signal_init();    ThreadList::__threads.pushBack(this);  }  //  // varinit - private  //  // initialize the variables associated with the class with  // default values.  void Pthread::varinit()  {    debug("scope %d",_attributes.a_scope);    _tid         = -1;    _errno       = 0;    _priority    = 0;    _signal      = 0;    _joining     = 0;    _cancel_jmp  = 0;    _signal_jmp  = 0;    _retval      = (void *)0;    _retcode     = 0;    _cancelstate = cancel_enable_e;    _canceltype  = cancel_asynchronous_e;    _state       = p_stopped_e;  }  //  // invoke - private  //  // create a stack for the thread and call the clone function with  // __routine() as the starting point.  void Pthread::invoke(void *arg_p,Semaphore *sem_p,size_t stackPages_p)  {    process_arg *ap = 0;        varinit();    if ( stackPages_p < 8 )      stackPages_p = 8;    ap        = new process_arg;    _sp       = new ThreadStack(stackPages_p*STACK_PAGE_SIZE);    if ( _sp && ap ) {      if( sem_p == 0 )	sem_p = new Semaphore;      ap->s_pthread = this;      ap->s_arg     = arg_p;      ap->s_sem     = _runner = sem_p;      _ppid = getpid();      Pthread::debug("cloning");      _tid  = beginthread(__routine, _sp->top(), (void *)ap);      Pthread::debug("clone is %d",_tid);      if ( _tid < 0 )	exception::fatal( EACCES );      else if( _tid > 0 )	ThreadList::__threads.pushBack(this);    } else      exception::fatal( ENOMEM );  }  //  // destructor  //  // if the process is running, terminate it.  then free memory and  // remove it from the list of threads.  Pthread::~Pthread()  {    Pthread::debug("object %d delete",id());    if( getpid() != id() && !terminated() ) {      Pthread::debug("need to terminate state %d",state());      kill(id(),s_quit);      usleep(100);    }    Pthread::debug("remove from lists");    ThreadList::__threads.remove( _tid );    ThreadList::__waiting_s.remove( _tid );    Pthread::debug("destroy stack");    if ( _sp )      delete _sp;    Pthread::debug("object deleted");  }  void   Pthread::cleanup()  {    int n = 0, status;    Pthread *th            = ThreadList::__threads.self();    Pthread *child=ThreadList::__threads.child(th->id());    debug("cleanup()");    for( ;child;child=ThreadList::__threads.nextChild(child) )      if ( !child->detached() && !child->canceled() && !child->terminated() ) {	debug("cleanup %d in state %d",child->id(),child->state());	child->set(cancel_enable_e);	child->set(cancel_asynchronous_e);	child->cancel();	waitpid(child->id(),&status,WUNTRACED);      }    SharedMemory::share.cleanup();    debug("cleanup() %d done.",n);  };    void   Pthread::exit_child(int retcode_p)  {    ThreadList::__threads.remove( getpid() );    ThreadList::__waiting_s.remove( getpid() );    kill( getppid(),s_child );    ::_exit( retcode_p );  }  //  // state  //  // query the state of the process  Pthread::thread_state Pthread::state()  {    return _state;  }  //  // state  //  // set the state of the process  Pthread::thread_state Pthread::state(thread_state state_p)  {    thread_state old_state = _state;    if( getpid() == id() || getpid() == ppid() )      _state = state_p;    return old_state;  }  //  // run  //  // put the process into running state  void Pthread::run()  {    if( _runner )      _runner->post();  }  //  // retcode  //  // returns with the return code, that was set by the system.  int Pthread::retcode()  {    return _retcode;  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -