File indexing completed on 2025-05-11 08:24:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <stdlib.h>
0037 #include <string.h>
0038
0039 #include <rtems.h>
0040 #include <rtems/chain.h>
0041 #include <rtems/score/assert.h>
0042
0043 #include <bsp/irq-generic.h>
0044
0045 #define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR BSP_INTERRUPT_VECTOR_COUNT
0046
0047 static rtems_interrupt_server_control bsp_interrupt_server_default;
0048
0049 static rtems_chain_control bsp_interrupt_server_chain =
0050 RTEMS_CHAIN_INITIALIZER_EMPTY(bsp_interrupt_server_chain);
0051
0052 static rtems_interrupt_server_control *bsp_interrupt_server_get_context(
0053 uint32_t server_index,
0054 rtems_status_code *sc
0055 )
0056 {
0057 rtems_chain_node *node;
0058
0059 bsp_interrupt_lock();
0060 node = rtems_chain_first(&bsp_interrupt_server_chain);
0061
0062 while (node != rtems_chain_tail(&bsp_interrupt_server_chain)) {
0063 rtems_interrupt_server_control *s;
0064
0065 s = RTEMS_CONTAINER_OF(node, rtems_interrupt_server_control, node);
0066 if (s->index == server_index) {
0067 bsp_interrupt_unlock();
0068 return s;
0069 }
0070
0071 node = rtems_chain_next(node);
0072 }
0073
0074 bsp_interrupt_unlock();
0075 *sc = RTEMS_INVALID_ID;
0076 return NULL;
0077 }
0078
0079 static void bsp_interrupt_server_trigger(void *arg)
0080 {
0081 rtems_interrupt_lock_context lock_context;
0082 rtems_interrupt_server_entry *e = arg;
0083 rtems_interrupt_server_control *s = e->server;
0084
0085 if (bsp_interrupt_is_valid_vector(e->vector)) {
0086 bsp_interrupt_vector_disable(e->vector);
0087 }
0088
0089 rtems_interrupt_lock_acquire(&s->lock, &lock_context);
0090
0091 if (rtems_chain_is_node_off_chain(&e->node)) {
0092 rtems_chain_append_unprotected(&s->entries, &e->node);
0093 } else {
0094 ++s->errors;
0095 }
0096
0097 rtems_interrupt_lock_release(&s->lock, &lock_context);
0098
0099 rtems_event_system_send(s->server, RTEMS_EVENT_SYSTEM_SERVER);
0100 }
0101
0102 typedef struct {
0103 rtems_interrupt_server_entry *entry;
0104 rtems_option *options;
0105 } bsp_interrupt_server_iterate_entry;
0106
0107 static void bsp_interrupt_server_per_handler_routine(
0108 void *iterate_arg,
0109 const char *info,
0110 rtems_option options,
0111 rtems_interrupt_handler handler,
0112 void *handler_arg
0113 )
0114 {
0115 if (handler == bsp_interrupt_server_trigger) {
0116 bsp_interrupt_server_iterate_entry *ie = iterate_arg;
0117
0118 ie->entry = handler_arg;
0119 *ie->options = options;
0120 }
0121 }
0122
0123 static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
0124 rtems_vector_number vector,
0125 rtems_option *trigger_options
0126 )
0127 {
0128 bsp_interrupt_server_iterate_entry ie = {
0129 .entry = NULL,
0130 .options = trigger_options
0131 };
0132
0133 rtems_interrupt_handler_iterate(
0134 vector,
0135 bsp_interrupt_server_per_handler_routine,
0136 &ie
0137 );
0138
0139 return ie.entry;
0140 }
0141
0142 typedef struct {
0143 rtems_interrupt_server_control *server;
0144 rtems_vector_number vector;
0145 rtems_option options;
0146 rtems_interrupt_handler handler;
0147 void *arg;
0148 rtems_id task;
0149 rtems_status_code sc;
0150 } bsp_interrupt_server_helper_data;
0151
0152 static void bsp_interrupt_server_install_helper(void *arg)
0153 {
0154 bsp_interrupt_server_helper_data *hd = arg;
0155 rtems_status_code sc;
0156 rtems_interrupt_server_entry *e;
0157 rtems_interrupt_server_action *a;
0158 rtems_option trigger_options;
0159
0160 a = calloc(1, sizeof(*a));
0161 if (a == NULL) {
0162 hd->sc = RTEMS_NO_MEMORY;
0163 rtems_event_transient_send(hd->task);
0164 return;
0165 }
0166
0167 a->handler = hd->handler;
0168 a->arg = hd->arg;
0169
0170 bsp_interrupt_lock();
0171
0172 e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
0173 if (e == NULL) {
0174 e = calloc(1, sizeof(*e));
0175 if (e != NULL) {
0176 e->server = hd->server;
0177 e->vector = hd->vector;
0178 e->actions = a;
0179
0180 sc = rtems_interrupt_handler_install(
0181 hd->vector,
0182 "IRQS",
0183 hd->options & RTEMS_INTERRUPT_UNIQUE,
0184 bsp_interrupt_server_trigger,
0185 e
0186 );
0187 if (sc != RTEMS_SUCCESSFUL) {
0188 free(e);
0189 }
0190 } else {
0191 sc = RTEMS_NO_MEMORY;
0192 }
0193 #if defined(RTEMS_SMP)
0194 } else if (e->server != hd->server) {
0195 sc = RTEMS_RESOURCE_IN_USE;
0196 #endif
0197 } else if (
0198 RTEMS_INTERRUPT_IS_UNIQUE(hd->options)
0199 || RTEMS_INTERRUPT_IS_UNIQUE(trigger_options)
0200 ) {
0201 sc = RTEMS_RESOURCE_IN_USE;
0202 } else {
0203 rtems_interrupt_server_action **link = &e->actions;
0204 rtems_interrupt_server_action *c;
0205
0206 sc = RTEMS_SUCCESSFUL;
0207
0208 while ((c = *link) != NULL) {
0209 if (c->handler == hd->handler && c->arg == hd->arg) {
0210 sc = RTEMS_TOO_MANY;
0211 break;
0212 }
0213
0214 link = &c->next;
0215 }
0216
0217 if (sc == RTEMS_SUCCESSFUL) {
0218 *link = a;
0219 }
0220 }
0221
0222 bsp_interrupt_unlock();
0223
0224 if (sc != RTEMS_SUCCESSFUL) {
0225 free(a);
0226 }
0227
0228 hd->sc = sc;
0229 rtems_event_transient_send(hd->task);
0230 }
0231
0232 static void bsp_interrupt_server_remove_helper(void *arg)
0233 {
0234 bsp_interrupt_server_helper_data *hd = arg;
0235 rtems_status_code sc;
0236 rtems_interrupt_server_entry *e;
0237 rtems_option trigger_options;
0238
0239 bsp_interrupt_lock();
0240
0241 e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
0242 if (e != NULL) {
0243 rtems_interrupt_server_action **link = &e->actions;
0244 rtems_interrupt_server_action *c;
0245
0246 while ((c = *link) != NULL) {
0247 if (c->handler == hd->handler && c->arg == hd->arg) {
0248 break;
0249 }
0250
0251 link = &c->next;
0252 }
0253
0254 if (c != NULL) {
0255 bool remove_last = e->actions->next == NULL;
0256
0257 if (remove_last) {
0258 rtems_interrupt_handler_remove(
0259 hd->vector,
0260 bsp_interrupt_server_trigger,
0261 e
0262 );
0263 }
0264
0265 *link = c->next;
0266 free(c);
0267
0268 if (remove_last) {
0269 free(e);
0270 }
0271
0272 sc = RTEMS_SUCCESSFUL;
0273 } else {
0274 sc = RTEMS_UNSATISFIED;
0275 }
0276 } else {
0277 sc = RTEMS_INVALID_ID;
0278 }
0279
0280 bsp_interrupt_unlock();
0281
0282 hd->sc = sc;
0283 rtems_event_transient_send(hd->task);
0284 }
0285
0286 static rtems_status_code bsp_interrupt_server_call_helper(
0287 rtems_interrupt_server_control *s,
0288 rtems_vector_number vector,
0289 rtems_option options,
0290 rtems_interrupt_handler handler,
0291 void *arg,
0292 void (*helper)(void *)
0293 )
0294 {
0295 bsp_interrupt_server_helper_data hd = {
0296 .server = s,
0297 .vector = vector,
0298 .options = options,
0299 .handler = handler,
0300 .arg = arg,
0301 .task = rtems_task_self()
0302 };
0303 rtems_interrupt_server_action a = {
0304 .handler = helper,
0305 .arg = &hd
0306 };
0307 rtems_interrupt_server_entry e = {
0308 .server = s,
0309 .vector = BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
0310 .actions = &a
0311 };
0312
0313 bsp_interrupt_server_trigger(&e);
0314 rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0315
0316 return hd.sc;
0317 }
0318
0319 static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
0320 rtems_interrupt_server_control *s
0321 )
0322 {
0323 rtems_interrupt_lock_context lock_context;
0324 rtems_interrupt_server_entry *e;
0325
0326 rtems_interrupt_lock_acquire(&s->lock, &lock_context);
0327
0328 if (!rtems_chain_is_empty(&s->entries)) {
0329 e = (rtems_interrupt_server_entry *)
0330 rtems_chain_get_first_unprotected(&s->entries);
0331 rtems_chain_set_off_chain(&e->node);
0332 } else {
0333 e = NULL;
0334 }
0335
0336 rtems_interrupt_lock_release(&s->lock, &lock_context);
0337
0338 return e;
0339 }
0340
0341 static void bsp_interrupt_server_task(rtems_task_argument arg)
0342 {
0343 rtems_interrupt_server_control *s = (rtems_interrupt_server_control *) arg;
0344
0345 while (true) {
0346 rtems_event_set events;
0347 rtems_interrupt_server_entry *e;
0348
0349 rtems_event_system_receive(
0350 RTEMS_EVENT_SYSTEM_SERVER,
0351 RTEMS_EVENT_ALL | RTEMS_WAIT,
0352 RTEMS_NO_TIMEOUT,
0353 &events
0354 );
0355
0356 while ((e = bsp_interrupt_server_get_entry(s)) != NULL) {
0357 rtems_interrupt_server_action *action = e->actions;
0358 rtems_vector_number vector = e->vector;
0359
0360 do {
0361 rtems_interrupt_server_action *current = action;
0362 action = action->next;
0363 (*current->handler)(current->arg);
0364 } while (action != NULL);
0365
0366 if (bsp_interrupt_is_valid_vector(vector)) {
0367 bsp_interrupt_vector_enable(vector);
0368 }
0369 }
0370 }
0371 }
0372
0373 rtems_status_code rtems_interrupt_server_handler_install(
0374 uint32_t server_index,
0375 rtems_vector_number vector,
0376 const char *info,
0377 rtems_option options,
0378 rtems_interrupt_handler handler,
0379 void *arg
0380 )
0381 {
0382 rtems_status_code sc;
0383 rtems_interrupt_server_control *s;
0384
0385 s = bsp_interrupt_server_get_context(server_index, &sc);
0386 if (s == NULL) {
0387 return sc;
0388 }
0389
0390 return bsp_interrupt_server_call_helper(
0391 s,
0392 vector,
0393 options,
0394 handler,
0395 arg,
0396 bsp_interrupt_server_install_helper
0397 );
0398 }
0399
0400 rtems_status_code rtems_interrupt_server_handler_remove(
0401 uint32_t server_index,
0402 rtems_vector_number vector,
0403 rtems_interrupt_handler handler,
0404 void *arg
0405 )
0406 {
0407 rtems_status_code sc;
0408 rtems_interrupt_server_control *s;
0409
0410 s = bsp_interrupt_server_get_context(server_index, &sc);
0411 if (s == NULL) {
0412 return sc;
0413 }
0414
0415 return bsp_interrupt_server_call_helper(
0416 s,
0417 vector,
0418 0,
0419 handler,
0420 arg,
0421 bsp_interrupt_server_remove_helper
0422 );
0423 }
0424
0425 typedef struct {
0426 rtems_interrupt_per_handler_routine routine;
0427 void *arg;
0428 } bsp_interrupt_server_handler_iterate_helper_data;
0429
0430 static void bsp_interrupt_server_handler_iterate_helper(void *arg)
0431 {
0432 bsp_interrupt_server_helper_data *hd = arg;
0433 bsp_interrupt_server_handler_iterate_helper_data *hihd = hd->arg;
0434 rtems_status_code sc;
0435 rtems_interrupt_server_entry *e;
0436 rtems_option trigger_options;
0437
0438 bsp_interrupt_lock();
0439
0440 e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
0441 if (e != NULL) {
0442 rtems_interrupt_server_action **link = &e->actions;
0443 rtems_interrupt_server_action *c;
0444
0445 while ((c = *link) != NULL) {
0446 (*hihd->routine)(hihd->arg, NULL, trigger_options, c->handler, c->arg);
0447 link = &c->next;
0448 }
0449
0450 sc = RTEMS_SUCCESSFUL;
0451 } else {
0452 sc = RTEMS_UNSATISFIED;
0453 }
0454
0455 bsp_interrupt_unlock();
0456
0457 hd->sc = sc;
0458 rtems_event_transient_send(hd->task);
0459 }
0460
0461 rtems_status_code rtems_interrupt_server_handler_iterate(
0462 uint32_t server_index,
0463 rtems_vector_number vector,
0464 rtems_interrupt_per_handler_routine routine,
0465 void *arg
0466 )
0467 {
0468 rtems_status_code sc;
0469 bsp_interrupt_server_handler_iterate_helper_data hihd;
0470 rtems_interrupt_server_control *s;
0471
0472 s = bsp_interrupt_server_get_context(server_index, &sc);
0473 if (s == NULL) {
0474 return sc;
0475 }
0476
0477 if (!bsp_interrupt_is_valid_vector(vector)) {
0478 return RTEMS_INVALID_ID;
0479 }
0480
0481 hihd.routine = routine;
0482 hihd.arg = arg;
0483 return bsp_interrupt_server_call_helper(
0484 s,
0485 vector,
0486 0,
0487 NULL,
0488 &hihd,
0489 bsp_interrupt_server_handler_iterate_helper
0490 );
0491 }
0492
0493
0494
0495
0496
0497 static void bsp_interrupt_server_destroy_default(
0498 rtems_interrupt_server_control *s
0499 )
0500 {
0501 memset(s, 0, sizeof(*s));
0502 }
0503
0504 #if defined(RTEMS_SMP)
0505 static void bsp_interrupt_server_destroy_secondary(
0506 rtems_interrupt_server_control *s
0507 )
0508 {
0509 free(s);
0510 }
0511 #endif
0512
0513 static rtems_status_code bsp_interrupt_server_create(
0514 rtems_interrupt_server_control *s,
0515 rtems_task_priority priority,
0516 size_t stack_size,
0517 rtems_mode modes,
0518 rtems_attribute attributes,
0519 uint32_t cpu_index
0520 )
0521 {
0522 rtems_status_code sc;
0523 #if defined(RTEMS_SMP)
0524 rtems_id scheduler;
0525 cpu_set_t cpu;
0526 #endif
0527
0528 sc = rtems_task_create(
0529 rtems_build_name('I', 'R', 'Q', 'S'),
0530 priority,
0531 stack_size,
0532 modes,
0533 attributes,
0534 &s->server
0535 );
0536 if (sc != RTEMS_SUCCESSFUL) {
0537 (*s->destroy)(s);
0538 return sc;
0539 }
0540
0541 rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
0542 rtems_chain_initialize_empty(&s->entries);
0543
0544 #if defined(RTEMS_SMP)
0545 sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
0546
0547
0548
0549
0550
0551
0552 if (sc == RTEMS_SUCCESSFUL) {
0553 sc = rtems_task_set_scheduler(s->server, scheduler, priority);
0554 _Assert(sc == RTEMS_SUCCESSFUL);
0555
0556
0557 CPU_ZERO(&cpu);
0558 CPU_SET(cpu_index, &cpu);
0559 (void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
0560 }
0561 #else
0562 (void) cpu_index;
0563 #endif
0564
0565 rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
0566
0567 sc = rtems_task_start(
0568 s->server,
0569 bsp_interrupt_server_task,
0570 (rtems_task_argument) s
0571 );
0572 _Assert(sc == RTEMS_SUCCESSFUL);
0573
0574 return sc;
0575 }
0576
0577 rtems_status_code rtems_interrupt_server_initialize(
0578 rtems_task_priority priority,
0579 size_t stack_size,
0580 rtems_mode modes,
0581 rtems_attribute attributes,
0582 uint32_t *server_count
0583 )
0584 {
0585 rtems_status_code sc;
0586 rtems_interrupt_server_control *s;
0587 uint32_t cpu_index;
0588 #if defined(RTEMS_SMP)
0589 uint32_t cpu_count;
0590 #endif
0591
0592 cpu_index = 0;
0593 s = &bsp_interrupt_server_default;
0594
0595 bsp_interrupt_lock();
0596
0597 if (s->server != 0) {
0598 sc = RTEMS_INCORRECT_STATE;
0599 goto done;
0600 }
0601
0602 s->destroy = bsp_interrupt_server_destroy_default;
0603 sc = bsp_interrupt_server_create(
0604 s,
0605 priority,
0606 stack_size,
0607 modes,
0608 attributes,
0609 cpu_index
0610 );
0611 if (sc != RTEMS_SUCCESSFUL) {
0612 goto done;
0613 }
0614
0615 cpu_index = 1;
0616
0617 #if defined(RTEMS_SMP)
0618 cpu_count = rtems_scheduler_get_processor_maximum();
0619
0620 while (cpu_index < cpu_count) {
0621 s = calloc(1, sizeof(*s));
0622
0623 if (s == NULL) {
0624 sc = RTEMS_NO_MEMORY;
0625 goto done;
0626 }
0627
0628 s->destroy = bsp_interrupt_server_destroy_secondary;
0629 s->index = cpu_index;
0630 sc = bsp_interrupt_server_create(
0631 s,
0632 priority,
0633 stack_size,
0634 modes,
0635 attributes,
0636 cpu_index
0637 );
0638 if (sc != RTEMS_SUCCESSFUL) {
0639 goto done;
0640 }
0641
0642 ++cpu_index;
0643 }
0644 #endif
0645
0646 done:
0647 bsp_interrupt_unlock();
0648
0649 if (server_count != NULL) {
0650 *server_count = cpu_index;
0651 }
0652
0653 return sc;
0654 }
0655
0656 rtems_status_code rtems_interrupt_server_create(
0657 rtems_interrupt_server_control *s,
0658 const rtems_interrupt_server_config *config,
0659 uint32_t *server_index
0660 )
0661 {
0662 rtems_status_code sc;
0663
0664 sc = rtems_task_create(
0665 config->name,
0666 config->priority,
0667 config->storage_size,
0668 config->modes,
0669 config->attributes,
0670 &s->server
0671 );
0672 if (sc != RTEMS_SUCCESSFUL) {
0673 return sc;
0674 }
0675
0676 rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
0677 rtems_chain_initialize_empty(&s->entries);
0678 s->destroy = config->destroy;
0679 s->index = rtems_object_id_get_index(s->server)
0680 + rtems_scheduler_get_processor_maximum();
0681 *server_index = s->index;
0682
0683 bsp_interrupt_lock();
0684 rtems_chain_initialize_node(&s->node);
0685 rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
0686 bsp_interrupt_unlock();
0687
0688 sc = rtems_task_start(
0689 s->server,
0690 bsp_interrupt_server_task,
0691 (rtems_task_argument) s
0692 );
0693 _Assert(sc == RTEMS_SUCCESSFUL);
0694
0695 return sc;
0696 }
0697
0698 static void bsp_interrupt_server_destroy_helper(void *arg)
0699 {
0700 bsp_interrupt_server_helper_data *hd = arg;
0701 rtems_interrupt_server_control *s = hd->server;
0702 rtems_status_code sc;
0703
0704 bsp_interrupt_lock();
0705 rtems_chain_extract_unprotected(&s->node);
0706 bsp_interrupt_unlock();
0707
0708 rtems_interrupt_lock_destroy(&s->lock);
0709
0710 if (s->destroy != NULL) {
0711 (*s->destroy)(s);
0712 }
0713
0714 sc = rtems_event_transient_send(hd->task);
0715 _Assert(sc == RTEMS_SUCCESSFUL);
0716 (void) sc;
0717
0718 rtems_task_exit();
0719 }
0720
0721 rtems_status_code rtems_interrupt_server_delete(uint32_t server_index)
0722 {
0723 rtems_status_code sc;
0724 rtems_interrupt_server_control *s;
0725
0726 s = bsp_interrupt_server_get_context(server_index, &sc);
0727 if (s == NULL) {
0728 return sc;
0729 }
0730
0731 bsp_interrupt_server_call_helper(
0732 s,
0733 BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
0734 0,
0735 NULL,
0736 NULL,
0737 bsp_interrupt_server_destroy_helper
0738 );
0739 return RTEMS_SUCCESSFUL;
0740 }
0741
0742 static void bsp_interrupt_server_entry_initialize(
0743 rtems_interrupt_server_entry *entry,
0744 rtems_interrupt_server_control *s
0745 )
0746 {
0747 rtems_chain_set_off_chain(&entry->node);
0748 entry->server = s;
0749 entry->vector = BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR;
0750 entry->actions = NULL;
0751 }
0752
0753 static void bsp_interrupt_server_action_prepend(
0754 rtems_interrupt_server_entry *entry,
0755 rtems_interrupt_server_action *action,
0756 rtems_interrupt_handler handler,
0757 void *arg
0758 )
0759 {
0760 action->handler = handler;
0761 action->arg = arg;
0762 action->next = entry->actions;
0763 entry->actions = action;
0764 }
0765
0766 rtems_status_code rtems_interrupt_server_entry_initialize(
0767 uint32_t server_index,
0768 rtems_interrupt_server_entry *entry
0769 )
0770 {
0771 rtems_status_code sc;
0772 rtems_interrupt_server_control *s;
0773
0774 s = bsp_interrupt_server_get_context(server_index, &sc);
0775 if (s == NULL) {
0776 return sc;
0777 }
0778
0779 bsp_interrupt_server_entry_initialize(entry, s);
0780 return RTEMS_SUCCESSFUL;
0781 }
0782
0783 void rtems_interrupt_server_action_prepend(
0784 rtems_interrupt_server_entry *entry,
0785 rtems_interrupt_server_action *action,
0786 rtems_interrupt_handler handler,
0787 void *arg
0788 )
0789 {
0790 bsp_interrupt_server_action_prepend(entry, action, handler, arg);
0791 }
0792
0793 void rtems_interrupt_server_entry_submit(
0794 rtems_interrupt_server_entry *entry
0795 )
0796 {
0797 bsp_interrupt_server_trigger(entry);
0798 }
0799
0800 rtems_status_code rtems_interrupt_server_entry_move(
0801 rtems_interrupt_server_entry *entry,
0802 uint32_t destination_server_index
0803 )
0804 {
0805 rtems_status_code sc;
0806 rtems_interrupt_server_control *s;
0807
0808 s = bsp_interrupt_server_get_context(destination_server_index, &sc);
0809 if (s == NULL) {
0810 return sc;
0811 }
0812
0813 entry->server = s;
0814 return RTEMS_SUCCESSFUL;
0815 }
0816
0817 static void bsp_interrupt_server_entry_synchronize_helper(void *arg)
0818 {
0819 bsp_interrupt_server_helper_data *hd = arg;
0820
0821 rtems_event_transient_send(hd->task);
0822 }
0823
0824 void rtems_interrupt_server_entry_destroy(
0825 rtems_interrupt_server_entry *entry
0826 )
0827 {
0828 rtems_interrupt_server_control *s;
0829 rtems_interrupt_lock_context lock_context;
0830
0831 s = entry->server;
0832 rtems_interrupt_lock_acquire(&s->lock, &lock_context);
0833
0834 if (!rtems_chain_is_node_off_chain(&entry->node)) {
0835 rtems_chain_extract_unprotected(&entry->node);
0836 rtems_chain_set_off_chain(&entry->node);
0837 }
0838
0839 rtems_interrupt_lock_release(&s->lock, &lock_context);
0840
0841 bsp_interrupt_server_call_helper(
0842 s,
0843 BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
0844 0,
0845 NULL,
0846 NULL,
0847 bsp_interrupt_server_entry_synchronize_helper
0848 );
0849 }
0850
0851 rtems_status_code rtems_interrupt_server_request_initialize(
0852 uint32_t server_index,
0853 rtems_interrupt_server_request *request,
0854 rtems_interrupt_handler handler,
0855 void *arg
0856 )
0857 {
0858 rtems_status_code sc;
0859 rtems_interrupt_server_control *s;
0860
0861 s = bsp_interrupt_server_get_context(server_index, &sc);
0862 if (s == NULL) {
0863 return sc;
0864 }
0865
0866 bsp_interrupt_server_entry_initialize(&request->entry, s);
0867 bsp_interrupt_server_action_prepend(
0868 &request->entry,
0869 &request->action,
0870 handler,
0871 arg
0872 );
0873 return RTEMS_SUCCESSFUL;
0874 }
0875
0876 static void bsp_interrupt_server_handler_move_helper(void *arg)
0877 {
0878 bsp_interrupt_server_helper_data *hd = arg;
0879 bsp_interrupt_server_handler_iterate_helper_data *hihd = hd->arg;
0880 rtems_interrupt_server_entry *e;
0881 rtems_option trigger_options;
0882
0883 bsp_interrupt_lock();
0884
0885 e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
0886 if (e != NULL) {
0887 rtems_interrupt_lock_context lock_context;
0888 rtems_interrupt_server_control *src = e->server;
0889 rtems_interrupt_server_control *dst = hihd->arg;
0890 bool pending;
0891
0892
0893 (void) src;
0894
0895 rtems_interrupt_lock_acquire(&src->lock, &lock_context);
0896
0897 pending = !rtems_chain_is_node_off_chain(&e->node);
0898 if (pending) {
0899 rtems_chain_extract_unprotected(&e->node);
0900 rtems_chain_set_off_chain(&e->node);
0901 }
0902
0903 rtems_interrupt_lock_release(&src->lock, &lock_context);
0904
0905 e->server = dst;
0906
0907 if (pending) {
0908 bsp_interrupt_server_trigger(e);
0909 }
0910 }
0911
0912 bsp_interrupt_unlock();
0913
0914 rtems_event_transient_send(hd->task);
0915 }
0916
0917 rtems_status_code rtems_interrupt_server_move(
0918 uint32_t source_server_index,
0919 rtems_vector_number vector,
0920 uint32_t destination_server_index
0921 )
0922 {
0923 rtems_status_code sc;
0924 rtems_interrupt_server_control *src;
0925 rtems_interrupt_server_control *dst;
0926 bsp_interrupt_server_handler_iterate_helper_data hihd;
0927
0928 src = bsp_interrupt_server_get_context(source_server_index, &sc);
0929 if (src == NULL) {
0930 return sc;
0931 }
0932
0933 dst = bsp_interrupt_server_get_context(destination_server_index, &sc);
0934 if (dst == NULL) {
0935 return sc;
0936 }
0937
0938 if (!bsp_interrupt_is_valid_vector(vector)) {
0939 return RTEMS_INVALID_ID;
0940 }
0941
0942 hihd.arg = dst;
0943 bsp_interrupt_server_call_helper(
0944 src,
0945 vector,
0946 0,
0947 NULL,
0948 &hihd,
0949 bsp_interrupt_server_handler_move_helper
0950 );
0951 return RTEMS_SUCCESSFUL;
0952 }
0953
0954 static void bsp_interrupt_server_entry_suspend_helper(void *arg)
0955 {
0956 bsp_interrupt_server_helper_data *hd = arg;
0957 rtems_event_set events;
0958
0959 rtems_event_transient_send(hd->task);
0960 rtems_event_system_receive(
0961 RTEMS_EVENT_SYSTEM_SERVER_RESUME,
0962 RTEMS_WAIT,
0963 RTEMS_NO_TIMEOUT,
0964 &events
0965 );
0966 }
0967
0968 rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
0969 {
0970 rtems_status_code sc;
0971 rtems_interrupt_server_control *s;
0972
0973 s = bsp_interrupt_server_get_context(server_index, &sc);
0974 if (s == NULL) {
0975 return sc;
0976 }
0977
0978 bsp_interrupt_server_call_helper(
0979 s,
0980 BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
0981 0,
0982 NULL,
0983 NULL,
0984 bsp_interrupt_server_entry_suspend_helper
0985 );
0986 return RTEMS_SUCCESSFUL;
0987 }
0988
0989 rtems_status_code rtems_interrupt_server_resume(uint32_t server_index)
0990 {
0991 rtems_status_code sc;
0992 rtems_interrupt_server_control *s;
0993
0994 s = bsp_interrupt_server_get_context(server_index, &sc);
0995 if (s == NULL) {
0996 return sc;
0997 }
0998
0999 rtems_event_system_send(s->server, RTEMS_EVENT_SYSTEM_SERVER_RESUME);
1000 bsp_interrupt_server_call_helper(
1001 s,
1002 BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
1003 0,
1004 NULL,
1005 NULL,
1006 bsp_interrupt_server_entry_synchronize_helper
1007 );
1008 return RTEMS_SUCCESSFUL;
1009 }
1010
1011 rtems_status_code rtems_interrupt_server_set_affinity(
1012 uint32_t server_index,
1013 size_t affinity_size,
1014 const cpu_set_t *affinity,
1015 rtems_task_priority priority
1016 )
1017 {
1018 rtems_status_code sc;
1019 rtems_interrupt_server_control *s;
1020 rtems_id scheduler;
1021
1022 s = bsp_interrupt_server_get_context(server_index, &sc);
1023 if (s == NULL) {
1024 return sc;
1025 }
1026
1027 sc = rtems_scheduler_ident_by_processor_set(
1028 affinity_size,
1029 affinity,
1030 &scheduler
1031 );
1032 if (sc != RTEMS_SUCCESSFUL) {
1033 return sc;
1034 }
1035
1036 sc = rtems_task_set_scheduler(s->server, scheduler, priority);
1037 if (sc != RTEMS_SUCCESSFUL) {
1038 return sc;
1039 }
1040
1041 return rtems_task_set_affinity(s->server, affinity_size, affinity);
1042 }