File indexing completed on 2025-05-11 08:24:32
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
0029
0030
0031
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include "tmacros.h"
0041
0042 #include <sys/stat.h>
0043 #include <assert.h>
0044 #include <errno.h>
0045 #include <fcntl.h>
0046 #include <stdlib.h>
0047 #include <unistd.h>
0048
0049 #include <rtems.h>
0050 #include <rtems/bdbuf.h>
0051 #include <rtems/test-info.h>
0052
0053 const char rtems_test_name[] = "BLOCK 10";
0054
0055 #define ASSERT_SC(sc) assert((sc) == RTEMS_SUCCESSFUL)
0056
0057 #define PRIORITY_HIGH 1
0058
0059 #define PRIORITY_INIT 2
0060
0061 #define PRIORITY_MID 3
0062
0063 #define PRIORITY_SWAPOUT 4
0064
0065 #define PRIORITY_LOW 5
0066
0067 #define PRIORITY_IDLE 6
0068
0069 #define BLOCK_SIZE 1
0070
0071 #define BLOCK_COUNT 1
0072
0073 #define DISK_PATH "/disk"
0074
0075 typedef rtems_bdbuf_buffer *(*access_func)(char task);
0076
0077 typedef void (*release_func)(char task, rtems_bdbuf_buffer *bd);
0078
0079 static rtems_disk_device *dd;
0080
0081 static rtems_id task_id_init;
0082
0083 static rtems_id task_id_purger;
0084
0085 static rtems_id task_id_waiter;
0086
0087 static void set_task_prio(rtems_id task, rtems_task_priority prio)
0088 {
0089 rtems_status_code sc = RTEMS_SUCCESSFUL;
0090 rtems_task_priority cur = 0;
0091
0092 sc = rtems_task_set_priority(task, prio, &cur);
0093 ASSERT_SC(sc);
0094 }
0095
0096 static void suspend(rtems_id task)
0097 {
0098 rtems_status_code sc = RTEMS_SUCCESSFUL;
0099
0100 sc = rtems_task_suspend(task);
0101 ASSERT_SC(sc);
0102 }
0103
0104 static void resume(rtems_id task)
0105 {
0106 rtems_status_code sc = RTEMS_SUCCESSFUL;
0107
0108 sc = rtems_task_resume(task);
0109 ASSERT_SC(sc);
0110 }
0111
0112 static int disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
0113 {
0114 rtems_status_code sc = RTEMS_SUCCESSFUL;
0115
0116 if (req == RTEMS_BLKIO_REQUEST) {
0117 rtems_blkdev_request *r = arg;
0118
0119 if (r->req == RTEMS_BLKDEV_REQ_WRITE) {
0120 set_task_prio(RTEMS_SELF, PRIORITY_IDLE);
0121 set_task_prio(RTEMS_SELF, PRIORITY_SWAPOUT);
0122 }
0123
0124 rtems_blkdev_request_done(r, sc);
0125
0126 return 0;
0127 } else {
0128 return rtems_blkdev_ioctl(dd, req, arg);
0129 }
0130 }
0131
0132 static void disk_register(
0133 uint32_t block_size,
0134 rtems_blkdev_bnum block_count,
0135 rtems_disk_device **dd
0136 )
0137 {
0138 rtems_status_code sc = RTEMS_SUCCESSFUL;
0139 int fd;
0140 int rv;
0141
0142 sc = rtems_blkdev_create(
0143 DISK_PATH,
0144 block_size,
0145 block_count,
0146 disk_ioctl,
0147 NULL
0148 );
0149 ASSERT_SC(sc);
0150
0151 fd = open(DISK_PATH, O_RDWR);
0152 rtems_test_assert(fd >= 0);
0153
0154 rv = rtems_disk_fd_get_disk_device(fd, dd);
0155 rtems_test_assert(rv == 0);
0156
0157 rv = close(fd);
0158 rtems_test_assert(rv == 0);
0159 }
0160
0161 static rtems_bdbuf_buffer *do_get(char task)
0162 {
0163 rtems_status_code sc = RTEMS_SUCCESSFUL;
0164 rtems_bdbuf_buffer *bd = NULL;
0165
0166 printf("%c: try get\n", task);
0167
0168 sc = rtems_bdbuf_get(dd, 0, &bd);
0169 ASSERT_SC(sc);
0170
0171 printf("%c: get\n", task);
0172
0173 return bd;
0174 }
0175
0176 static rtems_bdbuf_buffer *do_get_mod(char task)
0177 {
0178 rtems_status_code sc = RTEMS_SUCCESSFUL;
0179 rtems_bdbuf_buffer *bd = NULL;
0180
0181 printf("%c: try get modified\n", task);
0182
0183 sc = rtems_bdbuf_get(dd, 0, &bd);
0184 ASSERT_SC(sc);
0185
0186 sc = rtems_bdbuf_release_modified(bd);
0187 ASSERT_SC(sc);
0188
0189 sc = rtems_bdbuf_get(dd, 0, &bd);
0190 ASSERT_SC(sc);
0191
0192 printf("%c: get modified\n", task);
0193
0194 return bd;
0195 }
0196
0197 static rtems_bdbuf_buffer *do_read(char task)
0198 {
0199 rtems_status_code sc = RTEMS_SUCCESSFUL;
0200 rtems_bdbuf_buffer *bd = NULL;
0201
0202 printf("%c: try read\n", task);
0203
0204 sc = rtems_bdbuf_read(dd, 0, &bd);
0205 ASSERT_SC(sc);
0206
0207 printf("%c: read\n", task);
0208
0209 return bd;
0210 }
0211
0212 static void do_rel(char task, rtems_bdbuf_buffer *bd)
0213 {
0214 rtems_status_code sc = RTEMS_SUCCESSFUL;
0215
0216 printf("%c: release\n", task);
0217
0218 sc = rtems_bdbuf_release(bd);
0219 ASSERT_SC(sc);
0220
0221 printf("%c: release done\n", task);
0222 }
0223
0224 static void do_rel_mod(char task, rtems_bdbuf_buffer *bd)
0225 {
0226 rtems_status_code sc = RTEMS_SUCCESSFUL;
0227
0228 printf("%c: release modified\n", task);
0229
0230 sc = rtems_bdbuf_release_modified(bd);
0231 ASSERT_SC(sc);
0232
0233 printf("%c: release modified done\n", task);
0234 }
0235
0236 static void do_sync(char task, rtems_bdbuf_buffer *bd)
0237 {
0238 rtems_status_code sc = RTEMS_SUCCESSFUL;
0239
0240 printf("%c: sync\n", task);
0241
0242 sc = rtems_bdbuf_sync(bd);
0243 ASSERT_SC(sc);
0244
0245 printf("%c: sync done\n", task);
0246 }
0247
0248 static void purge(char task)
0249 {
0250 printf("%c: purge\n", task);
0251
0252 rtems_bdbuf_purge_dev(dd);
0253 }
0254
0255 static void task_purger(rtems_task_argument arg)
0256 {
0257 while (true) {
0258 suspend(RTEMS_SELF);
0259
0260 set_task_prio(RTEMS_SELF, PRIORITY_HIGH);
0261
0262 purge('P');
0263 }
0264
0265 rtems_task_exit();
0266 }
0267
0268 static void activate_purger(rtems_task_priority prio)
0269 {
0270 set_task_prio(task_id_purger, prio);
0271 resume(task_id_purger);
0272 }
0273
0274 static void task_waiter(rtems_task_argument arg)
0275 {
0276 while (true) {
0277 rtems_bdbuf_buffer *bd = NULL;
0278
0279 suspend(RTEMS_SELF);
0280
0281 bd = do_get('W');
0282
0283 do_rel('W', bd);
0284 }
0285
0286 rtems_task_exit();
0287 }
0288
0289 static void create_waiter(void)
0290 {
0291 resume(task_id_waiter);
0292 set_task_prio(task_id_waiter, PRIORITY_IDLE);
0293 }
0294
0295 static void restore_waiter(void)
0296 {
0297 set_task_prio(task_id_waiter, PRIORITY_HIGH);
0298 }
0299
0300 static void check_access(access_func ac, release_func rel, bool waiter)
0301 {
0302 rtems_bdbuf_buffer *bd = (*ac)('I');
0303
0304 if (waiter) {
0305 create_waiter();
0306 }
0307
0308 purge('I');
0309
0310 (*rel)('I', bd);
0311
0312 if (waiter) {
0313 restore_waiter();
0314 }
0315 }
0316
0317 static void check_intermediate(release_func rel, bool waiter)
0318 {
0319 rtems_bdbuf_buffer *bd = do_read('I');
0320
0321 if (waiter) {
0322 create_waiter();
0323 }
0324
0325 (*rel)('I', bd);
0326
0327 purge('I');
0328
0329 if (waiter) {
0330 restore_waiter();
0331 }
0332 }
0333
0334 static void check_transfer(rtems_task_priority prio, bool waiter)
0335 {
0336 rtems_bdbuf_buffer *bd = do_read('I');
0337
0338 if (waiter) {
0339 create_waiter();
0340 }
0341
0342 activate_purger(prio);
0343
0344 do_sync('I', bd);
0345
0346 if (waiter) {
0347 restore_waiter();
0348 }
0349 }
0350
0351 static const bool waiter_table [] = {
0352 true,
0353 false
0354 };
0355
0356 static const access_func access_table [] = {
0357 do_get,
0358 do_get_mod,
0359 do_read
0360 };
0361
0362 static const release_func release_table [] = {
0363 do_rel,
0364 do_rel_mod,
0365 do_sync
0366 };
0367
0368 static const rtems_task_priority purger_table [] = {
0369 PRIORITY_MID,
0370 PRIORITY_LOW
0371 };
0372
0373 #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array [0]))
0374
0375 #define WAITER_COUNT ARRAY_COUNT(waiter_table)
0376
0377 #define ACCESS_COUNT ARRAY_COUNT(access_table)
0378
0379 #define RELEASE_COUNT ARRAY_COUNT(release_table)
0380
0381 #define PURGER_COUNT ARRAY_COUNT(purger_table)
0382
0383 static const char *waiter_assoc_table [WAITER_COUNT] = {
0384 "with waiter",
0385 "without waiter"
0386 };
0387
0388 static const char *access_assoc_table [ACCESS_COUNT] = {
0389 "get",
0390 "access modified",
0391 "read"
0392 };
0393
0394 static const char *release_assoc_table [RELEASE_COUNT] = {
0395 "release",
0396 "release modified",
0397 "sync"
0398 };
0399
0400 static const char *purger_assoc_table [PURGER_COUNT] = {
0401 "sync",
0402 "transfer"
0403 };
0404
0405 static rtems_task Init(rtems_task_argument argument)
0406 {
0407 rtems_status_code sc = RTEMS_SUCCESSFUL;
0408 size_t i_w = 0;
0409 size_t i_ac = 0;
0410 size_t i_rel = 0;
0411 size_t i_p = 0;
0412
0413 TEST_BEGIN();
0414
0415 task_id_init = rtems_task_self();
0416
0417 disk_register(BLOCK_SIZE, BLOCK_COUNT, &dd);
0418
0419 sc = rtems_task_create(
0420 rtems_build_name('P', 'U', 'R', 'G'),
0421 PRIORITY_HIGH,
0422 0,
0423 RTEMS_DEFAULT_MODES,
0424 RTEMS_DEFAULT_ATTRIBUTES,
0425 &task_id_purger
0426 );
0427 ASSERT_SC(sc);
0428
0429 sc = rtems_task_start(task_id_purger, task_purger, 0);
0430 ASSERT_SC(sc);
0431
0432 set_task_prio(task_id_purger, PRIORITY_LOW);
0433
0434 sc = rtems_task_create(
0435 rtems_build_name('W', 'A', 'I', 'T'),
0436 PRIORITY_HIGH,
0437 0,
0438 RTEMS_DEFAULT_MODES,
0439 RTEMS_DEFAULT_ATTRIBUTES,
0440 &task_id_waiter
0441 );
0442 ASSERT_SC(sc);
0443
0444 sc = rtems_task_start(task_id_waiter, task_waiter, 0);
0445 ASSERT_SC(sc);
0446
0447 for (i_ac = 0; i_ac < ACCESS_COUNT; ++i_ac) {
0448 for (i_rel = 0; i_rel < RELEASE_COUNT; ++i_rel) {
0449 for (i_w = 0; i_w < WAITER_COUNT; ++i_w) {
0450 printf("test case [access]: %s and %s %s\n", access_assoc_table [i_ac], release_assoc_table [i_rel], waiter_assoc_table [i_w]);
0451 check_access(access_table [i_ac], release_table [i_rel], waiter_table [i_w]);
0452 }
0453 }
0454 }
0455
0456 for (i_rel = 0; i_rel < RELEASE_COUNT; ++i_rel) {
0457 for (i_w = 0; i_w < WAITER_COUNT; ++i_w) {
0458 printf("test case [intermediate]: %s %s\n", release_assoc_table [i_rel], waiter_assoc_table [i_w]);
0459 check_intermediate(release_table [i_rel], waiter_table [i_w]);
0460 }
0461 }
0462
0463 for (i_p = 0; i_p < PURGER_COUNT; ++i_p) {
0464 for (i_w = 0; i_w < WAITER_COUNT; ++i_w) {
0465 printf("test case [transfer]: %s %s\n", purger_assoc_table [i_p], waiter_assoc_table [i_w]);
0466 check_transfer(purger_table [i_p], waiter_table [i_w]);
0467 }
0468 }
0469
0470 TEST_END();
0471
0472 exit(0);
0473 }
0474
0475 #define CONFIGURE_INIT
0476
0477 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0478 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0479 #define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
0480
0481 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
0482
0483 #define CONFIGURE_MAXIMUM_TASKS 3
0484
0485 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0486
0487 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0488
0489 #define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_INIT
0490 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
0491 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0492
0493 #define CONFIGURE_SWAPOUT_TASK_PRIORITY PRIORITY_SWAPOUT
0494
0495 #define CONFIGURE_BDBUF_BUFFER_MIN_SIZE BLOCK_SIZE
0496 #define CONFIGURE_BDBUF_BUFFER_MAX_SIZE BLOCK_SIZE
0497 #define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (BLOCK_SIZE * BLOCK_COUNT)
0498
0499 #include <rtems/confdefs.h>