“Tobias Miksch” <miksch@uni-mannheim.de> wrote in message
news:boqbjc$ndk$1@inn.qnx.com…
Steve Furr wrote:
Consider the staging:
A given timer will only queue one signal at any point in time, according
to the timer overrun behavior described.
If more than one timer is used, and one of the timer fires when the
signal is already queued, or the signal is pending for any other reason,
POSIX indicates that it is undefined whether the signal will queue,
except where realtime signals are supported (they are); in the latter
case, the signal
will only queue if the SA_SIGINFO flag is set for that signal
(sigaction).
I didn’t see any indication in your example, but you said the signal
handler would call pthread_cond_signal. If indeed you are losing
signals – bearing in mind the timer overrun condition, which is POSIX
conformant – you might simply encounter difficulty at the next stage:
pthread_cond_signal may lose signals if a corresponding mutex (the
one used in pthread_cond_wait) is not held when the signal is sent.
However, mutex primitives, are definitely not async-signal safe. For
that matter, neither is the condvar function, but it is generally
accepted
to be async-signal safe in most if not all implementations.
To be quite honest, the way I see it, the only truly conforming way
I can see to write an application is to assign a realtime signal to each
target thread, and have the thread perform a sigwait to wait for its
signal – and have no other threads performing sigwait whatsoever.
In any case, this avoids a signal-catching function altogether.
Your solution would then imply the use of “pthread_sleepon_signal”, which
is
not Posix afaik.
To the contrary, I was saying to use sigwait().
The key is to use signals exclusively as the wakeup mechanism on the
thread and forego other IPC. To do so, each thread requires its own
unique realtime signal.
Consider the following (untested, not necessarily syntactically correct)
example.
e.g. (hypothetical RMS scheduling – some content elided, including error
handling)
static void *
periodic_task(void *data)
{
task_data_t *task_data = (task_data_t *)data;
sigset_t sigset;
siginfo_t info;
sigemptyset(&sigset);
sigaddset(&sigset, task_data->signum); // My unique realtime signal
… /* things like setting up thread cancellation /
do {
if (sigwaitinfo(&set, &info) == 0) {
/ start of critical timing (data race) window /
over = timer_getoverrun(task_data->timerid);
/ end of critical timing window – if this timer fires again
during this interval, overrun data may be inconsistent */
if (over > 0) {
(task_data->miss_f)(task_data,over);
/ Probably should return something and terminate/continue
accordingly */
} else {
(*task_data->task)(task_data->call_data);
}
}
} while (1);
…
}
int
rms_create_periodic_task(struct timespec *release, struct timespec
*interval, struct timespec *cost, void *call_data,
void (*task)(void *), void (*deadline_miss)(void *, int))
{
task_data_t *task_data = rms_new_task_data();
pthread_attr_t attr;
struct sched_param sched;
…
task_data->call_data = call_data;
task_data->signum = rms_get_signal_number(); /* get an available
realtime signal in range (RTMIN,RTMAX) */
task_data->miss_f = deadline_miss;
task_data->task_f = task;
…
if (rms_schedule(interval, cost,&task_data->sched_priority) == 0) {
pthread_attr_setschedpolicy (&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &task_data->sched_priority);
pthread_create(&task_data->tid, &attr, periodic_task, task_data);
}
…
}
With respect to other scheduling mechanisms, it is important not to forget
sporadic scheduling, which is applicable to RMS or other static priority
scheduling
that requires limits on processing within a periodic interval, and is useful
for
either sporadic or aperiodic tasks.
Hmm. I was always wondering why there is no Posix definition/standard
for periodic tasks. These are vital for control systems i’m dealing with.
Is there an alternative scheduler for QNX performing RM or EDF scheduling?
Or the possibility to write a scheduler (sched_other) yourself?
-Tobias