[Top][All Lists]
[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:
*/