Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:49

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <rtems.h>
0033 #include <rtems/libcsupport.h>
0034 
0035 #include <rtems/score/threadimpl.h>
0036 
0037 #include "tmacros.h"
0038 
0039 #define PRIO_INIT 1
0040 #define PRIO_HIGH 2
0041 #define PRIO_MID 3
0042 #define PRIO_LOW 4
0043 #define PRIO_VERY_LOW 5
0044 
0045 const char rtems_test_name[] = "SPTHREADLIFE 1";
0046 
0047 typedef enum {
0048   INIT,
0049   SET_PRIO,
0050   SET_PRIO_DONE,
0051   DO_OBTAIN_0,
0052   OBTAIN_DONE_0,
0053   DO_RELEASE_0,
0054   RELEASE_DONE_0,
0055   DO_OBTAIN_1,
0056   OBTAIN_DONE_1,
0057   RESTART_0,
0058   RESTART_1,
0059   RESTART_2,
0060   RESTART_3,
0061   DO_RELEASE_1,
0062   RELEASE_DONE_1,
0063   DELETE_0,
0064   DELETE_1,
0065   DELETE_2,
0066   DELETE_3,
0067   SET_PROTECTION,
0068   SET_PROTECTION_DONE,
0069   CLEAR_PROTECTION,
0070   DELETE_4,
0071   DELETE_5,
0072   DELETE_6,
0073   DELETE_SELF,
0074   DELETE_7,
0075   DELETE_8,
0076   DELETE_9,
0077   EXIT_0,
0078   EXIT_1,
0079   EXIT_2,
0080   EXIT_3,
0081   INVALID
0082 } test_state;
0083 
0084 typedef struct {
0085   rtems_id main_task_id;
0086   rtems_id worker_task_id;
0087   rtems_id sema_id;
0088   test_state current;
0089   test_state next;
0090 } test_context;
0091 
0092 static test_context test_instance;
0093 
0094 static void wake_up_main(const test_context *ctx)
0095 {
0096   rtems_status_code sc;
0097 
0098   sc = rtems_event_transient_send(ctx->main_task_id);
0099   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0100 }
0101 
0102 static void wait(void)
0103 {
0104   rtems_status_code sc;
0105 
0106   sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0107   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0108 }
0109 
0110 static void change_state(
0111   test_context *ctx,
0112   test_state expected,
0113   test_state current,
0114   test_state next
0115 )
0116 {
0117   rtems_test_assert(ctx->current == expected);
0118   ctx->current = current;
0119   ctx->next = next;
0120 }
0121 
0122 static void change_state_and_wait(
0123   test_context *ctx,
0124   test_state expected,
0125   test_state current,
0126   test_state next
0127 )
0128 {
0129   change_state(ctx, expected, current, next);
0130   wait();
0131 }
0132 
0133 static void set_priority(rtems_task_priority prio)
0134 {
0135   rtems_status_code sc;
0136 
0137   sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
0138   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0139 }
0140 
0141 static void assert_priority(rtems_task_priority expected)
0142 {
0143   rtems_status_code sc;
0144   rtems_task_priority prio;
0145 
0146   sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
0147   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0148 
0149   rtems_test_assert(prio == expected);
0150 }
0151 
0152 static void restart_extension(
0153   Thread_Control *executing,
0154   Thread_Control *restarted
0155 )
0156 {
0157   test_context *ctx = &test_instance;
0158   rtems_status_code sc;
0159 
0160   rtems_test_assert(executing == restarted);
0161 
0162   switch (ctx->current) {
0163     case RESTART_0:
0164       rtems_test_assert(ctx->worker_task_id == rtems_task_self());
0165       ctx->current = RESTART_1;
0166       sc = rtems_task_restart(RTEMS_SELF, 0);
0167       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0168       break;
0169     case RESTART_1:
0170       rtems_test_assert(ctx->worker_task_id == rtems_task_self());
0171       ctx->current = RESTART_2;
0172       break;
0173     default:
0174       rtems_test_assert(0);
0175       break;
0176   }
0177 }
0178 
0179 static void delete_extension(
0180   Thread_Control *executing,
0181   Thread_Control *deleted
0182 )
0183 {
0184   test_context *ctx = &test_instance;
0185 
0186   rtems_test_assert(executing != deleted);
0187   rtems_test_assert(ctx->main_task_id == rtems_task_self());
0188 
0189   switch (ctx->current) {
0190     case DELETE_2:
0191       assert_priority(PRIO_INIT);
0192       ctx->current = DELETE_3;
0193       break;
0194     case DELETE_5:
0195       assert_priority(PRIO_INIT);
0196       ctx->current = DELETE_6;
0197       break;
0198     case DELETE_8:
0199       assert_priority(PRIO_VERY_LOW);
0200       ctx->current = DELETE_9;
0201       break;
0202     case EXIT_2:
0203       assert_priority(PRIO_VERY_LOW);
0204       ctx->current = EXIT_3;
0205       break;
0206     default:
0207       rtems_test_assert(0);
0208       break;
0209   }
0210 }
0211 
0212 static void terminate_extension(Thread_Control *executing)
0213 {
0214   test_context *ctx = &test_instance;
0215 
0216   rtems_test_assert(ctx->worker_task_id == rtems_task_self());
0217 
0218   switch (ctx->current) {
0219     case DELETE_0:
0220       assert_priority(PRIO_INIT);
0221       ctx->current = DELETE_1;
0222       rtems_task_delete(RTEMS_SELF);
0223       rtems_test_assert(0);
0224       break;
0225     case DELETE_1:
0226       assert_priority(PRIO_INIT);
0227       ctx->current = DELETE_2;
0228       break;
0229     case DELETE_4:
0230       assert_priority(PRIO_INIT);
0231       ctx->current = DELETE_5;
0232       break;
0233     case DELETE_7:
0234       assert_priority(PRIO_LOW);
0235       ctx->current = DELETE_8;
0236       break;
0237     case EXIT_1:
0238       assert_priority(PRIO_LOW);
0239       ctx->current = EXIT_2;
0240       break;
0241     default:
0242       rtems_test_assert(0);
0243       break;
0244   }
0245 }
0246 
0247 static void worker_task(rtems_task_argument arg)
0248 {
0249   test_context *ctx = &test_instance;
0250 
0251   while (true) {
0252     test_state state = ctx->current;
0253     rtems_status_code sc;
0254     Thread_Life_state previous_thread_life_state;
0255     Per_CPU_Control *cpu_self;
0256 
0257     switch (state) {
0258       case SET_PRIO:
0259         assert_priority(PRIO_LOW);
0260         set_priority(PRIO_MID);
0261         break;
0262       case DO_OBTAIN_0:
0263       case DO_OBTAIN_1:
0264         assert_priority(PRIO_MID);
0265         sc = rtems_semaphore_obtain(
0266           ctx->sema_id,
0267           RTEMS_WAIT,
0268           RTEMS_NO_TIMEOUT
0269         );
0270         rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0271         assert_priority(PRIO_HIGH);
0272         break;
0273       case DO_RELEASE_0:
0274       case DO_RELEASE_1:
0275         assert_priority(PRIO_HIGH);
0276         sc = rtems_semaphore_release(ctx->sema_id);
0277         rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0278 
0279         switch (state) {
0280           case DO_RELEASE_0:
0281             assert_priority(PRIO_MID);
0282             break;
0283           case DO_RELEASE_1:
0284             assert_priority(PRIO_LOW);
0285             break;
0286           default:
0287             rtems_test_assert(0);
0288             break;
0289         }
0290 
0291         break;
0292       case RESTART_2:
0293         assert_priority(PRIO_HIGH);
0294         break;
0295       case SET_PROTECTION:
0296         cpu_self = _Thread_Dispatch_disable();
0297         previous_thread_life_state =
0298           _Thread_Set_life_protection(THREAD_LIFE_PROTECTED);
0299         rtems_test_assert(
0300           (previous_thread_life_state & THREAD_LIFE_PROTECTED) == 0
0301         );
0302         _Thread_Dispatch_enable(cpu_self);
0303         break;
0304       case CLEAR_PROTECTION:
0305         cpu_self = _Thread_Dispatch_disable();
0306         previous_thread_life_state = _Thread_Set_life_protection(0);
0307         rtems_test_assert(
0308           (previous_thread_life_state & THREAD_LIFE_PROTECTED) != 0
0309         );
0310         ctx->current = DELETE_4;
0311         _Thread_Dispatch_enable(cpu_self);
0312         break;
0313       case DELETE_SELF:
0314         ctx->current = DELETE_7;
0315         rtems_task_delete(RTEMS_SELF);
0316         rtems_test_assert(0);
0317         break;
0318       case EXIT_0:
0319         ctx->current = EXIT_1;
0320         rtems_task_exit();
0321         rtems_test_assert(0);
0322         break;
0323       default:
0324         rtems_test_assert(0);
0325         break;
0326     }
0327 
0328     ctx->current = ctx->next;
0329     wake_up_main(ctx);
0330   }
0331 }
0332 
0333 static void create_sema(test_context *ctx)
0334 {
0335   rtems_status_code sc;
0336 
0337   sc = rtems_semaphore_create(
0338     rtems_build_name('S', 'E', 'M', 'A'),
0339     1,
0340     RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
0341     PRIO_HIGH,
0342     &ctx->sema_id
0343   );
0344   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0345 }
0346 
0347 static void create_and_start_worker(test_context *ctx)
0348 {
0349   rtems_status_code sc;
0350 
0351   sc = rtems_task_create(
0352     rtems_build_name('W', 'O', 'R', 'K'),
0353     PRIO_LOW,
0354     RTEMS_MINIMUM_STACK_SIZE,
0355     RTEMS_DEFAULT_MODES,
0356     RTEMS_DEFAULT_ATTRIBUTES,
0357     &ctx->worker_task_id
0358   );
0359   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0360 
0361   sc = rtems_task_start(ctx->worker_task_id, worker_task, 0);
0362   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0363 }
0364 
0365 static void test(void)
0366 {
0367   test_context *ctx = &test_instance;
0368   rtems_status_code sc;
0369   rtems_resource_snapshot snapshot;
0370 
0371   ctx->main_task_id = rtems_task_self();
0372 
0373   rtems_resource_snapshot_take(&snapshot);
0374 
0375   create_sema(ctx);
0376   create_and_start_worker(ctx);
0377 
0378   change_state_and_wait(ctx, INIT, SET_PRIO, SET_PRIO_DONE);
0379   change_state_and_wait(ctx, SET_PRIO_DONE, DO_OBTAIN_0, OBTAIN_DONE_0);
0380 
0381   sc = rtems_semaphore_delete(ctx->sema_id);
0382   rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
0383 
0384   change_state_and_wait(ctx, OBTAIN_DONE_0, DO_RELEASE_0, RELEASE_DONE_0);
0385 
0386   sc = rtems_semaphore_delete(ctx->sema_id);
0387   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0388 
0389   create_sema(ctx);
0390 
0391   change_state_and_wait(ctx, RELEASE_DONE_0, DO_OBTAIN_1, OBTAIN_DONE_1);
0392 
0393   sc = rtems_semaphore_delete(ctx->sema_id);
0394   rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
0395 
0396   sc = rtems_task_restart(ctx->worker_task_id, 0);
0397   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0398 
0399   change_state_and_wait(ctx, OBTAIN_DONE_1, RESTART_0, RESTART_3);
0400   change_state_and_wait(ctx, RESTART_3, DO_RELEASE_1, RELEASE_DONE_1);
0401 
0402   sc = rtems_semaphore_delete(ctx->sema_id);
0403   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0404 
0405   change_state(ctx, RELEASE_DONE_1, DELETE_0, INVALID);
0406 
0407   sc = rtems_task_delete(ctx->worker_task_id);
0408   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0409 
0410   rtems_test_assert(ctx->current == DELETE_2);
0411 
0412   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0413 
0414   create_and_start_worker(ctx);
0415 
0416   change_state_and_wait(ctx, DELETE_3, SET_PROTECTION, SET_PROTECTION_DONE);
0417   change_state(ctx, SET_PROTECTION_DONE, CLEAR_PROTECTION, INVALID);
0418 
0419   sc = rtems_task_delete(ctx->worker_task_id);
0420   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0421 
0422   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0423 
0424   create_and_start_worker(ctx);
0425 
0426   change_state(ctx, DELETE_6, DELETE_SELF, INVALID);
0427   set_priority(PRIO_VERY_LOW);
0428 
0429   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0430   set_priority(PRIO_INIT);
0431 
0432   create_and_start_worker(ctx);
0433 
0434   change_state(ctx, DELETE_9, EXIT_0, INVALID);
0435   set_priority(PRIO_VERY_LOW);
0436 
0437   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0438   set_priority(PRIO_INIT);
0439 
0440   rtems_test_assert(ctx->current == EXIT_3);
0441 }
0442 
0443 static void Init(rtems_task_argument arg)
0444 {
0445   TEST_BEGIN();
0446 
0447   test();
0448 
0449   TEST_END();
0450   rtems_test_exit(0);
0451 }
0452 
0453 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0454 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0455 
0456 #define CONFIGURE_MAXIMUM_TASKS 2
0457 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0458 
0459 #define CONFIGURE_INITIAL_EXTENSIONS \
0460   { \
0461     .thread_restart = restart_extension, \
0462     .thread_delete = delete_extension, \
0463     .thread_terminate = terminate_extension \
0464   }, \
0465   RTEMS_TEST_INITIAL_EXTENSION
0466 
0467 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0468 
0469 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0470 
0471 #define CONFIGURE_INIT
0472 
0473 #include <rtems/confdefs.h>