bug-commoncpp
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problems with Linux CommonC++ Thread Class scheduling


From: David Sugar
Subject: Re: Problems with Linux CommonC++ Thread Class scheduling
Date: Fri, 22 Jun 2001 10:48:00 -0400
User-agent: Mozilla/5.0 (X11; U; Linux 2.2.16-9mdk i686; en-US; m18) Gecko/20001013

Okay, I have attached what I think will be the final version of this...


Ian Campbell wrote:

The code below that gets the priority and the policy of the creating
process and uses that to create the new thread so that should be ok. Not
sure what happens in other implementations though.

Ian

Ian Campbell
Band-X
t: +44 (0) 207 932 8846
f: +44 (0) 207 932 8800
e: address@hidden

On Fri, 22 Jun 2001, David Sugar wrote:


I have thought about this more, and I think the most correct solution is that
the setinherit should be called, but only when pri = 0, which indicates you do
want it scheduled the same as the parent, or in systems which do not allow
setting and changing of scheduler priorities anyway.  So I will do a more
specific implimentation of this.

David

Ian Campbell wrote:


Hello All,
        I have been experimenting with the CommonC++ Thread class on Linux
using the realtime pthread scheduler (either SCHED_RR or SCHED_FIFO) and
found it doesn't work properly in the 1.4.3 release. This fault means that
you can't give seperate threads a different priority from the creating
main process. This is caused by a call to pthread_attr_setinheritsched()
which according to the man page means that the priority and policy for
thread scheduler must be inherited from the creating thread. As such any
subsequent calls to pthread_attr_setschedpolicy() and
pthread_attr_setschedparam() will have no effect. Anyway the patch at the
end of this email should fixeth the problem.

Cheers,

Ian Campbell
Band-X
t: +44 (0) 207 932 8846
f: +44 (0) 207 932 8800
e: address@hidden

diff -u -r CommonC++-1.4.3/posix/thread.cpp
CommonC++-1.4.3-sched.patch/posix/thread.cpp
--- CommonC++-1.4.3/posix/thread.cpp    Thu May 31 08:30:51 2001
+++ CommonC++-1.4.3-sched.patch/posix/thread.cpp        Thu Jun 21
12:41:08 2001
@@ -1,23 +1,23 @@
 // Copyright (C) 1999-2001 Open Source Telecom Corporation.
-//
+//
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
 // the Free Software Foundation; either version 2 of the License, or
 // (at your option) any later version.
-//
+//
 // This program is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU General Public License for more details.
-//
+//
 // You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
+// along with this program; if not, write to the Free Software
 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
-//
-// As a special exception to the GNU General Public License, permission
is
-// granted for additional uses of the text contained in its release
+//
+// As a special exception to the GNU General Public License, permission
is
+// granted for additional uses of the text contained in its release
 // of Common C++.
-//
+//
 // The exception is that, if you link the Common C++ library with other
 // files to produce an executable, this does not by itself cause the
 // resulting executable to be covered by the GNU General Public License.
@@ -27,16 +27,16 @@
 // This exception does not however invalidate any other reasons why
 // the executable file might be covered by the GNU General Public
License.
 //
-// This exception applies only to the code released under the
+// This exception applies only to the code released under the
 // name Common C++.  If you copy code from other releases into a copy of
 // Common C++, as the General Public License permits, the exception does
 // not apply to the code that you add in this way.  To avoid misleading
 // anyone as to the status of such modified files, you must delete
 // this exception notice from them.
-//
+//
 // If you write modifications of your own for Common C++, it is your
choice
 // whether to permit this exception to apply to your modifications.
-// If you do not wish that, delete this exception notice.
+// If you do not wish that, delete this exception notice.

 #include "config.h"
 #include "macros.h"
@@ -137,7 +137,7 @@
                sigaction(SIGPOLL, &act, NULL);
 #else
                sigaction(SIGIO, &act, NULL);
-#endif
+#endif

 #ifndef        _SIG_THREAD_STOPCONT
 #ifndef        _THR_SUNOS5
@@ -161,11 +161,11 @@
                sigaddset(&act.sa_mask, SIGPIPE);

                sigaction(_SIG_THREAD_CANCEL, &act, NULL);
