source: rtems/testsuites/sptests/spintrcritical23/init.c @ 2e9c3d5

4.115
Last change on this file since 2e9c3d5 was 2e9c3d5, checked in by Sebastian Huber <sebastian.huber@…>, on 03/17/15 at 15:28:50

score: Add thread priority change handler

Since the thread current priority change and thread queue requeue is
performed in one critical section it is possible to simplify the thread
queue requeue procedure. Add a thread queue agnostic thread priority
change handler so that we are able to use alternative thread queue
implementations.

Update #2273.

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/*
2 * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <tmacros.h>
20#include <intrcritical.h>
21
22#include <string.h>
23
24#include <rtems.h>
25#include <rtems/score/schedulerpriority.h>
26#include <rtems/score/threadimpl.h>
27
28const char rtems_test_name[] = "SPINTRCRITICAL 23";
29
30typedef struct {
31  RTEMS_INTERRUPT_LOCK_MEMBER(lock)
32  rtems_id task_id;
33  Thread_Control *tcb;
34  rtems_task_priority priority_task;
35  rtems_task_priority priority_interrupt;
36  uint32_t priority_generation;
37  Scheduler_priority_Node scheduler_node;
38  bool done;
39} test_context;
40
41static test_context ctx_instance;
42
43static Thread_Control *get_tcb(rtems_id id)
44{
45  Objects_Locations location;
46  Thread_Control *tcb;
47
48  tcb = _Thread_Get(id, &location);
49  _Objects_Put(&tcb->Object);
50
51  rtems_test_assert(tcb != NULL && location == OBJECTS_LOCAL);
52
53  return tcb;
54}
55
56static bool scheduler_node_unchanged(const test_context *ctx)
57{
58   return memcmp(
59     &ctx->scheduler_node,
60     ctx->tcb->Scheduler.node,
61     sizeof(ctx->scheduler_node)
62   ) == 0;
63}
64
65static void change_priority(rtems_id timer, void *arg)
66{
67  /* The arg is NULL */
68  test_context *ctx = &ctx_instance;
69  rtems_interrupt_lock_context lock_context;
70
71  rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
72  if (
73    ctx->priority_generation != ctx->tcb->Priority.generation
74      && scheduler_node_unchanged(ctx)
75  ) {
76    rtems_task_priority priority_interrupt;
77    rtems_task_priority priority_task;
78    rtems_task_priority previous;
79    rtems_status_code sc;
80
81    priority_interrupt = ctx->priority_interrupt;
82    priority_task = ctx->priority_task;
83
84    rtems_interrupt_lock_release(&ctx->lock, &lock_context);
85
86    sc = rtems_task_set_priority(
87      ctx->task_id,
88      priority_interrupt,
89      &previous
90    );
91    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
92    rtems_test_assert(previous == priority_task);
93
94    ctx->done = true;
95  } else {
96    rtems_interrupt_lock_release(&ctx->lock, &lock_context);
97  }
98}
99
100static bool test_body(void *arg)
101{
102  test_context *ctx = arg;
103  rtems_status_code sc;
104  rtems_interrupt_lock_context lock_context;
105  rtems_task_priority priority_last;
106  rtems_task_priority priority_task;
107  rtems_task_priority priority_interrupt;
108  rtems_task_priority previous;
109
110  rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
111  priority_last = ctx->priority_task;
112  priority_task = 1 + (priority_last + 1) % 3;
113  priority_interrupt = 1 + (priority_task + 1) % 3;
114  ctx->priority_task = priority_task;
115  ctx->priority_interrupt = priority_interrupt;
116  ctx->priority_generation = ctx->tcb->Priority.generation;
117  memcpy(
118    &ctx->scheduler_node,
119    ctx->tcb->Scheduler.node,
120    sizeof(ctx->scheduler_node)
121  );
122  rtems_interrupt_lock_release(&ctx->lock, &lock_context);
123
124  sc = rtems_task_set_priority(
125    ctx->task_id,
126    priority_task,
127    &previous
128  );
129  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
130  rtems_test_assert(previous == priority_last);
131
132  if (ctx->done) {
133    sc = rtems_task_set_priority(
134      ctx->task_id,
135      RTEMS_CURRENT_PRIORITY,
136      &previous
137    );
138    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
139    rtems_test_assert(previous == priority_interrupt);
140  }
141
142  return ctx->done;
143}
144
145static void Init(rtems_task_argument arg)
146{
147  test_context *ctx = &ctx_instance;
148  rtems_status_code sc;
149
150  TEST_BEGIN();
151
152  rtems_interrupt_lock_initialize(&ctx->lock, "Test");
153  ctx->priority_task = 1;
154
155  sc = rtems_task_create(
156    rtems_build_name('T', 'E', 'S', 'T'),
157    ctx->priority_task,
158    RTEMS_MINIMUM_STACK_SIZE,
159    RTEMS_DEFAULT_MODES,
160    RTEMS_DEFAULT_ATTRIBUTES,
161    &ctx->task_id
162  );
163  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
164
165  ctx->tcb = get_tcb(ctx->task_id);
166
167  interrupt_critical_section_test(test_body, ctx, change_priority);
168  rtems_test_assert(ctx->done);
169
170  TEST_END();
171  rtems_test_exit(0);
172}
173
174#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
175#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
176
177#define CONFIGURE_MICROSECONDS_PER_TICK 1000
178
179#define CONFIGURE_MAXIMUM_TASKS 2
180#define CONFIGURE_MAXIMUM_TIMERS 1
181#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
182
183#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
184
185#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
186
187#define CONFIGURE_INIT
188
189#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.