00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <linux/kernel.h>
00021
#include <linux/module.h>
00022
00023
#include <rtai_schedcore.h>
00024
#include <rtai_signal.h>
00025
00026
MODULE_LICENSE(
"GPL");
00027 #define MODULE_NAME "RTAI_SIGNALS"
00028
00029 #define RT_SCHED_SIGSUSP (1 << 15)
00030
00031 #define RT_SIGNALS ((struct rt_signal_t *)task->rt_signals)
00032 struct rt_signal_t {
unsigned long flags;
RT_TASK *
sigtask; };
00033
00034 static int rt_request_signal_(
RT_TASK *sigtask,
RT_TASK *task,
long signal)
00035 {
00036
int retval;
00037
if (signal >= 0 && sigtask &&
task) {
00038
if (!
task->rt_signals) {
00039
task->rt_signals =
rt_malloc(MAXSIGNALS*
sizeof(
struct rt_signal_t));
00040
task->pstate = 0;
00041 }
00042
RT_SIGNALS[signal].flags = (1 << SIGNAL_ENBIT);
00043
RT_SIGNALS[signal].sigtask = sigtask;
00044 retval = 0;
00045 }
else {
00046 retval = -EINVAL;
00047 }
00048
task->retval = retval;
00049
rt_task_resume(
task);
00050
return retval;
00051 }
00052
EXPORT_SYMBOL(rt_request_signal_);
00053
00054 static inline void rt_exec_signal(
RT_TASK *sigtask,
RT_TASK *task)
00055 {
00056
unsigned long flags;
00057
00058
flags = rt_global_save_flags_and_cli();
00059
if (!(--sigtask->suspdepth)) {
00060
if (
task) {
00061 sigtask->priority =
task->priority;
00062
if (!
task->pstate++) {
00063 rem_ready_task(
task);
00064
task->state |=
RT_SCHED_SIGSUSP;
00065 }
00066 }
00067 sigtask->state &= ~
RT_SCHED_SIGSUSP;
00068 sigtask->retval = (
long)
task;
00069 enq_ready_task(sigtask);
00070 RT_SCHEDULE(sigtask, rtai_cpuid());
00071 }
00072 rt_global_restore_flags(
flags);
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 int rt_release_signal(
long signal,
RT_TASK *task)
00091 {
00092
if (
task == NULL) {
00093
task = RT_CURRENT;
00094 }
00095
if (signal >= 0 &&
RT_SIGNALS &&
RT_SIGNALS[signal].sigtask) {
00096
RT_SIGNALS[signal].sigtask->priority =
task->priority;
00097
rt_exec_signal(
RT_SIGNALS[signal].sigtask, 0);
00098
return 0;
00099 }
00100
return -EINVAL;
00101 }
00102
EXPORT_SYMBOL(rt_release_signal);
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 void rt_trigger_signal(
long signal,
RT_TASK *task)
00119 {
00120
if (
task == NULL) {
00121
task = RT_CURRENT;
00122 }
00123
if (signal >= 0 &&
RT_SIGNALS &&
RT_SIGNALS[signal].sigtask) {
00124
do {
00125
if (test_and_clear_bit(SIGNAL_ENBIT, &
RT_SIGNALS[signal].
flags)) {
00126
rt_exec_signal(
RT_SIGNALS[signal].sigtask,
task);
00127 test_and_set_bit(SIGNAL_ENBIT, &
RT_SIGNALS[signal].
flags);
00128 }
else {
00129 test_and_set_bit(SIGNAL_PNDBIT, &
RT_SIGNALS[signal].
flags);
00130
break;
00131 }
00132 }
while (test_and_clear_bit(SIGNAL_PNDBIT, &
RT_SIGNALS[signal].
flags));
00133 }
00134 }
00135
EXPORT_SYMBOL(rt_trigger_signal);
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 void rt_enable_signal(
long signal,
RT_TASK *task)
00150 {
00151
if (
task == NULL) {
00152
task = RT_CURRENT;
00153 }
00154
if (signal >= 0 &&
RT_SIGNALS) {
00155 set_bit(SIGNAL_ENBIT, &
RT_SIGNALS[signal].
flags);
00156 }
00157 }
00158
EXPORT_SYMBOL(rt_enable_signal);
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 void rt_disable_signal(
long signal,
RT_TASK *task)
00173 {
00174
if (
task == NULL) {
00175
task = RT_CURRENT;
00176 }
00177
if (signal >= 0 &&
RT_SIGNALS) {
00178 clear_bit(SIGNAL_ENBIT, &
RT_SIGNALS[signal].
flags);
00179 }
00180 }
00181
EXPORT_SYMBOL(rt_disable_signal);
00182
00183 static int rt_signal_helper(
RT_TASK *task)
00184 {
00185
if (
task) {
00186
rt_task_suspend(
task);
00187
return task->retval;
00188 }
00189
return (RT_CURRENT)->runnable_on_cpus;
00190 }
00191
00192 int rt_wait_signal(
RT_TASK *sigtask,
RT_TASK *task)
00193 {
00194
unsigned long flags;
00195
00196
flags = rt_global_save_flags_and_cli();
00197
if (!sigtask->suspdepth++) {
00198 sigtask->state |=
RT_SCHED_SIGSUSP;
00199 rem_ready_current(sigtask);
00200
if (
task->pstate > 0 && !(--
task->pstate) && (
task->state &= ~
RT_SCHED_SIGSUSP) ==
RT_SCHED_READY) {
00201 enq_ready_task(
task);
00202 }
00203
rt_schedule();
00204 }
00205 rt_global_restore_flags(
flags);
00206
return sigtask->retval;
00207 }
00208
EXPORT_SYMBOL(rt_wait_signal);
00209
00210 static void signal_suprt_fun(
struct sigsuprt_t *funarg)
00211 {
00212
struct sigsuprt_t arg = *funarg;
00213
00214 arg.
sigtask = RT_CURRENT;
00215
if (!
rt_request_signal_(arg.
sigtask, arg.
task, arg.
signal)) {
00216
while (
rt_wait_signal(arg.
sigtask, arg.
task)) {
00217 arg.
sighdl(arg.
signal, arg.
task);
00218 }
00219 }
else {
00220
rt_task_resume(arg.
task);
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 int rt_request_signal(
long signal,
void (*sighdl)(
long,
RT_TASK *))
00244 {
00245
if (signal >= 0 && sighdl) {
00246
RT_TASK *
task = RT_CURRENT;
00247
struct sigsuprt_t arg = { NULL,
task, signal, sighdl,
task->runnable_on_cpus };
00248
if ((
task =
rt_malloc(
sizeof(
RT_TASK)))) {
00249
rt_task_init_cpuid(
task, (
void *)
signal_suprt_fun, (
long)&arg,
SIGNAL_TASK_STACK_SIZE, arg.task->priority, 0, 0, arg.cpuid);
00250
rt_task_resume(
task);
00251
rt_task_suspend(arg.task);
00252
return arg.task->retval;
00253 }
00254 }
00255
return -EINVAL;
00256 }
00257
EXPORT_SYMBOL(rt_request_signal);
00258
00259 static struct rt_fun_entry
rtai_signals_fun[] = {
00260 [
SIGNAL_HELPER] = { 1,
rt_signal_helper },
00261 [
SIGNAL_WAITSIG] = { 1,
rt_wait_signal },
00262 [
SIGNAL_REQUEST] = { 1,
rt_request_signal_ },
00263 [
SIGNAL_RELEASE] = { 1,
rt_release_signal },
00264 [
SIGNAL_ENABLE] = { 1,
rt_enable_signal },
00265 [
SIGNAL_DISABLE] = { 1,
rt_disable_signal },
00266 [
SIGNAL_TRIGGER] = { 1,
rt_trigger_signal }
00267 };
00268
00269 int init_module(
void)
00270 {
00271
if (
set_rt_fun_ext_index(
rtai_signals_fun,
RTAI_SIGNALS_IDX)) {
00272
printk(
"Wrong or already used LXRT extension: %d.\n",
RTAI_SIGNALS_IDX);
00273
return -EACCES;
00274 }
00275
printk(
"%s: loaded.\n",
MODULE_NAME);
00276
return 0;
00277 }
00278
00279 void cleanup_module(
void)
00280 {
00281
reset_rt_fun_ext_index(
rtai_signals_fun,
RTAI_SIGNALS_IDX);
00282
printk(
"%s: unloaded.\n",
MODULE_NAME);
00283 }