-#endif
+#endif
                _main = this;
        }
        _self.setKey(this);
-}
+}

 Thread::Thread(Semaphore *start, int pri, size_t stack)
 {
@@ -176,7 +176,7 @@

        pthread_attr_init(&_attr);
        pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_JOINABLE);
-       pthread_attr_setinheritsched(&_attr, PTHREAD_INHERIT_SCHED);
+

 #ifdef PTHREAD_STACK_MIN
        if(pthread_attr_setstacksize(&_attr, stack <= PTHREAD_STACK_MIN ?
PTHREAD_STACK_MIN : stack))
@@ -192,7 +192,7 @@
 #endif

 #ifndef        __FreeBSD__
-#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
        if(pri)
        {
                struct sched_param sched;
@@ -220,8 +220,9 @@
                        pri = sched_get_priority_min(policy);

                sched.sched_priority = pri;
+               pthread_attr_setschedpolicy(&_attr, policy);
                pthread_attr_setschedparam(&_attr, &sched);
-       }
+       }
 #endif
 #endif

@@ -289,7 +290,7 @@
        {
                pthread_detach(_tid);
                if(_start)
-               {
+               {
                        _start->Post();
                        return 0;
                }
@@ -351,7 +352,7 @@
                        Thread::_timer->OnTimer();
                }
                else
-#endif
+#endif
                    if(th)
                        th->OnTimer();
                break;
@@ -386,7 +387,7 @@

        if(!setjmp(th->_env))
        {
-               th->Initial();
+               th->Initial();
                if(th->getCancel() == THREAD_CANCEL_INITIAL)
                        th->setCancel(THREAD_CANCEL_DEFAULT);

@@ -411,7 +412,7 @@

 #ifdef HAVE_SETITIMER
        struct itimerval itimer;
-
+
        memset(&itimer, 0, sizeof(itimer));
        itimer.it_value.tv_usec = (timer * 1000) % 1000000;
        itimer.it_value.tv_sec = timer / 1000;
@@ -419,7 +420,7 @@
        timer /= 1000;
 #endif

-#ifndef        _SIG_THREAD_ALARM
+#ifndef        _SIG_THREAD_ALARM
        _arm;
        _timer = this;
 #endif
@@ -432,7 +433,7 @@
 #else
        alarm(timer);
 #endif
-}
+}

 timeout_t Thread::getTimer(void)
 {
@@ -491,7 +492,7 @@
 #else
        sigwait(&mask, &signo);
 #endif
-}
+}

 void   Thread::setSuspend(thread_suspend_t mode)
 {
@@ -518,7 +519,7 @@

        sigemptyset(&mask);
        sigaddset(&mask, _SIG_THREAD_CANCEL);
-
+
        switch(mode)
        {
        case THREAD_CANCEL_IMMEDIATE:
@@ -545,7 +546,7 @@
                pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
        else
                pthread_sigmask(SIG_BLOCK, &sigs, NULL);
-}
+}

 void   Thread::setCancel(thread_cancel_t mode)
 {
@@ -580,7 +581,7 @@
        sigemptyset(&cancel);
        sigaddset(&cancel, _SIG_THREAD_CANCEL);

-       if(_cancel != THREAD_CANCEL_DISABLED &&
+       if(_cancel != THREAD_CANCEL_DISABLED &&
           _cancel != THREAD_CANCEL_INITIAL)
                pthread_sigmask(SIG_UNBLOCK, &cancel, &old);
 #else
@@ -600,28 +601,28 @@
 {
 #ifdef  _SIG_THREAD_CANCEL
         sigset_t cancel, old;
-
+
         sigemptyset(&cancel);
         sigaddset(&cancel, _SIG_THREAD_CANCEL);
-
+
         if(_cancel != THREAD_CANCEL_DISABLED &&
            _cancel != THREAD_CANCEL_INITIAL)
                 pthread_sigmask(SIG_UNBLOCK, &cancel, &old);
 #else
         pthread_testcancel();
 #endif
-
+
 #ifdef  _SIG_THREAD_CANCEL
         if(_cancel != THREAD_CANCEL_DISABLED)
                 pthread_sigmask(SIG_SETMASK, &old, NULL);
 #endif
-}
+}


 void siginstall(int signo)
 {
        struct sigaction act;
-
+
        act.sa_handler = (signalexec_t)&sigHandler;
        sigemptyset(&act.sa_mask);




_______________________________________________
Bug-commoncpp mailing list
address@hidden
http://mail.gnu.org/mailman/listinfo/bug-commoncpp



// Copyright (C) 1999-2001 Open Source Telecom Corporation.
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// 
// As a special exception to the GNU General Public License, permission is 
// granted for additional uses of the text contained in its release 
// of Common C++.
// 
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the 
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
// 
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.  

#include "config.h"
#include "macros.h"
#include "thread.h"
#include <stdlib.h>

typedef void    *(*exec_t)(void *);
typedef RETSIGTYPE (*signalexec_t)(int);

#ifdef  _SIG_THREAD_CANCEL

static  RETSIGTYPE      sigcancel(int)
{
        pthread_exit(NULL);
}

#endif

#ifndef _SIG_THREAD_STOPCONT
#ifndef _THR_SUNOS5

static  RETSIGTYPE      sigsuspend(int)
{
        sigset_t sigs;

        sigemptyset(&sigs);
        sigaddset(&sigs, SIGUSR3);
#ifdef  HAVE_SIGWAIT2
        sigwait(&sigs, NULL);
#else
        sigwait(&sigs);
#endif
}
#endif
#endif

static  sigset_t *blocked_signals(sigset_t *sig)
{
        sigemptyset(sig);
        sigaddset(sig, SIGINT);
        sigaddset(sig, SIGKILL);
        sigaddset(sig, SIGHUP);
        sigaddset(sig, SIGABRT);
        sigaddset(sig, SIGALRM);
        sigaddset(sig, SIGPIPE);
#ifndef _SIG_THREAD_STOPCONT
        sigaddset(sig, SIGUSR3);
#endif
        return sig;
}

class MainThread : public Thread
{
protected:
        void Run(void) {return;};
        void OnSignal(int signo) {exit(signo);};

public:
        MainThread() : Thread(true) {};
};

static  ThreadKey _self;
static  MainThread _mainthread;

Thread  *Thread::_main = NULL;

#ifndef _SIG_THREAD_ALARM
Thread  *Thread::_timer = NULL;
Mutex   Thread::_arm;
#endif

Thread::Thread(bool flag)
{
        _tid = pthread_self();
        _throw = THROW_OBJECT;
        _parent = NULL;
        _msgpos = 0;
        struct sigaction act;

        if(flag == true)
        {
                siginstall(SIGHUP);
                siginstall(SIGALRM);
                siginstall(SIGPIPE);
                siginstall(SIGABRT);

                act.sa_handler = (signalexec_t)&sigHandler;
                sigemptyset(&act.sa_mask);
#ifdef  SA_RESTART
                act.sa_flags = SA_RESTART;
#else
                act.sa_flags = 0;
#endif
#ifdef  SA_INTERRUPT
                act.sa_flags |= SA_INTERRUPT;
#endif
#ifdef  SIGPOLL
                sigaction(SIGPOLL, &act, NULL);
#else
                sigaction(SIGIO, &act, NULL);
#endif          

#ifndef _SIG_THREAD_STOPCONT
#ifndef _THR_SUNOS5
                act.sa_handler = sigsuspend;
                sigemptyset(&act.sa_mask);
#ifdef  SA_RESTART
                act.sa_flags = SA_RESTART;
#else
                act.sa_flags = 0;
#endif
                sigaction(SIGUSR3, &act, NULL);
#endif
#endif

#ifdef  _SIG_THREAD_CANCEL
                act.sa_flags = 0;
                act.sa_handler = sigcancel;
                sigemptyset(&act.sa_mask);
                sigaddset(&act.sa_mask, SIGHUP);
                sigaddset(&act.sa_mask, SIGALRM);
                sigaddset(&act.sa_mask, SIGPIPE);

                sigaction(_SIG_THREAD_CANCEL, &act, NULL);
#endif          
                _main = this;
        }
        _self.setKey(this);
}       

Thread::Thread(Semaphore *start, int pri, size_t stack)
{
        int     rc;

        _msgpos = 0;
        _tid = 0;

        pthread_attr_init(&_attr);
        pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_JOINABLE);

#ifdef  PTHREAD_STACK_MIN
        if(pthread_attr_setstacksize(&_attr, stack <= PTHREAD_STACK_MIN ? 
PTHREAD_STACK_MIN : stack))
        {
                switch(getException())
                {
                case THROW_OBJECT:
                        throw(this);
                default:
                        return;
                }
        }
#endif

#ifndef __FreeBSD__
#ifdef  _POSIX_THREAD_PRIORITY_SCHEDULING
#define __HAS_PRIORITY_SCHEDULING__     
        if(pri)
        {
                struct sched_param sched;
                int policy;

                policy = sched_getscheduler(0);
                if(policy < 0)
                {
                        switch(getException())
                        {
                        case THROW_OBJECT:
                                throw(this);
                        default:
                                return;
                        }
                }

                sched_getparam(0, &sched);

                pri = sched.sched_priority - pri;
                if(pri  > sched_get_priority_max(policy))
                        pri = sched_get_priority_max(policy);

                if(pri < sched_get_priority_min(policy))
                        pri = sched_get_priority_min(policy);

                sched.sched_priority = pri;
                pthread_attr_setschedpolicy(&_attr, policy);
                pthread_attr_setschedparam(&_attr, &sched);
        }       
#endif
#endif

#ifdef  __HAS_PRIORITY_SCHEDULING__
        if(!pri)
                pthread_attr_setinheritsched(&_attr, PTHREAD_INHERIT_SCHED);    
         
#else
        pthread_attr_setinheritsched(&_attr, PTHREAD_INHERIT_SCHED);            
 
#endif

        _parent = getThread();
        _throw = _parent->_throw;
        if(!_parent)
                _parent = this;

        _cancel = THREAD_CANCEL_INITIAL;
        _start = start;

        if(_start)
        {
                rc = pthread_create(&_tid, &_attr, exec_t(&execHandler), this);
                if(rc && getException() == THROW_OBJECT)
                        throw(this);
        }
};

Thread::Thread(const Thread &th)
{
        sigset_t mask, newmask;
        int rc;

        _parent = th._parent;
        _cancel = THREAD_CANCEL_INITIAL;
        pthread_sigmask(SIG_BLOCK, blocked_signals(&newmask), &mask);
        rc = pthread_create(&_tid, &_attr, exec_t(&execHandler), this);
        pthread_sigmask(SIG_SETMASK, &mask, NULL);
        if(rc && getException() == THROW_OBJECT)
                throw(this);
}

bool Thread::isThread(void)
{
        return (_tid == pthread_self()) ? true : false;
}

bool Thread::isRunning(void)
{
        return (_tid != 0) ? true : false;
}

int Thread::Start(Semaphore *start)
{
        if(_tid)
        {
                if(_start)
                {
                        _start->Post();
                        return 0;
                }
                else
                        return -1;
        }

        _start = start;
        return pthread_create(&_tid, &_attr, exec_t(&execHandler), this);
}

int Thread::Detach(Semaphore *start)
{
        int rtn;
        if(_tid)
        {
                pthread_detach(_tid);
                if(_start)
                {       
                        _start->Post();
                        return 0;
                }
                else
                        return -1;
        }

        _start = start;
        rtn = pthread_create(&_tid, &_attr, exec_t(&execHandler), this);
        if(!rtn && _tid)
                pthread_detach(_tid);
}

void Thread::Terminate(void)
{
        if(!_tid)
                return;

        if(pthread_self() != _tid)
        {
                // assure thread has ran before we try to cancel...
                if(_start)
                        _start->Post();

                pthread_cancel(_tid);
                if(!pthread_join(_tid, NULL) && _parent)
                        _parent->Notify(this);
                _tid = 0;
        }
        pthread_attr_destroy(&_attr);
}

extern "C"
{

  void sigHandler(int signo)
  {
        Thread  *th = getThread();

        switch(signo)
        {
        case SIGHUP:
                if(th)
                        th->OnHangup();
                break;
        case SIGABRT:
                if(th)
                        th->OnException();
                break;
        case SIGPIPE:
                if(th)
                        th->OnDisconnect();
                break;
        case SIGALRM:
#ifndef _SIG_THREAD_ALARM
                if(Thread::_timer)
                {
                        Thread::_timer->_alarm = 0;
                        Thread::_timer->OnTimer();
                }
                else
#endif 
                    if(th)
                        th->OnTimer();
                break;
#ifdef  SIGPOLL
        case SIGPOLL:
#else
        case SIGIO:
#endif
                if(th)
                        th->OnPolling();
                break;
        default:
                if(th)
                        th->OnSignal(signo);
        }
  }

  void  execHandler(Thread *th)
  {
        sigset_t mask;

        pthread_sigmask(SIG_BLOCK, blocked_signals(&mask), NULL);
        _self.setKey(th);
        th->_tid = pthread_self();
        th->setCancel(THREAD_CANCEL_INITIAL);
        th->Yield();
        if(th->_start)
        {
                th->_start->Wait();
                th->_start = NULL;
        }

        if(!setjmp(th->_env))
        {
                th->Initial();  
                if(th->getCancel() == THREAD_CANCEL_INITIAL)
                        th->setCancel(THREAD_CANCEL_DEFAULT);

                th->Run();
        }

#ifndef _SIG_THREAD_ALARM
        if(th == Thread::_timer)
                --Thread::_arm;
#endif

        th->setCancel(THREAD_CANCEL_DISABLED);
        if(!pthread_detach(th->_tid) && th->_parent)
                th->_parent->Notify(th);
        th->Final();
        pthread_exit(NULL);
  }
}
void    Thread::setTimer(timeout_t timer)
{
        sigset_t sigs;

#ifdef  HAVE_SETITIMER
        struct itimerval itimer;
        
        memset(&itimer, 0, sizeof(itimer));
        itimer.it_value.tv_usec = (timer * 1000) % 1000000;
        itimer.it_value.tv_sec = timer / 1000;
#else
        timer /= 1000;
#endif

#ifndef _SIG_THREAD_ALARM       
        _arm;
        _timer = this;
#endif
        time(&_alarm);
        sigemptyset(&sigs);
        sigaddset(&sigs, SIGALRM);
        pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
#ifdef  HAVE_SETITIMER
        setitimer(ITIMER_REAL, &itimer, NULL);
#else
        alarm(timer);
#endif
}       

timeout_t Thread::getTimer(void)
{
#ifdef  HAVE_SETITIMER
        struct itimerval itimer;
#endif

        if(!_alarm)
                return 0;

#ifdef  HAVE_SETITIMER
        getitimer(ITIMER_REAL, &itimer);
        return (timeout_t)(itimer.it_value.tv_sec * 1000 +
                itimer.it_value.tv_usec / 1000);
#else
        time_t now;
        time(&now);
        return (timeout_t)(((now - _alarm) * 1000) + 500);
#endif
}

void Thread::endTimer(void)
{
#ifdef  HAVE_SETITIMER
        static const struct itimerval itimer = {{0, 0},{0,0}};
#endif

        sigset_t sigs;
#ifndef _SIG_THREAD_ALARM
        if(_timer != this)
                return;
#endif

#ifdef  HAVE_SETITIMER
        setitimer(ITIMER_REAL, (struct itimerval *)&itimer, NULL);
#else
        alarm(0);
#endif
        sigemptyset(&sigs);
        sigaddset(&sigs, SIGALRM);
        pthread_sigmask(SIG_BLOCK, &sigs, NULL);
#ifndef _SIG_THREAD_ALARM
        --_arm;
        _timer = NULL;
#endif
}

void    Thread::WaitSignal(signo_t signo)
{
        sigset_t        mask;

        sigemptyset(&mask);
        sigaddset(&mask, signo);
#ifndef HAVE_SIGWAIT2
        signo = sigwait(&mask);
#else
        sigwait(&mask, &signo);
#endif
}       

void    Thread::setSuspend(thread_suspend_t mode)
{
        sigset_t mask;

        sigemptyset(&mask);
        sigaddset(&mask, _SIG_THREAD_SUSPEND);

        switch(mode)
        {
        case THREAD_SUSPEND_ENABLE:
                pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
                return;
        case THREAD_SUSPEND_DISABLE:
                pthread_sigmask(SIG_BLOCK, &mask, NULL);
        }
}

#ifdef  _SIG_THREAD_CANCEL

void    Thread::setCancel(thread_cancel_t mode)
{
        sigset_t        mask;

        sigemptyset(&mask);
        sigaddset(&mask, _SIG_THREAD_CANCEL);
        
        switch(mode)
        {
        case THREAD_CANCEL_IMMEDIATE:
                pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
                break;
        case THREAD_CANCEL_INITIAL:
        case THREAD_CANCEL_DISABLED:
        case THREAD_CANCEL_DEFERRED:
                pthread_sigmask(SIG_BLOCK, &mask, NULL);
                break;
        }
        _cancel = mode;
}
#else

void    Thread::setSignal(int signo, bool mode)
{
        sigset_t sigs;

        sigemptyset(&sigs);
        sigaddset(&sigs, signo);

        if(mode)
                pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
        else
                pthread_sigmask(SIG_BLOCK, &sigs, NULL);
}       

void    Thread::setCancel(thread_cancel_t mode)
{
        switch(mode)
        {
        case THREAD_CANCEL_IMMEDIATE:
                pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
                pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
                break;
        case THREAD_CANCEL_DEFERRED:
                pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
                pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
                break;
        case THREAD_CANCEL_INITIAL:
        case THREAD_CANCEL_DISABLED:
                pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
                break;
        default:
                mode = THREAD_CANCEL_INVALID;
        }
        if(mode != THREAD_CANCEL_INVALID)
                _cancel = mode;
}

#endif

void    Thread::Yield(void)
{
#ifdef  _SIG_THREAD_CANCEL
        sigset_t cancel, old;

        sigemptyset(&cancel);
        sigaddset(&cancel, _SIG_THREAD_CANCEL);

        if(_cancel != THREAD_CANCEL_DISABLED && 
           _cancel != THREAD_CANCEL_INITIAL)
                pthread_sigmask(SIG_UNBLOCK, &cancel, &old);
#else
        pthread_testcancel();
#endif
#ifdef  HAVE_PTHREAD_YIELD
        pthread_yield();
#endif

#ifdef  _SIG_THREAD_CANCEL
        if(_cancel != THREAD_CANCEL_DISABLED)
                pthread_sigmask(SIG_SETMASK, &old, NULL);
#endif
}

void Thread::testCancel(void)
{
#ifdef  _SIG_THREAD_CANCEL
        sigset_t cancel, old;
 
        sigemptyset(&cancel);
        sigaddset(&cancel, _SIG_THREAD_CANCEL);
 
        if(_cancel != THREAD_CANCEL_DISABLED &&
           _cancel != THREAD_CANCEL_INITIAL)
                pthread_sigmask(SIG_UNBLOCK, &cancel, &old);
#else
        pthread_testcancel();
#endif
 
#ifdef  _SIG_THREAD_CANCEL
        if(_cancel != THREAD_CANCEL_DISABLED)
                pthread_sigmask(SIG_SETMASK, &old, NULL);
#endif
} 


void siginstall(int signo)
{
        struct sigaction act;
        
        act.sa_handler = (signalexec_t)&sigHandler;
        sigemptyset(&act.sa_mask);

#ifdef  SA_INTERRUPT
        act.sa_flags = SA_INTERRUPT;
#else
        act.sa_flags = 0;
#endif
        sigaction(signo, &act, NULL);
}

Thread *getThread(void)
{
        Thread *thread;

        if(!Thread::_main)
                return &_mainthread;

        thread = (Thread *)_self.getKey();

        if(!thread)
        {
                thread = (Thread *)new MainThread;
                _self.setKey(thread);
        }
        return thread;
}

#ifdef  __CCXX_USE_POLL

Poller::Poller()
{
        nufds = 0;
        ufds = NULL;
};


Poller::~Poller()
{
        if(ufds)
                delete[] ufds;
}

pollfd *Poller::getList(int cnt)
{
        if(nufds < cnt)
        {
                if(ufds)
                        delete[] ufds;
                ufds = new pollfd[cnt];
                nufds = cnt;
        }
        return ufds;
}

#endif

/** EMACS **
 * Local variables:
 * mode: c++
 * c-basic-offset: 8
 * End:
 */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]