source: rtems/bsps/shared/irq/irq-server.c @ 9b7c456

5
Last change on this file since 9b7c456 was 9b7c456, checked in by Sebastian Huber <sebastian.huber@…>, on 04/05/18 at 04:40:02

bsps: Move generic IRQ support to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 18.9 KB
RevLine 
[8634637]1/**
2 * @file
3 *
4 * @ingroup bsp_interrupt
5 *
6 * @brief Generic BSP interrupt server implementation.
7 */
8
9/*
[3398602]10 * Copyright (c) 2009, 2017 embedded brains GmbH.  All rights reserved.
[5fca9ef]11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
[8634637]17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
[c499856]20 * http://www.rtems.org/license/LICENSE.
[8634637]21 */
22
23#include <stdlib.h>
24
[11d6263b]25#include <rtems.h>
26#include <rtems/chain.h>
[d9bd59da]27#include <rtems/score/assert.h>
[11d6263b]28
[8634637]29#include <bsp/irq-generic.h>
30
[3398602]31#define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
32
[e7ee719f]33typedef struct {
34  RTEMS_INTERRUPT_LOCK_MEMBER(lock);
35  rtems_chain_control entries;
36  rtems_id server;
37  unsigned errors;
38} bsp_interrupt_server_context;
39
40#if defined(RTEMS_SMP)
41static bsp_interrupt_server_context *bsp_interrupt_server_instances;
42#else
43static bsp_interrupt_server_context bsp_interrupt_server_instance;
44#endif
45
46static bsp_interrupt_server_context *bsp_interrupt_server_get_context(
47  uint32_t server_index,
48  rtems_status_code *sc
[5fca9ef]49)
[8634637]50{
[e7ee719f]51#if defined(RTEMS_SMP)
52  if (bsp_interrupt_server_instances == NULL) {
53    *sc = RTEMS_INCORRECT_STATE;
54    return NULL;
[8634637]55  }
[e7ee719f]56#else
57  if (bsp_interrupt_server_instance.server == RTEMS_ID_NONE) {
58    *sc = RTEMS_INCORRECT_STATE;
59    return NULL;
60  }
61#endif
[8634637]62
[e7ee719f]63  if (server_index >= rtems_get_processor_count()) {
64    *sc = RTEMS_INVALID_ID;
65    return NULL;
66  }
67
68  *sc = RTEMS_SUCCESSFUL;
69#if defined(RTEMS_SMP)
70  return &bsp_interrupt_server_instances[server_index];
71#else
72  return &bsp_interrupt_server_instance;
73#endif
74}
[11d6263b]75
[27de3942]76static void bsp_interrupt_server_trigger(void *arg)
[8634637]77{
[610909f]78  rtems_interrupt_lock_context lock_context;
[3398602]79  rtems_interrupt_server_entry *e = arg;
[e7ee719f]80  bsp_interrupt_server_context *s = e->server;
[8634637]81
[c6810c8]82  if (bsp_interrupt_is_valid_vector(e->vector)) {
83    bsp_interrupt_vector_disable(e->vector);
84  }
[8634637]85
[e7ee719f]86  rtems_interrupt_lock_acquire(&s->lock, &lock_context);
[5fca9ef]87
[610909f]88  if (rtems_chain_is_node_off_chain(&e->node)) {
[e7ee719f]89    rtems_chain_append_unprotected(&s->entries, &e->node);
[11d6263b]90  } else {
[e7ee719f]91    ++s->errors;
[11d6263b]92  }
93
[e7ee719f]94  rtems_interrupt_lock_release(&s->lock, &lock_context);
[610909f]95
[e7ee719f]96  rtems_event_system_send(s->server, RTEMS_EVENT_SYSTEM_SERVER);
[11d6263b]97}
98
[8634637]99typedef struct {
[3398602]100  rtems_interrupt_server_entry *entry;
[d9bd59da]101  rtems_option *options;
[8634637]102} bsp_interrupt_server_iterate_entry;
103
104static void bsp_interrupt_server_per_handler_routine(
105  void *iterate_arg,
106  const char *info,
107  rtems_option options,
108  rtems_interrupt_handler handler,
109  void *handler_arg
110)
111{
112  if (handler == bsp_interrupt_server_trigger) {
[d9bd59da]113    bsp_interrupt_server_iterate_entry *ie = iterate_arg;
114
115    ie->entry = handler_arg;
116    *ie->options = options;
[8634637]117  }
118}
119
[3398602]120static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
[d9bd59da]121  rtems_vector_number vector,
122  rtems_option *trigger_options
123)
124{
125  bsp_interrupt_server_iterate_entry ie = {
126    .entry = NULL,
127    .options = trigger_options
128  };
129
130  rtems_interrupt_handler_iterate(
131    vector,
132    bsp_interrupt_server_per_handler_routine,
133    &ie
134  );
135
136  return ie.entry;
137}
138
[10670a5]139typedef struct {
[e7ee719f]140  bsp_interrupt_server_context *server;
[10670a5]141  rtems_vector_number vector;
142  rtems_option options;
143  rtems_interrupt_handler handler;
144  void *arg;
145  rtems_id task;
146  rtems_status_code sc;
147} bsp_interrupt_server_helper_data;
148
149static void bsp_interrupt_server_install_helper(void *arg)
[8634637]150{
[10670a5]151  bsp_interrupt_server_helper_data *hd = arg;
[d9bd59da]152  rtems_status_code sc;
[3398602]153  rtems_interrupt_server_entry *e;
154  rtems_interrupt_server_action *a;
[d9bd59da]155  rtems_option trigger_options;
[8634637]156
[d9bd59da]157  a = calloc(1, sizeof(*a));
158  if (a == NULL) {
[10670a5]159    hd->sc = RTEMS_NO_MEMORY;
160    rtems_event_transient_send(hd->task);
161    return;
[8634637]162  }
163
[10670a5]164  a->handler = hd->handler;
165  a->arg = hd->arg;
[d9bd59da]166
167  bsp_interrupt_lock();
168
[10670a5]169  e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
[8634637]170  if (e == NULL) {
[d9bd59da]171    e = calloc(1, sizeof(*e));
172    if (e != NULL) {
[e7ee719f]173      e->server = hd->server;
[10670a5]174      e->vector = hd->vector;
[d9bd59da]175      e->actions = a;
176
177      sc = rtems_interrupt_handler_install(
[10670a5]178        hd->vector,
[d9bd59da]179        "IRQS",
[10670a5]180        hd->options & RTEMS_INTERRUPT_UNIQUE,
[d9bd59da]181        bsp_interrupt_server_trigger,
182        e
183      );
184      if (sc != RTEMS_SUCCESSFUL) {
185        free(e);
186      }
187    } else {
188      sc = RTEMS_NO_MEMORY;
189    }
[e7ee719f]190#if defined(RTEMS_SMP)
191  } else if (e->server != hd->server) {
192    sc = RTEMS_RESOURCE_IN_USE;
193#endif
[d9bd59da]194  } else if (
[10670a5]195    RTEMS_INTERRUPT_IS_UNIQUE(hd->options)
[d9bd59da]196      || RTEMS_INTERRUPT_IS_UNIQUE(trigger_options)
197  ) {
198    sc = RTEMS_RESOURCE_IN_USE;
199  } else {
[3398602]200    rtems_interrupt_server_action **link = &e->actions;
201    rtems_interrupt_server_action *c;
[d9bd59da]202
[10670a5]203    sc = RTEMS_SUCCESSFUL;
204
[d9bd59da]205    while ((c = *link) != NULL) {
[10670a5]206      if (c->handler == hd->handler && c->arg == hd->arg) {
[d9bd59da]207        sc = RTEMS_TOO_MANY;
208        break;
209      }
210
211      link = &c->next;
212    }
213
214    if (sc == RTEMS_SUCCESSFUL) {
[10670a5]215      *link = a;
[d9bd59da]216    }
[8634637]217  }
218
[d9bd59da]219  bsp_interrupt_unlock();
[8634637]220
221  if (sc != RTEMS_SUCCESSFUL) {
[d9bd59da]222    free(a);
[8634637]223  }
224
[10670a5]225  hd->sc = sc;
226  rtems_event_transient_send(hd->task);
[8634637]227}
228
[10670a5]229static void bsp_interrupt_server_remove_helper(void *arg)
[8634637]230{
[10670a5]231  bsp_interrupt_server_helper_data *hd = arg;
[d9bd59da]232  rtems_status_code sc;
[3398602]233  rtems_interrupt_server_entry *e;
[d9bd59da]234  rtems_option trigger_options;
[8634637]235
[d9bd59da]236  bsp_interrupt_lock();
[8634637]237
[10670a5]238  e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
[d9bd59da]239  if (e != NULL) {
[3398602]240    rtems_interrupt_server_action **link = &e->actions;
241    rtems_interrupt_server_action *c;
[d9bd59da]242
243    while ((c = *link) != NULL) {
[10670a5]244      if (c->handler == hd->handler && c->arg == hd->arg) {
[d9bd59da]245        break;
246      }
247
248      link = &c->next;
249    }
250
251    if (c != NULL) {
252      bool remove_last = e->actions->next == NULL;
253
254      if (remove_last) {
255        rtems_interrupt_handler_remove(
[10670a5]256          hd->vector,
[d9bd59da]257          bsp_interrupt_server_trigger,
258          e
259        );
260      }
261
[10670a5]262      *link = c->next;
[d9bd59da]263      free(c);
264
265      if (remove_last) {
266        free(e);
267      }
[10670a5]268
269      sc = RTEMS_SUCCESSFUL;
[d9bd59da]270    } else {
271      sc = RTEMS_UNSATISFIED;
272    }
273  } else {
274    sc = RTEMS_INVALID_ID;
[8634637]275  }
276
[d9bd59da]277  bsp_interrupt_unlock();
[8634637]278
[10670a5]279  hd->sc = sc;
280  rtems_event_transient_send(hd->task);
281}
282
283static rtems_status_code bsp_interrupt_server_call_helper(
[e7ee719f]284  bsp_interrupt_server_context *s,
[10670a5]285  rtems_vector_number vector,
286  rtems_option options,
287  rtems_interrupt_handler handler,
288  void *arg,
289  void (*helper)(void *)
290)
291{
292  bsp_interrupt_server_helper_data hd = {
[e7ee719f]293    .server = s,
[10670a5]294    .vector = vector,
295    .options = options,
296    .handler = handler,
297    .arg = arg,
298    .task = rtems_task_self()
299  };
[3398602]300  rtems_interrupt_server_action a = {
[10670a5]301    .handler = helper,
302    .arg = &hd
303  };
[3398602]304  rtems_interrupt_server_entry e = {
[e7ee719f]305    .server = s,
[3398602]306    .vector = BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
[10670a5]307    .actions = &a
308  };
309
310  bsp_interrupt_server_trigger(&e);
311  rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
312
313  return hd.sc;
314}
315
[e7ee719f]316static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
317  bsp_interrupt_server_context *s
318)
[10670a5]319{
320  rtems_interrupt_lock_context lock_context;
[3398602]321  rtems_interrupt_server_entry *e;
[10670a5]322
[e7ee719f]323  rtems_interrupt_lock_acquire(&s->lock, &lock_context);
[10670a5]324
[e7ee719f]325  if (!rtems_chain_is_empty(&s->entries)) {
[3398602]326    e = (rtems_interrupt_server_entry *)
[e7ee719f]327      rtems_chain_get_first_unprotected(&s->entries);
[10670a5]328    rtems_chain_set_off_chain(&e->node);
329  } else {
330    e = NULL;
331  }
332
[e7ee719f]333  rtems_interrupt_lock_release(&s->lock, &lock_context);
[10670a5]334
335  return e;
336}
337
338static void bsp_interrupt_server_task(rtems_task_argument arg)
339{
[e7ee719f]340  bsp_interrupt_server_context *s = (bsp_interrupt_server_context *) arg;
341
[10670a5]342  while (true) {
343    rtems_event_set events;
[3398602]344    rtems_interrupt_server_entry *e;
[10670a5]345
346    rtems_event_system_receive(
347      RTEMS_EVENT_SYSTEM_SERVER,
348      RTEMS_EVENT_ALL | RTEMS_WAIT,
349      RTEMS_NO_TIMEOUT,
350      &events
351    );
352
[e7ee719f]353    while ((e = bsp_interrupt_server_get_entry(s)) != NULL) {
[3398602]354      rtems_interrupt_server_action *action = e->actions;
[10670a5]355      rtems_vector_number vector = e->vector;
356
357      do {
[3398602]358        rtems_interrupt_server_action *current = action;
[10670a5]359        action = action->next;
360        (*current->handler)(current->arg);
361      } while (action != NULL);
362
[c6810c8]363      if (bsp_interrupt_is_valid_vector(vector)) {
364        bsp_interrupt_vector_enable(vector);
365      }
[10670a5]366    }
367  }
368}
369
370rtems_status_code rtems_interrupt_server_handler_install(
[e7ee719f]371  uint32_t server_index,
[10670a5]372  rtems_vector_number vector,
373  const char *info,
374  rtems_option options,
375  rtems_interrupt_handler handler,
376  void *arg
377)
378{
379  rtems_status_code sc;
[e7ee719f]380  bsp_interrupt_server_context *s;
[10670a5]381
[e7ee719f]382  s = bsp_interrupt_server_get_context(server_index, &sc);
383  if (s == NULL) {
[10670a5]384    return sc;
385  }
386
387  return bsp_interrupt_server_call_helper(
[e7ee719f]388    s,
[10670a5]389    vector,
390    options,
391    handler,
392    arg,
393    bsp_interrupt_server_install_helper
394  );
395}
396
397rtems_status_code rtems_interrupt_server_handler_remove(
[e7ee719f]398  uint32_t server_index,
[10670a5]399  rtems_vector_number vector,
400  rtems_interrupt_handler handler,
401  void *arg
402)
403{
404  rtems_status_code sc;
[e7ee719f]405  bsp_interrupt_server_context *s;
[10670a5]406
[e7ee719f]407  s = bsp_interrupt_server_get_context(server_index, &sc);
408  if (s == NULL) {
[10670a5]409    return sc;
410  }
411
412  return bsp_interrupt_server_call_helper(
[e7ee719f]413    s,
[10670a5]414    vector,
415    0,
416    handler,
417    arg,
418    bsp_interrupt_server_remove_helper
419  );
[8634637]420}
421
[5bfeab95]422typedef struct {
423  rtems_interrupt_per_handler_routine routine;
424  void *arg;
425} bsp_interrupt_server_handler_iterate_helper_data;
426
427static void bsp_interrupt_server_handler_iterate_helper(void *arg)
428{
429  bsp_interrupt_server_helper_data *hd = arg;
430  bsp_interrupt_server_handler_iterate_helper_data *hihd = hd->arg;
431  rtems_status_code sc;
432  rtems_interrupt_server_entry *e;
433  rtems_option trigger_options;
434
435  bsp_interrupt_lock();
436
437  e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
438  if (e != NULL) {
439    rtems_interrupt_server_action **link = &e->actions;
440    rtems_interrupt_server_action *c;
441
442    while ((c = *link) != NULL) {
443      (*hihd->routine)(hihd->arg, NULL, trigger_options, c->handler, c->arg);
444      link = &c->next;
445    }
446
447    sc = RTEMS_SUCCESSFUL;
448  } else {
449    sc = RTEMS_UNSATISFIED;
450  }
451
452  bsp_interrupt_unlock();
453
454  hd->sc = sc;
455  rtems_event_transient_send(hd->task);
456}
457
458rtems_status_code rtems_interrupt_server_handler_iterate(
[e7ee719f]459  uint32_t server_index,
[5bfeab95]460  rtems_vector_number vector,
461  rtems_interrupt_per_handler_routine routine,
462  void *arg
463)
464{
465  rtems_status_code sc;
466  bsp_interrupt_server_handler_iterate_helper_data hihd;
[e7ee719f]467  bsp_interrupt_server_context *s;
[5bfeab95]468
[e7ee719f]469  s = bsp_interrupt_server_get_context(server_index, &sc);
470  if (s == NULL) {
[5bfeab95]471    return sc;
472  }
473
474  if (!bsp_interrupt_is_valid_vector(vector)) {
475    return RTEMS_INVALID_ID;
476  }
477
478  hihd.routine = routine;
479  hihd.arg = arg;
480  return bsp_interrupt_server_call_helper(
[e7ee719f]481    s,
[5bfeab95]482    vector,
483    0,
484    NULL,
485    &hihd,
486    bsp_interrupt_server_handler_iterate_helper
487  );
488}
489
[8634637]490rtems_status_code rtems_interrupt_server_initialize(
491  rtems_task_priority priority,
492  size_t stack_size,
493  rtems_mode modes,
494  rtems_attribute attributes,
[e7ee719f]495  uint32_t *server_count
[8634637]496)
497{
[e7ee719f]498  uint32_t cpu_index;
499  uint32_t cpu_count;
500  uint32_t dummy;
501  bsp_interrupt_server_context *instances;
[8634637]502
[e7ee719f]503  if (server_count == NULL) {
504    server_count = &dummy;
[27de3942]505  }
506
[e7ee719f]507  cpu_count = rtems_get_processor_count();
508
509#if defined(RTEMS_SMP)
510  instances = calloc(cpu_count, sizeof(*instances));
511  if (instances == NULL) {
512    return RTEMS_NO_MEMORY;
[8634637]513  }
[e7ee719f]514#else
515  instances = &bsp_interrupt_server_instance;
516#endif
517
518  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
519    bsp_interrupt_server_context *s = &instances[cpu_index];
520    rtems_status_code sc;
521#if defined(RTEMS_SMP)
522    rtems_id scheduler;
523    cpu_set_t cpu;
524#endif
525
526    rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
527    rtems_chain_initialize_empty(&s->entries);
528
529    sc = rtems_task_create(
530      rtems_build_name('I', 'R', 'Q', 'S'),
531      priority,
532      stack_size,
533      modes,
534      attributes,
535      &s->server
536    );
537    if (sc != RTEMS_SUCCESSFUL) {
538      *server_count = cpu_index;
[8634637]539
[e7ee719f]540#if defined(RTEMS_SMP)
541      if (cpu_index > 0) {
542        return RTEMS_SUCCESSFUL;
543      }
544
545      free(instances);
546#endif
547
548      return RTEMS_TOO_MANY;
549    }
550
551#if defined(RTEMS_SMP)
552    sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
553    _Assert(sc == RTEMS_SUCCESSFUL);
554
555    sc = rtems_task_set_scheduler(s->server, scheduler, priority);
556    _Assert(sc == RTEMS_SUCCESSFUL);
557
558    CPU_ZERO(&cpu);
559    CPU_SET(cpu_index, &cpu);
560    sc = rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
561    _Assert(sc == RTEMS_SUCCESSFUL);
562#endif
563
564    sc = rtems_task_start(
565      s->server,
566      bsp_interrupt_server_task,
567      (rtems_task_argument) s
568    );
569    _Assert(sc == RTEMS_SUCCESSFUL);
570  }
571
572#if defined(RTEMS_SMP)
573  bsp_interrupt_server_instances = instances;
574#endif
575  *server_count = cpu_index;
[8634637]576
577  return RTEMS_SUCCESSFUL;
578}
[3398602]579
580static void bsp_interrupt_server_entry_initialize(
[e7ee719f]581  rtems_interrupt_server_entry *entry,
582  bsp_interrupt_server_context *s
[3398602]583)
584{
585  rtems_chain_set_off_chain(&entry->node);
[e7ee719f]586  entry->server = s;
[3398602]587  entry->vector = BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR;
588  entry->actions = NULL;
589}
590
591static void bsp_interrupt_server_action_prepend(
592  rtems_interrupt_server_entry  *entry,
593  rtems_interrupt_server_action *action,
594  rtems_interrupt_handler        handler,
595  void                          *arg
596)
597{
598  action->handler = handler;
599  action->arg = arg;
600  action->next = entry->actions;
601  entry->actions = action;
602}
603
[e7ee719f]604rtems_status_code rtems_interrupt_server_entry_initialize(
605  uint32_t                      server_index,
[3398602]606  rtems_interrupt_server_entry *entry
607)
608{
[e7ee719f]609  rtems_status_code sc;
610  bsp_interrupt_server_context *s;
611
612  s = bsp_interrupt_server_get_context(server_index, &sc);
613  if (s == NULL) {
614    return sc;
615  }
616
617  bsp_interrupt_server_entry_initialize(entry, s);
618  return RTEMS_SUCCESSFUL;
[3398602]619}
620
621void rtems_interrupt_server_action_prepend(
622  rtems_interrupt_server_entry  *entry,
623  rtems_interrupt_server_action *action,
624  rtems_interrupt_handler        handler,
625  void                          *arg
626)
627{
628  bsp_interrupt_server_action_prepend(entry, action, handler, arg);
629}
630
631void rtems_interrupt_server_entry_submit(
632  rtems_interrupt_server_entry *entry
633)
634{
635  bsp_interrupt_server_trigger(entry);
636}
637
[a961e198]638static void bsp_interrupt_server_entry_synchronize_helper(void *arg)
[3398602]639{
640  bsp_interrupt_server_helper_data *hd = arg;
641
642  rtems_event_transient_send(hd->task);
643}
644
645void rtems_interrupt_server_entry_destroy(
646  rtems_interrupt_server_entry *entry
647)
648{
[e7ee719f]649  bsp_interrupt_server_context *s;
[3398602]650  rtems_interrupt_lock_context lock_context;
651
[e7ee719f]652  s = entry->server;
653  rtems_interrupt_lock_acquire(&s->lock, &lock_context);
[3398602]654
655  if (!rtems_chain_is_node_off_chain(&entry->node)) {
656    rtems_chain_extract_unprotected(&entry->node);
657    rtems_chain_set_off_chain(&entry->node);
658  }
659
[e7ee719f]660  rtems_interrupt_lock_release(&s->lock, &lock_context);
[3398602]661
662  bsp_interrupt_server_call_helper(
[e7ee719f]663    s,
[3398602]664    BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
665    0,
666    NULL,
667    NULL,
[a961e198]668    bsp_interrupt_server_entry_synchronize_helper
[3398602]669  );
670}
671
[e7ee719f]672rtems_status_code rtems_interrupt_server_request_initialize(
673  uint32_t                        server_index,
[3398602]674  rtems_interrupt_server_request *request,
675  rtems_interrupt_handler         handler,
676  void                           *arg
677)
678{
[e7ee719f]679  rtems_status_code sc;
680  bsp_interrupt_server_context *s;
681
682  s = bsp_interrupt_server_get_context(server_index, &sc);
683  if (s == NULL) {
684    return sc;
685  }
686
687  bsp_interrupt_server_entry_initialize(&request->entry, s);
[3398602]688  bsp_interrupt_server_action_prepend(
689    &request->entry,
690    &request->action,
691    handler,
692    arg
693  );
[e7ee719f]694  return RTEMS_SUCCESSFUL;
[3398602]695}
[a961e198]696
[ccc87c8b]697static void bsp_interrupt_server_handler_move_helper(void *arg)
698{
699  bsp_interrupt_server_helper_data *hd = arg;
700  bsp_interrupt_server_handler_iterate_helper_data *hihd = hd->arg;
701  rtems_interrupt_server_entry *e;
702  rtems_option trigger_options;
703
704  bsp_interrupt_lock();
705
706  e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
707  if (e != NULL) {
708    rtems_interrupt_lock_context lock_context;
709    bsp_interrupt_server_context *src = e->server;
710    bsp_interrupt_server_context *dst = hihd->arg;
711    bool pending;
712
[dcc3ccc]713    /* The source server is only used in SMP configurations for the lock */
714    (void) src;
715
[ccc87c8b]716    rtems_interrupt_lock_acquire(&src->lock, &lock_context);
717
718    pending = !rtems_chain_is_node_off_chain(&e->node);
719    if (pending) {
720      rtems_chain_extract_unprotected(&e->node);
721      rtems_chain_set_off_chain(&e->node);
722    }
723
724    rtems_interrupt_lock_release(&src->lock, &lock_context);
725
726    e->server = dst;
727
728    if (pending) {
729      bsp_interrupt_server_trigger(e);
730    }
731  }
732
733  bsp_interrupt_unlock();
734
735  rtems_event_transient_send(hd->task);
736}
737
738rtems_status_code rtems_interrupt_server_move(
739  uint32_t source_server_index,
740  rtems_vector_number vector,
741  uint32_t destination_server_index
742)
743{
744  rtems_status_code sc;
745  bsp_interrupt_server_context *src;
746  bsp_interrupt_server_context *dst;
747  bsp_interrupt_server_handler_iterate_helper_data hihd;
748
749  src = bsp_interrupt_server_get_context(source_server_index, &sc);
750  if (src == NULL) {
751    return sc;
752  }
753
754  dst = bsp_interrupt_server_get_context(destination_server_index, &sc);
755  if (dst == NULL) {
756    return sc;
757  }
758
759  if (!bsp_interrupt_is_valid_vector(vector)) {
760    return RTEMS_INVALID_ID;
761  }
762
763  hihd.arg = dst;
764  bsp_interrupt_server_call_helper(
765    src,
766    vector,
767    0,
768    NULL,
769    &hihd,
770    bsp_interrupt_server_handler_move_helper
771  );
772  return RTEMS_SUCCESSFUL;
773}
774
[a961e198]775static void bsp_interrupt_server_entry_suspend_helper(void *arg)
776{
777  bsp_interrupt_server_helper_data *hd = arg;
778  rtems_event_set events;
779
780  rtems_event_transient_send(hd->task);
781  rtems_event_system_receive(
782    RTEMS_EVENT_SYSTEM_SERVER_RESUME,
783    RTEMS_WAIT,
784    RTEMS_NO_TIMEOUT,
785    &events
786  );
787}
788
789rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
790{
791  rtems_status_code sc;
792  bsp_interrupt_server_context *s;
793
794  s = bsp_interrupt_server_get_context(server_index, &sc);
795  if (s == NULL) {
796    return sc;
797  }
798
799  bsp_interrupt_server_call_helper(
800    s,
801    BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
802    0,
803    NULL,
804    NULL,
805    bsp_interrupt_server_entry_suspend_helper
806  );
807  return RTEMS_SUCCESSFUL;
808}
809
810rtems_status_code rtems_interrupt_server_resume(uint32_t server_index)
811{
812  rtems_status_code sc;
813  bsp_interrupt_server_context *s;
814
815  s = bsp_interrupt_server_get_context(server_index, &sc);
816  if (s == NULL) {
817    return sc;
818  }
819
820  rtems_event_system_send(s->server, RTEMS_EVENT_SYSTEM_SERVER_RESUME);
821  bsp_interrupt_server_call_helper(
822    s,
823    BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
824    0,
825    NULL,
826    NULL,
827    bsp_interrupt_server_entry_synchronize_helper
828  );
829  return RTEMS_SUCCESSFUL;
830}
[d184140]831
832rtems_status_code rtems_interrupt_server_set_affinity(
833  uint32_t            server_index,
834  size_t              affinity_size,
835  const cpu_set_t    *affinity,
836  rtems_task_priority priority
837)
838{
839  rtems_status_code sc;
840  bsp_interrupt_server_context *s;
841  rtems_id scheduler;
842
843  s = bsp_interrupt_server_get_context(server_index, &sc);
844  if (s == NULL) {
845    return sc;
846  }
847
848  sc = rtems_scheduler_ident_by_processor_set(
849    affinity_size,
850    affinity,
851    &scheduler
852  );
853  if (sc != RTEMS_SUCCESSFUL) {
854    return sc;
855  }
856
857  sc = rtems_task_set_scheduler(s->server, scheduler, priority);
858  if (sc != RTEMS_SUCCESSFUL) {
859    return sc;
860  }
861
862  return rtems_task_set_affinity(s->server, affinity_size, affinity);
863}
Note: See TracBrowser for help on using the repository browser.