[haiku-commits] r41508 - in haiku/branches/developer/bonefish/signals: headers/private/kernel src/system/kernel
- From: ingo_weinhold@xxxxxx
- To: haiku-commits@xxxxxxxxxxxxx
- Date: Sun, 15 May 2011 03:00:48 +0200 (CEST)
Author: bonefish
Date: 2011-05-15 03:00:48 +0200 (Sun, 15 May 2011)
New Revision: 41508
Changeset: https://dev.haiku-os.org/changeset/41508
Modified:
haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
Log:
Work towards support for queued signals:
* Added new class Signal, instances of which represent queued signals. Currently
the only data member is the signal number. Later it will contain all data
associate with the signal.
* Rewrote most of PendingSignals:
- It does now store queued and unqueued signals. The queued ones are,
obviously, stored in a queue. The unqueued ones in a mask.
- Added methods to get the signals' highest priority and to dequeue the signal
with the highest priority. Not used yet.
Modified:
haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
===================================================================
--- haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
2011-05-15 00:37:59 UTC (rev 41507)
+++ haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
2011-05-15 01:00:48 UTC (rev 41508)
@@ -5,11 +5,16 @@
#ifndef _KERNEL_SIGNAL_H
#define _KERNEL_SIGNAL_H
+#include <signal.h>
#include <KernelExport.h>
-#include <signal.h>
+#include <Referenceable.h>
+#include <heap.h>
+#include <util/DoublyLinkedList.h>
+
+
namespace BKernel {
struct ProcessGroup;
struct Team;
@@ -32,29 +37,69 @@
namespace BKernel {
+struct Signal : BReferenceable, DeferredDeletable,
+ DoublyLinkedListLinkImpl<Signal> {
+public:
+ Signal(int32
number) : fNumber(number) {}
+
+ void SetTo(int32 number)
+ {
fNumber = number; }
+
+ int32 Number() const { return
fNumber; }
+ int32 Priority() const;
+
+protected:
+ virtual void LastReferenceReleased();
+
+private:
+ int fNumber;
+};
+
+
struct PendingSignals {
-
PendingSignals() : fAllMask(0) {}
-
~PendingSignals() {}
+
PendingSignals();
+
~PendingSignals();
- sigset_t AllSignals() const
{ return fAllMask; }
+ sigset_t AllSignals() const
+ {
return fQueuedSignalsMask
+
| fUnqueuedSignalsMask; }
- void Clear()
- {
fAllMask = 0; }
- void AddSignal(int signal)
- {
fAllMask |= SIGNAL_TO_MASK(signal); }
- void RemoveSignal(int signal)
+ int32
HighestSignalPriority(sigset_t blocked) const;
+
+ void Clear();
+ void AddSignal(int32 signal)
+ {
fUnqueuedSignalsMask
+
|= SIGNAL_TO_MASK(signal); }
+ void AddSignal(Signal*
signal);
+ void RemoveSignal(int32
signal)
{
RemoveSignals(SIGNAL_TO_MASK(signal)); }
- void RemoveSignals(sigset_t
mask)
- {
fAllMask &= ~mask; }
+ void RemoveSignals(sigset_t
mask);
+ Signal* DequeueSignal(sigset_t
blocked, Signal& buffer);
+
private:
- sigset_t fAllMask;
+ typedef DoublyLinkedList<Signal> SignalList;
+
+private:
+ int32
_GetHighestPrioritySignal(sigset_t blocked,
+
Signal*& _queuedSignal,
+ int32&
_unqueuedSignal) const;
+ void
_UpdateQueuedSignalMask();
+
+private:
+ sigset_t fQueuedSignalsMask;
+ sigset_t fUnqueuedSignalsMask;
+ SignalList fQueuedSignals;
};
} // namespace BKernel
+using BKernel::PendingSignals;
+using BKernel::Signal;
+
+
#ifdef __cplusplus
extern "C" {
#endif
Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
2011-05-15 00:37:59 UTC (rev 41507)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
2011-05-15 01:00:48 UTC (rev 41508)
@@ -56,17 +56,268 @@
| SIGNAL_TO_MASK(SIGSEGV))
-const char * const sigstr[NSIG] = {
- "NONE", "HUP", "INT", "QUIT", "ILL", "CHLD", "ABRT", "PIPE",
- "FPE", "KILL", "STOP", "SEGV", "CONT", "TSTP", "ALRM", "TERM",
- "TTIN", "TTOU", "USR1", "USR2", "WINCH", "KILLTHR", "TRAP",
- "POLL", "PROF", "SYS", "URG", "VTALRM", "XCPU", "XFSZ"
+static const struct {
+ const char* name;
+ int32 priority;
+} kSignalInfos[] = {
+ {"NONE", -1},
+ {"HUP", 0},
+ {"INT", 0},
+ {"QUIT", 0},
+ {"ILL", 0},
+ {"CHLD", 0},
+ {"ABRT", 0},
+ {"PIPE", 0},
+ {"FPE", 0},
+ {"KILL", 100},
+ {"STOP", 0},
+ {"SEGV", 0},
+ {"CONT", 0},
+ {"TSTP", 0},
+ {"ALRM", 0},
+ {"TERM", 0},
+ {"TTIN", 0},
+ {"TTOU", 0},
+ {"USR1", 0},
+ {"USR2", 0},
+ {"WINCH", 0},
+ {"KILLTHR", 100},
+ {"TRAP", 0},
+ {"POLL", 0},
+ {"PROF", 0},
+ {"SYS", 0},
+ {"URG", 0},
+ {"VTALRM", 0},
+ {"XCPU", 0},
+ {"XFSZ", 0}
};
static status_t deliver_signal(Thread *thread, uint signal, uint32 flags);
+// #pragma mark - Signal
+
+
+int32
+Signal::Priority() const
+{
+ return kSignalInfos[fNumber].priority;
+}
+
+
+void
+Signal::LastReferenceReleased()
+{
+ if (are_interrupts_enabled())
+ delete this;
+ else
+ deferred_delete(this);
+}
+
+
+// #pragma mark - PendingSignals
+
+
+PendingSignals::PendingSignals()
+ :
+ fQueuedSignalsMask(0),
+ fUnqueuedSignalsMask(0)
+{
+}
+
+
+PendingSignals::~PendingSignals()
+{
+ Clear();
+}
+
+
+/*! Of the signals not it \a blocked returns the priority of that with the
+ highest priority.
+ \param blocked The mask with the blocked signals.
+ \return The priority of the highest priority non-blocked signal, or, if
all
+ signals are blocked, \c -1.
+*/
+int32
+PendingSignals::HighestSignalPriority(sigset_t blocked) const
+{
+ Signal* queuedSignal;
+ int32 unqueuedSignal;
+ return _GetHighestPrioritySignal(blocked, queuedSignal, unqueuedSignal);
+}
+
+
+void
+PendingSignals::Clear()
+{
+ // release references of all queued signals
+ while (Signal* signal = fQueuedSignals.RemoveHead())
+ signal->ReleaseReference();
+
+ fQueuedSignalsMask = 0;
+ fUnqueuedSignalsMask = 0;
+}
+
+
+/*! Adds a signal.
+ Takes over the reference to the signal from the caller.
+*/
+void
+PendingSignals::AddSignal(Signal* signal)
+{
+ // queue according to priority
+ int32 priority = signal->Priority();
+ Signal* otherSignal = NULL;
+ for (SignalList::Iterator it = fQueuedSignals.GetIterator();
+ (otherSignal = it.Next()) != NULL;) {
+ if (priority > otherSignal->Priority())
+ break;
+ }
+
+ fQueuedSignals.InsertBefore(otherSignal, signal);
+
+ fQueuedSignalsMask |= SIGNAL_TO_MASK(signal->Number());
+}
+
+
+void
+PendingSignals::RemoveSignals(sigset_t mask)
+{
+ // remove from queued signals
+ if ((fQueuedSignalsMask & mask) != 0) {
+ for (SignalList::Iterator it = fQueuedSignals.GetIterator();
+ Signal* signal = it.Next();) {
+ // remove signal, if in mask
+ if ((SIGNAL_TO_MASK(signal->Number()) & mask) != 0) {
+ it.Remove();
+ signal->ReleaseReference();
+ }
+ }
+
+ fQueuedSignalsMask &= ~mask;
+ }
+
+ // remove from unqueued signals
+ fUnqueuedSignalsMask &= ~mask;
+}
+
+
+/*! Removes and returns a signal not in \a blocked that has the highest
+ priority.
+ The caller gets a reference to the returned signal, if any.
+ \param blocked The mask of blocked signals.
+ \param buffer If the signal is not queued this buffer is returned. In
this
+ case the method acquires a reference to \a buffer, so that the
caller
+ gets a reference also in this case.
+ \return The removed signal or \c NULL, if all signals are blocked.
+*/
+Signal*
+PendingSignals::DequeueSignal(sigset_t blocked, Signal& buffer)
+{
+ // find the signal with the highest priority
+ Signal* queuedSignal;
+ int32 unqueuedSignal;
+ if (_GetHighestPrioritySignal(blocked, queuedSignal, unqueuedSignal) <
0)
+ return NULL;
+
+ // if it is a queued signal, dequeue it
+ if (queuedSignal != NULL) {
+ fQueuedSignals.Remove(queuedSignal);
+ _UpdateQueuedSignalMask();
+ return queuedSignal;
+ }
+
+ // it is unqueued -- remove from mask
+ fUnqueuedSignalsMask &= ~SIGNAL_TO_MASK(unqueuedSignal);
+
+ // init buffer
+ buffer.SetTo(unqueuedSignal);
+ buffer.AcquireReference();
+ return &buffer;
+}
+
+
+/*! Of the signals not it \a blocked returns the priority of that with the
+ highest priority.
+ \param blocked The mask with the blocked signals.
+ \param _queuedSignal If the found signal is a queued signal, the
variable
+ will be set to that signal, otherwise to \c NULL.
+ \param _unqueuedSignal If the found signal is an unqueued signal, the
+ variable is set to that signal's number, otherwise to \c -1.
+ \return The priority of the highest priority non-blocked signal, or, if
all
+ signals are blocked, \c -1.
+*/
+int32
+PendingSignals::_GetHighestPrioritySignal(sigset_t blocked,
+ Signal*& _queuedSignal, int32& _unqueuedSignal) const
+{
+ sigset_t nonBlocked = ~blocked;
+
+ // check queued signals
+ Signal* queuedSignal = NULL;
+ int32 queuedPriority = -1;
+
+ if ((fQueuedSignalsMask & nonBlocked) != 0) {
+ for (SignalList::ConstIterator it =
fQueuedSignals.GetIterator();
+ Signal* signal = it.Next();) {
+ if ((SIGNAL_TO_MASK(signal->Number()) & nonBlocked) !=
0) {
+ queuedPriority = signal->Priority();
+ queuedSignal = signal;
+ break;
+ }
+ }
+ }
+
+ // check unqueued signals
+ int32 unqueuedSignal = -1;
+ int32 unqueuedPriority = -1;
+
+ sigset_t unqueuedSignals = fUnqueuedSignalsMask & nonBlocked;
+ if (unqueuedSignals != 0) {
+ int32 signal = 1;
+ while (unqueuedSignals != 0) {
+ sigset_t mask = SIGNAL_TO_MASK(signal);
+ if ((unqueuedSignals & mask) != 0) {
+ int32 priority = kSignalInfos[signal].priority;
+ if (priority > unqueuedPriority) {
+ unqueuedSignal = signal;
+ unqueuedPriority = priority;
+ }
+ unqueuedSignals &= ~mask;
+ }
+
+ signal++;
+ }
+ }
+
+ // Return found queued or unqueued signal, whichever has the higher
+ // priority.
+ if (queuedPriority >= unqueuedPriority) {
+ _queuedSignal = queuedSignal;
+ _unqueuedSignal = -1;
+ return queuedPriority;
+ }
+
+ _queuedSignal = NULL;
+ _unqueuedSignal = unqueuedSignal;
+ return queuedPriority;
+}
+
+
+void
+PendingSignals::_UpdateQueuedSignalMask()
+{
+ sigset_t mask = 0;
+ for (SignalList::Iterator it = fQueuedSignals.GetIterator();
+ Signal* signal = it.Next();) {
+ mask |= SIGNAL_TO_MASK(signal->Number());
+ }
+
+ fQueuedSignalsMask = mask;
+}
+
+
// #pragma mark - signal tracing
@@ -131,7 +382,8 @@
{
out.Print("signal send: target: %ld, signal: %lu (%s), "
"flags: 0x%lx", fTarget, fSignal,
- (fSignal < NSIG ? sigstr[fSignal] : "invalid"),
fFlags);
+ fSignal < NSIG ? kSignalInfos[fSignal].name :
"invalid",
+ fFlags);
}
private:
@@ -157,7 +409,7 @@
out.Print("signal action: thread: %ld, signal: %lu
(%s), "
"action: {handler: %p, flags: 0x%x, mask:
0x%lx}",
fThread, fSignal,
- (fSignal < NSIG ? sigstr[fSignal] : "invalid"),
+ fSignal < NSIG ? kSignalInfos[fSignal].name :
"invalid",
fAction.sa_handler, fAction.sa_flags,
fAction.sa_mask);
}
@@ -398,7 +650,8 @@
debugSignal = !(~atomic_get(&thread->team->debug_info.flags)
& (B_TEAM_DEBUG_SIGNALS |
B_TEAM_DEBUG_DEBUGGER_INSTALLED));
- TRACE(("Thread 0x%lx received signal %s\n", thread->id,
sigstr[signal]));
+ TRACE(("Thread 0x%lx received signal %s\n", thread->id,
+ kSignalInfos[signal].name));
if (handler.sa_handler == SIG_IGN) {
// signal is to be ignored
Other related posts:
- » [haiku-commits] r41508 - in haiku/branches/developer/bonefish/signals: headers/private/kernel src/system/kernel - ingo_weinhold