source: rtems/testsuites/validation/tc-score-thread.c @ c821b92

Last change on this file since c821b92 was c821b92, checked in by Sebastian Huber <sebastian.huber@…>, on 11/22/22 at 18:09:12

validation: Test the global construction

Update #3716.

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup ScoreThreadValThread
7 */
8
9/*
10 * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * This file is part of the RTEMS quality process and was automatically
36 * generated.  If you find something that needs to be fixed or
37 * worded better please post a report or patch to an RTEMS mailing list
38 * or raise a bug report:
39 *
40 * https://www.rtems.org/bugs.html
41 *
42 * For information on updating and regenerating please refer to the How-To
43 * section in the Software Requirements Engineering chapter of the
44 * RTEMS Software Engineering manual.  The manual is provided as a part of
45 * a release.  For development sources please refer to the online
46 * documentation at:
47 *
48 * https://docs.rtems.org
49 */
50
51#ifdef HAVE_CONFIG_H
52#include "config.h"
53#endif
54
55#include <rtems.h>
56#include <rtems/score/statesimpl.h>
57#include <rtems/score/threadimpl.h>
58
59#include "ts-config.h"
60#include "tx-support.h"
61
62#include <rtems/test.h>
63
64/**
65 * @defgroup ScoreThreadValThread spec:/score/thread/val/thread
66 *
67 * @ingroup TestsuitesValidationNoClock0
68 *
69 * @brief Tests general thread behaviour.
70 *
71 * This test case performs the following actions:
72 *
73 * - Create an extension set with a thread terminate extension which deletes
74 *   the killer task if it is invoked for the worker task.  Create and start
75 *   the worker task.  Create and start the killer task.  The killer task
76 *   deletes the worker task.
77 *
78 *   - Check that the killer task was deleted.
79 *
80 *   - Check that the worker task still exists.
81 *
82 *   - Check that the life of the worker task is protected and terminating.
83 *
84 *   - Check that the worker task is waiting for a joining thread.
85 *
86 *   - Delete the worker task using brute force.
87 *
88 *   - Clean up all used resources.
89 *
90 * - Delete a thread which least recently used the floating point coprocessor.
91 *
92 *   - Start the worker thread.  Let it use the floating point coprocessor.
93 *
94 *   - Delete the worker thread and free the thread resources.
95 *
96 *   - Clean up all used resources.
97 *
98 * - Validate the global construction.  Mark that the test case executed.
99 *
100 *   - Check that the global constructor was called exactly once.
101 *
102 *   - Check that the global construction was done by the Classic API user
103 *     initialization task.
104 *
105 *   - Check that the global constructor was called before the task entry.
106 *
107 * @{
108 */
109
110/**
111 * @brief Test context for spec:/score/thread/val/thread test case.
112 */
113typedef struct {
114  /**
115   * @brief This member contains the worker task identifier.
116   */
117  rtems_id worker_id;
118
119  /**
120   * @brief This member contains the killer task identifier.
121   */
122  rtems_id killer_id;
123
124  /**
125   * @brief This member contains a floating-point object.
126   */
127  volatile double fp_obj;
128} ScoreThreadValThread_Context;
129
130static ScoreThreadValThread_Context
131  ScoreThreadValThread_Instance;
132
133typedef ScoreThreadValThread_Context Context;
134
135static bool test_case_executed;
136
137static bool constructor_test_case_executed;
138
139static uint32_t constructor_calls;
140
141static rtems_id constructor_id;
142
143static __attribute__(( __constructor__ )) void Constructor( void )
144{
145  constructor_test_case_executed = test_case_executed;
146  ++constructor_calls;
147  constructor_id = rtems_task_self();
148}
149
150static void TaskTerminate( rtems_tcb *executing )
151{
152  Context *ctx;
153
154  ctx = T_fixture_context();
155
156  if ( ctx->worker_id == executing->Object.id ) {
157    DeleteTask( ctx->killer_id );
158  }
159}
160
161static void WorkerTask( rtems_task_argument arg )
162{
163  (void) arg;
164  SuspendSelf();
165}
166
167static void GoBackToRunner( void *arg )
168{
169  Context *ctx;
170
171  ctx = arg;
172  SetPriority( ctx->worker_id, PRIO_LOW );
173}
174
175static void FloatingPointTask( rtems_task_argument arg )
176{
177  Context *ctx;
178
179  ctx = (Context *) arg;
180  ctx->fp_obj *= 1.23;
181
182  /*
183   * We use an interrupt to go back to the runner since on some
184   * architectures, the floating-point context is only saved during interrupt
185   * processing and not for synchronous thread switches.
186   */
187  CallWithinISR( GoBackToRunner, ctx );
188}
189
190static void KillerTask( rtems_task_argument arg )
191{
192  Context *ctx;
193
194  ctx = (Context *) arg;
195  DeleteTask( ctx->worker_id );
196}
197
198static T_fixture ScoreThreadValThread_Fixture = {
199  .setup = NULL,
200  .stop = NULL,
201  .teardown = NULL,
202  .scope = NULL,
203  .initial_context = &ScoreThreadValThread_Instance
204};
205
206/**
207 * @brief Create an extension set with a thread terminate extension which
208 *   deletes the killer task if it is invoked for the worker task.  Create and
209 *   start the worker task.  Create and start the killer task.  The killer task
210 *   deletes the worker task.
211 */
212static void ScoreThreadValThread_Action_0( ScoreThreadValThread_Context *ctx )
213{
214  rtems_extensions_table table = {
215    .thread_terminate = TaskTerminate
216  };
217  rtems_status_code sc;
218  rtems_id          id;
219  rtems_tcb        *worker_tcb;
220
221  sc = rtems_extension_create(
222    rtems_build_name( 'T', 'E', 'S', 'T' ),
223    &table,
224    &id
225  );
226  T_rsc_success( sc );
227
228  SetSelfPriority( PRIO_NORMAL );
229  ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
230  worker_tcb = GetThread( ctx->worker_id );
231  StartTask( ctx->worker_id, WorkerTask, NULL );
232  ctx->killer_id = CreateTask( "KILL", PRIO_HIGH );
233  StartTask( ctx->killer_id, KillerTask, ctx );
234
235  /*
236   * Check that the killer task was deleted.
237   */
238  sc = rtems_event_send( ctx->killer_id, RTEMS_EVENT_0 );
239  T_rsc( sc, RTEMS_INVALID_ID );
240
241  /*
242   * Check that the worker task still exists.
243   */
244  sc = rtems_event_send( ctx->worker_id, RTEMS_EVENT_0 );
245  T_rsc_success( sc );
246
247  /*
248   * Check that the life of the worker task is protected and terminating.
249   */
250  T_eq_int(
251    worker_tcb->Life.state,
252    THREAD_LIFE_PROTECTED | THREAD_LIFE_TERMINATING
253  );
254
255  /*
256   * Check that the worker task is waiting for a joining thread.
257   */
258  T_eq_u32(
259    worker_tcb->current_state,
260    STATES_WAITING_FOR_JOIN_AT_EXIT
261  );
262
263  /*
264   * Delete the worker task using brute force.
265   */
266  worker_tcb->Life.state = THREAD_LIFE_DETACHED |
267    THREAD_LIFE_PROTECTED | THREAD_LIFE_TERMINATING;
268  _Thread_Clear_state( worker_tcb, STATES_WAITING_FOR_JOIN_AT_EXIT );
269
270  /*
271   * Clean up all used resources.
272   */
273  KillZombies();
274  RestoreRunnerPriority();
275
276  sc = rtems_extension_delete( id );
277  T_rsc_success( sc );
278}
279
280/**
281 * @brief Delete a thread which least recently used the floating point
282 *   coprocessor.
283 */
284static void ScoreThreadValThread_Action_1( ScoreThreadValThread_Context *ctx )
285{
286  rtems_status_code sc;
287
288  SetSelfPriority( PRIO_NORMAL );
289  sc = rtems_task_create(
290    rtems_build_name( 'W', 'O', 'R', 'K'),
291    PRIO_HIGH,
292    TEST_MINIMUM_STACK_SIZE,
293    RTEMS_DEFAULT_MODES,
294    RTEMS_FLOATING_POINT,
295    &ctx->worker_id
296  );
297  T_rsc_success( sc );
298
299  /*
300   * Start the worker thread.  Let it use the floating point coprocessor.
301   */
302  StartTask( ctx->worker_id, FloatingPointTask, ctx );
303
304  /*
305   * Delete the worker thread and free the thread resources.
306   */
307  DeleteTask( ctx->worker_id );
308  KillZombies();
309
310  /*
311   * Clean up all used resources.
312   */
313  RestoreRunnerPriority();
314}
315
316/**
317 * @brief Validate the global construction.  Mark that the test case executed.
318 */
319static void ScoreThreadValThread_Action_2( ScoreThreadValThread_Context *ctx )
320{
321  test_case_executed = true;
322
323  /*
324   * Check that the global constructor was called exactly once.
325   */
326  T_eq_u32( constructor_calls, 1 );
327
328  /*
329   * Check that the global construction was done by the Classic API user
330   * initialization task.
331   */
332  T_eq_u32( constructor_id, rtems_task_self() );
333
334  /*
335   * Check that the global constructor was called before the task entry.
336   */
337  T_false( constructor_test_case_executed );
338}
339
340/**
341 * @fn void T_case_body_ScoreThreadValThread( void )
342 */
343T_TEST_CASE_FIXTURE( ScoreThreadValThread, &ScoreThreadValThread_Fixture )
344{
345  ScoreThreadValThread_Context *ctx;
346
347  ctx = T_fixture_context();
348
349  ScoreThreadValThread_Action_0( ctx );
350  ScoreThreadValThread_Action_1( ctx );
351  ScoreThreadValThread_Action_2( ctx );
352}
353
354/** @} */
Note: See TracBrowser for help on using the repository browser.