File indexing completed on 2025-05-11 08:24:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include "tmacros.h"
0033
0034 #include <threads.h>
0035
0036 #include <rtems/malloc.h>
0037
0038 const char rtems_test_name[] = "SPSTDTHREADS 1";
0039
0040 #define US_PER_TICK 10000
0041
0042 #define EVENT_MTX_LOCK RTEMS_EVENT_0
0043
0044 #define EVENT_MTX_UNLOCK RTEMS_EVENT_1
0045
0046 #define EVENT_CND_WAIT RTEMS_EVENT_2
0047
0048 #define EVENT_CND_TIMEDWAIT RTEMS_EVENT_3
0049
0050 #define EVENT_TSS RTEMS_EVENT_4
0051
0052 typedef struct {
0053 rtems_id high;
0054 rtems_id low;
0055 once_flag once_flag;
0056 mtx_t mtx;
0057 cnd_t cnd;
0058 tss_t tss;
0059 thrd_t thrd;
0060 int generation;
0061 } test_context;
0062
0063 static test_context test_instance = {
0064 .once_flag = ONCE_FLAG_INIT
0065 };
0066
0067 static void next_generation(test_context *ctx)
0068 {
0069 ++ctx->generation;
0070 }
0071
0072 static void send_event(test_context *ctx, rtems_event_set events)
0073 {
0074 rtems_status_code sc;
0075
0076 sc = rtems_event_send(ctx->high, events);
0077 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0078 }
0079
0080 static void get_abs_timeout(struct timespec *to)
0081 {
0082 int rv;
0083
0084 rv = clock_gettime(CLOCK_REALTIME, to);
0085 rtems_test_assert(rv == 0);
0086
0087 to->tv_nsec += 2 * US_PER_TICK * 1000;
0088 if (to->tv_nsec >= 1000000000) {
0089 ++to->tv_sec;
0090 to->tv_nsec -= 1000000000;
0091 }
0092 }
0093
0094 static void test_init(test_context *ctx)
0095 {
0096 int status;
0097
0098 status = mtx_init(&ctx->mtx, mtx_plain);
0099 rtems_test_assert(status == thrd_success);
0100
0101 status = cnd_init(&ctx->cnd);
0102 rtems_test_assert(status == thrd_success);
0103 }
0104
0105 static void test_destroy(test_context *ctx)
0106 {
0107 mtx_destroy(&ctx->mtx);
0108 cnd_destroy(&ctx->cnd);
0109 }
0110
0111 static void once_func(void)
0112 {
0113 test_context *ctx = &test_instance;
0114
0115 next_generation(ctx);
0116 }
0117
0118 static void test_once(test_context *ctx)
0119 {
0120 int gen = ctx->generation;
0121
0122 call_once(&ctx->once_flag, once_func);
0123 rtems_test_assert(ctx->generation == gen + 1);
0124
0125 call_once(&ctx->once_flag, once_func);
0126 rtems_test_assert(ctx->generation == gen + 1);
0127 }
0128
0129 static void test_mtx(test_context *ctx)
0130 {
0131 mtx_t *mtx = &ctx->mtx;
0132 int gen = ctx->generation;
0133 struct timespec to;
0134 int status;
0135
0136 status = mtx_trylock(mtx);
0137 rtems_test_assert(status == thrd_success);
0138
0139 status = mtx_lock(mtx);
0140 rtems_test_assert(status == thrd_success);
0141
0142 get_abs_timeout(&to);
0143 status = mtx_timedlock(mtx, &to);
0144 rtems_test_assert(status == thrd_success);
0145
0146 status = mtx_unlock(mtx);
0147 rtems_test_assert(status == thrd_success);
0148
0149 status = mtx_unlock(mtx);
0150 rtems_test_assert(status == thrd_success);
0151
0152 status = mtx_unlock(mtx);
0153 rtems_test_assert(status == thrd_success);
0154
0155 send_event(ctx, EVENT_MTX_LOCK);
0156 rtems_test_assert(ctx->generation == gen + 1);
0157
0158 status = mtx_trylock(mtx);
0159 rtems_test_assert(status == thrd_busy);
0160
0161 memset(&to, 0xff, sizeof(to));
0162 status = mtx_timedlock(mtx, &to);
0163 rtems_test_assert(status == thrd_error);
0164
0165 get_abs_timeout(&to);
0166 status = mtx_timedlock(mtx, &to);
0167 rtems_test_assert(status == thrd_timedout);
0168
0169 send_event(ctx, EVENT_MTX_UNLOCK);
0170 rtems_test_assert(ctx->generation == gen + 2);
0171 }
0172
0173 static void test_cnd(test_context *ctx)
0174 {
0175 cnd_t *cnd = &ctx->cnd;
0176 mtx_t *mtx = &ctx->mtx;
0177 int gen = ctx->generation;
0178 struct timespec to;
0179 int status;
0180
0181 send_event(ctx, EVENT_CND_WAIT);
0182 rtems_test_assert(ctx->generation == gen + 1);
0183
0184 status = mtx_lock(mtx);
0185 rtems_test_assert(status == thrd_success);
0186
0187 status = cnd_signal(cnd);
0188 rtems_test_assert(status == thrd_success);
0189
0190 status = mtx_unlock(mtx);
0191 rtems_test_assert(status == thrd_success);
0192 rtems_test_assert(ctx->generation == gen + 2);
0193
0194 send_event(ctx, EVENT_CND_WAIT);
0195 rtems_test_assert(ctx->generation == gen + 3);
0196
0197 status = mtx_lock(mtx);
0198 rtems_test_assert(status == thrd_success);
0199
0200 status = cnd_broadcast(cnd);
0201 rtems_test_assert(status == thrd_success);
0202
0203 status = mtx_unlock(mtx);
0204 rtems_test_assert(status == thrd_success);
0205 rtems_test_assert(ctx->generation == gen + 4);
0206
0207 status = mtx_lock(mtx);
0208 rtems_test_assert(status == thrd_success);
0209
0210 memset(&to, 0xff, sizeof(to));
0211 status = cnd_timedwait(cnd, mtx, &to);
0212 rtems_test_assert(status == thrd_error);
0213
0214 get_abs_timeout(&to);
0215 status = cnd_timedwait(cnd, mtx, &to);
0216 rtems_test_assert(status == thrd_timedout);
0217
0218 status = mtx_unlock(mtx);
0219 rtems_test_assert(status == thrd_success);
0220
0221 send_event(ctx, EVENT_CND_TIMEDWAIT);
0222 rtems_test_assert(ctx->generation == gen + 5);
0223
0224 status = mtx_lock(mtx);
0225 rtems_test_assert(status == thrd_success);
0226
0227 status = cnd_signal(cnd);
0228 rtems_test_assert(status == thrd_success);
0229
0230 status = mtx_unlock(mtx);
0231 rtems_test_assert(status == thrd_success);
0232 rtems_test_assert(ctx->generation == gen + 6);
0233 }
0234
0235 static int tss_val = TSS_DTOR_ITERATIONS;
0236
0237 static void tss_dtor(void *val)
0238 {
0239 test_context *ctx = &test_instance;
0240
0241 rtems_test_assert(val == &tss_val);
0242 next_generation(ctx);
0243 }
0244
0245 static void test_tss(test_context *ctx)
0246 {
0247 tss_dtor_t dtor = tss_dtor;
0248 int gen = ctx->generation;
0249 int status;
0250
0251 status = tss_create(&ctx->tss, dtor);
0252 rtems_test_assert(status == thrd_success);
0253
0254 send_event(ctx, EVENT_TSS);
0255 rtems_test_assert(ctx->generation == gen + 1);
0256
0257 tss_delete(ctx->tss);
0258 }
0259
0260 static int thrd(void *arg)
0261 {
0262 thrd_exit(123);
0263 }
0264
0265 static void test_thrd(test_context *ctx)
0266 {
0267 thrd_start_t thrd_start = thrd;
0268 int status;
0269 int exit_status;
0270 struct timespec duration;
0271 struct timespec remaining;
0272 void *greedy;
0273
0274 rtems_test_assert(thrd_equal(rtems_task_self(), thrd_current()));
0275
0276 thrd_yield();
0277
0278 memset(&duration, 0, sizeof(duration));
0279 duration.tv_nsec = 1;
0280 thrd_sleep(&duration, &remaining);
0281 rtems_test_assert(remaining.tv_sec == 0);
0282 rtems_test_assert(remaining.tv_nsec == 0);
0283
0284 greedy = rtems_heap_greedy_allocate(NULL, 0);
0285 status = thrd_create(&ctx->thrd, thrd_start, ctx);
0286 rtems_test_assert(status == thrd_nomem);
0287 rtems_heap_greedy_free(greedy);
0288
0289 status = thrd_create(&ctx->thrd, thrd_start, ctx);
0290 rtems_test_assert(status == thrd_success);
0291
0292 status = thrd_create(&ctx->thrd, thrd_start, ctx);
0293 rtems_test_assert(status == thrd_error);
0294
0295 exit_status = 0;
0296 status = thrd_join(ctx->thrd, &exit_status);
0297 rtems_test_assert(status == thrd_success);
0298 rtems_test_assert(exit_status == 123);
0299
0300 status = thrd_detach(thrd_current());
0301 rtems_test_assert(status == thrd_success);
0302
0303 status = thrd_detach(11235);
0304 rtems_test_assert(status == thrd_error);
0305 }
0306
0307 static void high_task(rtems_task_argument idx)
0308 {
0309 test_context *ctx = &test_instance;
0310
0311 while (true) {
0312 rtems_event_set events;
0313 rtems_status_code sc;
0314 int status;
0315
0316 sc = rtems_event_receive(
0317 RTEMS_ALL_EVENTS,
0318 RTEMS_EVENT_ANY | RTEMS_WAIT,
0319 RTEMS_NO_TIMEOUT,
0320 &events
0321 );
0322 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0323
0324 if ((events & EVENT_MTX_LOCK) != 0) {
0325 status = mtx_lock(&ctx->mtx);
0326 rtems_test_assert(status == thrd_success);
0327 next_generation(ctx);
0328 }
0329
0330 if ((events & EVENT_MTX_UNLOCK) != 0) {
0331 status = mtx_unlock(&ctx->mtx);
0332 rtems_test_assert(status == thrd_success);
0333 next_generation(ctx);
0334 }
0335
0336 if ((events & EVENT_CND_WAIT) != 0) {
0337 status = mtx_lock(&ctx->mtx);
0338 rtems_test_assert(status == thrd_success);
0339 next_generation(ctx);
0340
0341 status = cnd_wait(&ctx->cnd, &ctx->mtx);
0342 rtems_test_assert(status == thrd_success);
0343 next_generation(ctx);
0344
0345 status = mtx_unlock(&ctx->mtx);
0346 rtems_test_assert(status == thrd_success);
0347 }
0348
0349 if ((events & EVENT_CND_TIMEDWAIT) != 0) {
0350 struct timespec to;
0351
0352 status = mtx_lock(&ctx->mtx);
0353 rtems_test_assert(status == thrd_success);
0354 next_generation(ctx);
0355
0356 get_abs_timeout(&to);
0357 status = cnd_timedwait(&ctx->cnd, &ctx->mtx, &to);
0358 rtems_test_assert(status == thrd_success);
0359 next_generation(ctx);
0360
0361 status = mtx_unlock(&ctx->mtx);
0362 rtems_test_assert(status == thrd_success);
0363 }
0364
0365 if ((events & EVENT_TSS) != 0) {
0366 void *val;
0367
0368 status = tss_set(ctx->tss, &tss_val);
0369 rtems_test_assert(status == thrd_success);
0370
0371 val = tss_get(ctx->tss);
0372 rtems_test_assert(val == &tss_val);
0373
0374 rtems_task_exit();
0375 rtems_test_assert(0);
0376 }
0377 }
0378 }
0379
0380 static void test(void)
0381 {
0382 test_context *ctx = &test_instance;
0383 rtems_status_code sc;
0384
0385 test_init(ctx);
0386
0387 ctx->low = rtems_task_self();
0388
0389 sc = rtems_task_create(
0390 rtems_build_name('H', 'I', 'G', 'H'),
0391 1,
0392 RTEMS_MINIMUM_STACK_SIZE,
0393 RTEMS_DEFAULT_MODES,
0394 RTEMS_DEFAULT_ATTRIBUTES,
0395 &ctx->high
0396 );
0397 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0398
0399 sc = rtems_task_start(ctx->high, high_task, 0);
0400 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0401
0402 test_once(ctx);
0403 test_mtx(ctx);
0404 test_cnd(ctx);
0405 test_tss(ctx);
0406 test_thrd(ctx);
0407 test_destroy(ctx);
0408 }
0409
0410 static void Init(rtems_task_argument arg)
0411 {
0412 TEST_BEGIN();
0413
0414 test();
0415
0416 TEST_END();
0417 rtems_test_exit(0);
0418 }
0419
0420 #define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
0421
0422 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0423 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0424
0425 #define CONFIGURE_MAXIMUM_TASKS 4
0426
0427 #define CONFIGURE_MAXIMUM_POSIX_KEYS 1
0428 #define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 1
0429 #define CONFIGURE_MAXIMUM_POSIX_THREADS 1
0430
0431 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0432
0433 #define CONFIGURE_INIT_TASK_PRIORITY 4
0434 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0435
0436 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0437
0438 #define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e')
0439
0440 #define CONFIGURE_INIT
0441
0442 #include <rtems/confdefs.h>