source: rtems/testsuites/smptests/smpscheduler03/test.c @ 1dbce41

Last change on this file since 1dbce41 was 1dbce41, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 26, 2017 at 8:27:23 AM

smptests: Split smpscheduler03

Split smpscheduler03 to run the tests with only one processor.

Update #3056.

  • Property mode set to 100644
File size: 13.6 KB
Line 
1/*
2 * Copyright (c) 2014, 2017 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 <rtems.h>
20#include <rtems/libcsupport.h>
21#include <rtems/score/threadimpl.h>
22#include <rtems/score/schedulersmpimpl.h>
23
24#include "tmacros.h"
25
26void Init(rtems_task_argument arg);
27
28static Scheduler_SMP_Node *get_scheduler_node(Thread_Control *thread)
29{
30  return _Scheduler_SMP_Node_downcast(_Thread_Scheduler_get_home_node(thread));
31}
32
33static void apply_priority(
34  Thread_Control *thread,
35  Priority_Control new_priority,
36  bool prepend_it,
37  Thread_queue_Context *queue_context
38)
39{
40  _Thread_queue_Context_initialize(queue_context);
41  _Thread_queue_Context_clear_priority_updates(queue_context);
42  _Thread_Wait_acquire(thread, queue_context);
43  _Thread_Priority_change(
44    thread,
45    &thread->Real_priority,
46    new_priority,
47    prepend_it,
48    queue_context
49  );
50  _Thread_Wait_release(thread, queue_context);
51}
52
53static void change_priority(
54  Thread_Control *thread,
55  Priority_Control new_priority,
56  bool prepend_it
57)
58{
59  Thread_queue_Context queue_context;
60
61  apply_priority(thread, new_priority, prepend_it, &queue_context);
62  _Thread_Priority_update(&queue_context);
63}
64
65static void task(rtems_task_argument arg)
66{
67  rtems_test_assert(0);
68}
69
70static rtems_id start_task(rtems_task_priority prio)
71{
72  rtems_status_code sc;
73  rtems_id task_id;
74
75  sc = rtems_task_create(
76    rtems_build_name('T', 'A', 'S', 'K'),
77    prio,
78    RTEMS_MINIMUM_STACK_SIZE,
79    RTEMS_DEFAULT_MODES,
80    RTEMS_DEFAULT_ATTRIBUTES,
81    &task_id
82  );
83  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
84
85  sc = rtems_task_start(task_id, task, 0);
86  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
87
88  return task_id;
89}
90
91static Thread_Control *get_thread_by_id(rtems_id task_id)
92{
93  ISR_lock_Context lock_context;
94  Thread_Control *thread;
95
96  thread = _Thread_Get(task_id, &lock_context);
97  rtems_test_assert(thread != NULL);
98  _ISR_lock_ISR_enable(&lock_context);
99
100  return thread;
101}
102
103static void test_case_change_priority(
104  Thread_Control *executing,
105  Scheduler_SMP_Node *executing_node,
106  Scheduler_SMP_Node_state start_state,
107  Priority_Control prio,
108  bool prepend_it,
109  Scheduler_SMP_Node_state new_state
110)
111{
112  Per_CPU_Control *cpu_self;
113
114  cpu_self = _Thread_Dispatch_disable();
115
116  switch (start_state) {
117    case SCHEDULER_SMP_NODE_SCHEDULED:
118      change_priority(executing, 1, true);
119      break;
120    case SCHEDULER_SMP_NODE_READY:
121      change_priority(executing, 4, true);
122      break;
123    default:
124      rtems_test_assert(0);
125      break;
126  }
127  rtems_test_assert(executing_node->state == start_state);
128
129  change_priority(executing, prio, prepend_it);
130  rtems_test_assert(executing_node->state == new_state);
131
132  change_priority(executing, 1, true);
133  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
134
135  _Thread_Dispatch_enable( cpu_self );
136}
137
138static const Scheduler_SMP_Node_state states[2] = {
139  SCHEDULER_SMP_NODE_SCHEDULED,
140  SCHEDULER_SMP_NODE_READY
141};
142
143static const Priority_Control priorities[2] = { 2, 5 };
144
145static const bool prepend_it[2] = { true, false };
146
147static void test_change_priority(void)
148{
149  rtems_status_code sc;
150  rtems_id task_id;
151  Thread_Control *executing;
152  Scheduler_SMP_Node *executing_node;
153  size_t i;
154  size_t j;
155  size_t k;
156
157  task_id = start_task(3);
158  executing = _Thread_Get_executing();
159  executing_node = get_scheduler_node(executing);
160
161  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
162    for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
163      for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) {
164        test_case_change_priority(
165          executing,
166          executing_node,
167          states[i],
168          priorities[j],
169          prepend_it[k],
170          states[j]
171        );
172      }
173    }
174  }
175
176  sc = rtems_task_delete(task_id);
177  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
178}
179
180static void update_priority_op(
181  Thread_Control *thread,
182  Scheduler_SMP_Node *scheduler_node,
183  Priority_Control new_priority,
184  bool prepend_it
185)
186{
187  const Scheduler_Control *scheduler;
188  ISR_lock_Context state_lock_context;
189  ISR_lock_Context scheduler_lock_context;
190  Thread_queue_Context queue_context;
191
192  apply_priority(thread, new_priority, prepend_it, &queue_context);
193
194  _Thread_State_acquire( thread, &state_lock_context );
195  scheduler = _Thread_Scheduler_get_home( thread );
196  _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
197
198  (*scheduler->Operations.update_priority)(
199    scheduler,
200    thread,
201    &scheduler_node->Base
202  );
203
204  _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
205  _Thread_State_release( thread, &state_lock_context );
206}
207
208static void test_case_update_priority_op(
209  Thread_Control *executing,
210  Scheduler_SMP_Node *executing_node,
211  Thread_Control *other,
212  Scheduler_SMP_Node_state start_state,
213  Priority_Control prio,
214  bool prepend_it,
215  Scheduler_SMP_Node_state new_state
216)
217{
218  Per_CPU_Control *cpu_self;
219
220  cpu_self = _Thread_Dispatch_disable();
221
222  switch (start_state) {
223    case SCHEDULER_SMP_NODE_SCHEDULED:
224      change_priority(executing, 1, true);
225      break;
226    case SCHEDULER_SMP_NODE_READY:
227      change_priority(executing, 4, true);
228      break;
229    default:
230      rtems_test_assert(0);
231      break;
232  }
233  rtems_test_assert(executing_node->state == start_state);
234
235  update_priority_op(executing, executing_node, prio, prepend_it);
236  rtems_test_assert(executing_node->state == new_state);
237
238  if (start_state != new_state) {
239    switch (start_state) {
240      case SCHEDULER_SMP_NODE_SCHEDULED:
241        rtems_test_assert(cpu_self->heir == other);
242        break;
243      case SCHEDULER_SMP_NODE_READY:
244        rtems_test_assert(cpu_self->heir == executing);
245        break;
246      default:
247        rtems_test_assert(0);
248        break;
249    }
250  }
251
252  change_priority(executing, 1, true);
253  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
254
255  _Thread_Dispatch_enable( cpu_self );
256}
257
258static void test_update_priority_op(void)
259{
260  rtems_status_code sc;
261  rtems_id task_id;
262  Thread_Control *executing;
263  Scheduler_SMP_Node *executing_node;
264  Thread_Control *other;
265  size_t i;
266  size_t j;
267  size_t k;
268
269  task_id = start_task(3);
270  executing = _Thread_Get_executing();
271  executing_node = get_scheduler_node(executing);
272
273  other = get_thread_by_id(task_id);
274
275  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
276    for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
277      for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) {
278        test_case_update_priority_op(
279          executing,
280          executing_node,
281          other,
282          states[i],
283          priorities[j],
284          prepend_it[k],
285          states[j]
286        );
287      }
288    }
289  }
290
291  sc = rtems_task_delete(task_id);
292  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
293}
294
295static void yield_op(
296  Thread_Control *thread,
297  Scheduler_SMP_Node *scheduler_node
298)
299{
300  const Scheduler_Control *scheduler;
301  ISR_lock_Context state_lock_context;
302  ISR_lock_Context scheduler_lock_context;
303
304  _Thread_State_acquire( thread, &state_lock_context );
305  scheduler = _Thread_Scheduler_get_home( thread );
306  _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
307
308  (*scheduler->Operations.yield)(
309    scheduler,
310    thread,
311    &scheduler_node->Base
312  );
313
314  _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
315  _Thread_State_release( thread, &state_lock_context );
316}
317
318static void test_case_yield_op(
319  Thread_Control *executing,
320  Scheduler_SMP_Node *executing_node,
321  Thread_Control *other,
322  Scheduler_SMP_Node_state start_state,
323  Scheduler_SMP_Node_state new_state
324)
325{
326  Per_CPU_Control *cpu_self;
327
328  cpu_self = _Thread_Dispatch_disable();
329
330  change_priority(executing, 4, false);
331  change_priority(other, 4, false);
332
333  switch (start_state) {
334    case SCHEDULER_SMP_NODE_SCHEDULED:
335      switch (new_state) {
336        case SCHEDULER_SMP_NODE_SCHEDULED:
337          change_priority(executing, 2, false);
338          change_priority(other, 3, false);
339          break;
340        case SCHEDULER_SMP_NODE_READY:
341          change_priority(executing, 2, false);
342          change_priority(other, 2, false);
343          break;
344        default:
345          rtems_test_assert(0);
346          break;
347      }
348      break;
349    case SCHEDULER_SMP_NODE_READY:
350      switch (new_state) {
351        case SCHEDULER_SMP_NODE_SCHEDULED:
352          rtems_test_assert(0);
353          break;
354        case SCHEDULER_SMP_NODE_READY:
355          change_priority(executing, 3, false);
356          change_priority(other, 2, false);
357          break;
358        default:
359          rtems_test_assert(0);
360          break;
361      }
362      break;
363    default:
364      rtems_test_assert(0);
365      break;
366  }
367  rtems_test_assert(executing_node->state == start_state);
368
369  yield_op(executing, executing_node);
370  rtems_test_assert(executing_node->state == new_state);
371
372  switch (new_state) {
373    case SCHEDULER_SMP_NODE_SCHEDULED:
374    case SCHEDULER_SMP_NODE_READY:
375      break;
376    default:
377      rtems_test_assert(0);
378      break;
379  }
380
381  change_priority(executing, 1, true);
382  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
383
384  _Thread_Dispatch_enable( cpu_self );
385}
386
387static void test_yield_op(void)
388{
389  rtems_status_code sc;
390  rtems_id task_id;
391  Thread_Control *executing;
392  Scheduler_SMP_Node *executing_node;
393  Thread_Control *other;
394  size_t i;
395  size_t j;
396
397  task_id = start_task(2);
398  executing = _Thread_Get_executing();
399  executing_node = get_scheduler_node(executing);
400
401  other = get_thread_by_id(task_id);
402
403  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
404    for (j = 0; j < RTEMS_ARRAY_SIZE(states); ++j) {
405      if (
406        states[i] != SCHEDULER_SMP_NODE_READY
407          || states[j] != SCHEDULER_SMP_NODE_SCHEDULED
408      ) {
409        test_case_yield_op(
410          executing,
411          executing_node,
412          other,
413          states[i],
414          states[j]
415        );
416      }
417    }
418  }
419
420  sc = rtems_task_delete(task_id);
421  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
422}
423
424static void block_op(
425  Thread_Control *thread,
426  Scheduler_SMP_Node *scheduler_node
427)
428{
429  const Scheduler_Control *scheduler;
430  ISR_lock_Context state_lock_context;
431  ISR_lock_Context scheduler_lock_context;
432
433  _Thread_State_acquire( thread, &state_lock_context );
434  scheduler = _Thread_Scheduler_get_home( thread );
435  _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
436
437  (*scheduler->Operations.block)(scheduler, thread, &scheduler_node->Base);
438
439  _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
440  _Thread_State_release( thread, &state_lock_context );
441}
442
443static void unblock_op(
444  Thread_Control *thread,
445  Scheduler_SMP_Node *scheduler_node
446)
447{
448  const Scheduler_Control *scheduler;
449  ISR_lock_Context state_lock_context;
450  ISR_lock_Context scheduler_lock_context;
451
452  _Thread_State_acquire( thread, &state_lock_context );
453  scheduler = _Thread_Scheduler_get_home( thread );
454  _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
455
456  (*scheduler->Operations.unblock)(
457    scheduler,
458    thread,
459    &scheduler_node->Base
460  );
461
462  _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
463  _Thread_State_release( thread, &state_lock_context );
464}
465
466static void test_case_unblock_op(
467  Thread_Control *executing,
468  Scheduler_SMP_Node *executing_node,
469  Thread_Control *other,
470  Scheduler_SMP_Node_state new_state
471)
472{
473  Per_CPU_Control *cpu_self;
474
475  cpu_self = _Thread_Dispatch_disable();
476
477  switch (new_state) {
478    case SCHEDULER_SMP_NODE_SCHEDULED:
479      change_priority(executing, 2, false);
480      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
481      break;
482    case SCHEDULER_SMP_NODE_READY:
483      change_priority(executing, 4, false);
484      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_READY);
485      break;
486    default:
487      rtems_test_assert(0);
488      break;
489  }
490
491  block_op(executing, executing_node);
492  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_BLOCKED);
493
494  unblock_op(executing, executing_node);
495  rtems_test_assert(executing_node->state == new_state);
496
497  switch (new_state) {
498    case SCHEDULER_SMP_NODE_SCHEDULED:
499    case SCHEDULER_SMP_NODE_READY:
500      break;
501    default:
502      rtems_test_assert(0);
503      break;
504  }
505
506  change_priority(executing, 1, true);
507  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
508
509  _Thread_Dispatch_enable( cpu_self );
510}
511
512static void test_unblock_op(void)
513{
514  rtems_status_code sc;
515  rtems_id task_id;
516  Thread_Control *executing;
517  Scheduler_SMP_Node *executing_node;
518  Thread_Control *other;
519  size_t i;
520
521  task_id = start_task(3);
522  executing = _Thread_Get_executing();
523  executing_node = get_scheduler_node(executing);
524
525  other = get_thread_by_id(task_id);
526
527  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
528    test_case_unblock_op(
529      executing,
530      executing_node,
531      other,
532      states[i]
533    );
534  }
535
536  sc = rtems_task_delete(task_id);
537  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
538}
539
540void Init(rtems_task_argument arg)
541{
542  rtems_resource_snapshot snapshot;
543  rtems_status_code sc;
544  rtems_id task_id;
545
546  TEST_BEGIN();
547
548  rtems_resource_snapshot_take(&snapshot);
549
550  sc = rtems_task_create(
551    rtems_build_name('T', 'A', 'S', 'K'),
552    255,
553    RTEMS_MINIMUM_STACK_SIZE,
554    RTEMS_DEFAULT_MODES,
555    RTEMS_DEFAULT_ATTRIBUTES,
556    &task_id
557  );
558  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
559
560  test_change_priority();
561  test_update_priority_op();
562  test_yield_op();
563  test_unblock_op();
564
565  sc = rtems_task_delete(task_id);
566  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
567
568  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
569
570  TEST_END();
571  rtems_test_exit(0);
572}
Note: See TracBrowser for help on using the repository browser.