Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup test_bdbuf
0007  *
0008  * @brief Bdbuf test.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2009, 2018 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039 
0040 #include <sys/stat.h>
0041 #include <errno.h>
0042 #include <fcntl.h>
0043 #include <stdarg.h>
0044 
0045 #include <rtems.h>
0046 #include <rtems/bspIo.h>
0047 #include <rtems/bdbuf.h>
0048 #include <rtems/blkdev.h>
0049 
0050 #include <tmacros.h>
0051 
0052 const char rtems_test_name[] = "BLOCK 5";
0053 
0054 /* forward declarations to avoid warnings */
0055 static rtems_task Init(rtems_task_argument argument);
0056 
0057 #define ASSERT_SC(sc) rtems_test_assert((sc) == RTEMS_SUCCESSFUL)
0058 
0059 #define PRIORITY_INIT 1
0060 
0061 #define PRIORITY_HIGH 2
0062 
0063 #define PRIORITY_LOW_ALT 3
0064 
0065 #define PRIORITY_SWAPOUT 4
0066 
0067 #define PRIORITY_LOW 5
0068 
0069 #define PRIORITY_RESUME 6
0070 
0071 #define BLOCK_SIZE_A 1
0072 
0073 #define BLOCK_COUNT_A 2
0074 
0075 #define BLOCK_SIZE_B 2
0076 
0077 #define BLOCK_COUNT_B 1
0078 
0079 /* In case of trouble change this to 1 or 2 for more output */
0080 static unsigned output_level = 0;
0081 
0082 static rtems_disk_device *dd_a;
0083 
0084 static rtems_disk_device *dd_b;
0085 
0086 static rtems_id task_id_init;
0087 
0088 static rtems_id task_id_low;
0089 
0090 static rtems_id task_id_high;
0091 
0092 static rtems_id task_id_resume;
0093 
0094 static volatile bool finish_low;
0095 
0096 static volatile bool finish_high;
0097 
0098 static volatile enum resume_style {
0099   RESUME_IMMEDIATE,
0100   RESUME_FINISH
0101 } resume;
0102 
0103 static volatile enum trig_style {
0104   SUSP = 0,
0105   CONT
0106 } trig;
0107 
0108 static volatile enum get_type {
0109   GET = 0,
0110   READ
0111 } trig_get, low_get, high_get;
0112 
0113 static volatile enum blk_kind {
0114   BLK_A0 = 0,
0115   BLK_A1,
0116   BLK_B0
0117 } trig_blk, low_blk, high_blk;
0118 
0119 static volatile enum rel_type {
0120   REL = 0,
0121   REL_MOD,
0122   SYNC
0123 } trig_rel, low_rel, high_rel;
0124 
0125 static const char trig_style_desc [] = {
0126   'S',
0127   'C'
0128 };
0129 
0130 static const char get_type_desc [] = {
0131   'G',
0132   'R'
0133 };
0134 
0135 static const char *blk_kind_desc [] = {
0136   "A0",
0137   "A1",
0138   "B0"
0139 };
0140 
0141 static const char rel_type_desc [] = {
0142   'R',
0143   'M',
0144   'S'
0145 };
0146 
0147 static void print(unsigned level, const char *fmt, ...)
0148 {
0149   if (level <= output_level) {
0150     va_list ap;
0151 
0152     va_start(ap, fmt);
0153     vprintk(fmt, ap);
0154     va_end(ap);
0155   }
0156 }
0157 
0158 static void set_task_prio(rtems_id task, rtems_task_priority prio)
0159 {
0160   rtems_status_code sc = RTEMS_SUCCESSFUL;
0161   rtems_task_priority cur = 0;
0162 
0163   sc = rtems_task_set_priority(task, prio, &cur);
0164   ASSERT_SC(sc);
0165 }
0166 
0167 static rtems_bdbuf_buffer *get(enum get_type type, enum blk_kind kind)
0168 {
0169   rtems_status_code sc = RTEMS_SUCCESSFUL;
0170   rtems_bdbuf_buffer *bd = NULL;
0171   rtems_blkdev_bnum blk_index = 0;
0172   rtems_status_code (*get_bd)(
0173     rtems_disk_device *,
0174     rtems_blkdev_bnum,
0175     rtems_bdbuf_buffer **
0176   ) = NULL;
0177   rtems_disk_device *dd = NULL;
0178   size_t bds_per_group = 0;
0179 
0180   switch (kind) {
0181     case BLK_A0:
0182       dd = dd_a;
0183       blk_index = 0;
0184       bds_per_group = 2;
0185       break;
0186     case BLK_A1:
0187       dd = dd_a;
0188       blk_index = 1;
0189       bds_per_group = 2;
0190       break;
0191     case BLK_B0:
0192       dd = dd_b;
0193       blk_index = 0;
0194       bds_per_group = 1;
0195       break;
0196     default:
0197       rtems_test_assert(false);
0198       break;
0199   }
0200 
0201   switch (type) {
0202     case GET:
0203       get_bd = rtems_bdbuf_get;
0204       break;
0205     case READ:
0206       get_bd = rtems_bdbuf_read;
0207       break;
0208     default:
0209       rtems_test_assert(false);
0210       break;
0211   }
0212 
0213   sc = (*get_bd)(dd, blk_index, &bd);
0214   rtems_test_assert(
0215     sc == RTEMS_SUCCESSFUL
0216       && bd->dd == dd
0217       && bd->block == blk_index
0218       && bd->group->bds_per_group == bds_per_group
0219    );
0220 
0221   return bd;
0222 }
0223 
0224 static void rel(rtems_bdbuf_buffer *bd, enum rel_type type)
0225 {
0226   rtems_status_code sc = RTEMS_SUCCESSFUL;
0227   rtems_status_code (*rel_bd)(rtems_bdbuf_buffer *) = NULL;
0228 
0229   switch (type) {
0230     case REL:
0231       rel_bd = rtems_bdbuf_release;
0232       break;
0233     case REL_MOD:
0234       rel_bd = rtems_bdbuf_release_modified;
0235       break;
0236     case SYNC:
0237       rel_bd = rtems_bdbuf_sync;
0238       break;
0239     default:
0240       rtems_test_assert(false);
0241       break;
0242   }
0243 
0244   sc = (*rel_bd)(bd);
0245   ASSERT_SC(sc);
0246 }
0247 
0248 static void task_low(rtems_task_argument arg)
0249 {
0250   rtems_status_code sc = RTEMS_SUCCESSFUL;
0251 
0252   while (true) {
0253     print(2, "LG\n");
0254     rtems_bdbuf_buffer *bd = get(low_get, low_blk);
0255 
0256     print(2, "LR\n");
0257     rel(bd, low_rel);
0258 
0259     finish_low = true;
0260 
0261     sc = rtems_task_suspend(RTEMS_SELF);
0262     ASSERT_SC(sc);
0263   }
0264 }
0265 
0266 static void task_high(rtems_task_argument arg)
0267 {
0268   rtems_status_code sc = RTEMS_SUCCESSFUL;
0269 
0270   while (true) {
0271     print(2, "HG\n");
0272     rtems_bdbuf_buffer *bd = get(high_get, high_blk);
0273 
0274     print(2, "HR\n");
0275     rel(bd, high_rel);
0276 
0277     finish_high = true;
0278 
0279     sc = rtems_task_suspend(RTEMS_SELF);
0280     ASSERT_SC(sc);
0281   }
0282 }
0283 
0284 static void task_resume(rtems_task_argument arg)
0285 {
0286   while (true) {
0287     bool do_resume = false;
0288 
0289     switch (resume) {
0290       case RESUME_IMMEDIATE:
0291         print(2, "RI\n");
0292         do_resume = true;
0293         break;
0294       case RESUME_FINISH:
0295         print(2, "RF\n");
0296         do_resume = finish_low && finish_high;
0297         break;
0298       default:
0299         rtems_test_assert(false);
0300         break;
0301     }
0302 
0303     if (do_resume) {
0304       rtems_task_resume(task_id_init);
0305     }
0306   }
0307 }
0308 
0309 static void execute_test(unsigned i)
0310 {
0311   rtems_status_code sc = RTEMS_SUCCESSFUL;
0312   rtems_bdbuf_buffer *bd = NULL;
0313   bool suspend = false;
0314 
0315   print(
0316     1,
0317     "[%05u]T(%c,%c,%s,%c)L(%c,%s,%c)H(%c,%s,%c)\n",
0318     i,
0319     trig_style_desc [trig],
0320     get_type_desc [trig_get],
0321     blk_kind_desc [trig_blk],
0322     rel_type_desc [trig_rel],
0323     get_type_desc [low_get],
0324     blk_kind_desc [low_blk],
0325     rel_type_desc [low_rel],
0326     get_type_desc [high_get],
0327     blk_kind_desc [high_blk],
0328     rel_type_desc [high_rel]
0329   );
0330 
0331   set_task_prio(task_id_low, PRIORITY_LOW);
0332 
0333   finish_low = false;
0334   finish_high = false;
0335 
0336   sc = rtems_task_resume(task_id_low);
0337   ASSERT_SC(sc);
0338 
0339   sc = rtems_task_resume(task_id_high);
0340   ASSERT_SC(sc);
0341 
0342   sc = rtems_bdbuf_get(dd_b, 0, &bd);
0343   rtems_test_assert(sc == RTEMS_SUCCESSFUL && bd->dd == dd_b && bd->block == 0);
0344 
0345   sc = rtems_bdbuf_release(bd);
0346   ASSERT_SC(sc);
0347 
0348   switch (trig) {
0349     case SUSP:
0350       suspend = true;
0351       break;
0352     case CONT:
0353       suspend = false;
0354       break;
0355     default:
0356       rtems_test_assert(false);
0357       break;
0358   }
0359 
0360   print(2, "TG\n");
0361   bd = get(trig_get, trig_blk);
0362 
0363   if (suspend) {
0364     print(2, "S\n");
0365     resume = RESUME_IMMEDIATE;
0366     sc = rtems_task_suspend(RTEMS_SELF);
0367     ASSERT_SC(sc);
0368   }
0369   resume = RESUME_FINISH;
0370 
0371   print(2, "TR\n");
0372   rel(bd, trig_rel);
0373 
0374   sc = rtems_task_suspend(RTEMS_SELF);
0375   ASSERT_SC(sc);
0376 
0377   print(2, "F\n");
0378 
0379   sc = rtems_bdbuf_syncdev(dd_a);
0380   ASSERT_SC(sc);
0381 
0382   sc = rtems_bdbuf_syncdev(dd_b);
0383   ASSERT_SC(sc);
0384 }
0385 
0386 static int disk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
0387 {
0388   if (req == RTEMS_BLKIO_REQUEST) {
0389     rtems_blkdev_request *r = argp;
0390 
0391     set_task_prio(task_id_low, PRIORITY_LOW_ALT);
0392 
0393     switch (r->req) {
0394       case RTEMS_BLKDEV_REQ_READ:
0395       case RTEMS_BLKDEV_REQ_WRITE:
0396         rtems_blkdev_request_done(r, RTEMS_SUCCESSFUL);
0397         return 0;
0398       default:
0399         errno = EINVAL;
0400         return -1;
0401     }
0402   } else {
0403     return rtems_blkdev_ioctl(dd, req, argp);
0404   }
0405 }
0406 
0407 static void disk_register(
0408   const char *dev,
0409   uint32_t block_size,
0410   rtems_blkdev_bnum block_count,
0411   rtems_disk_device **dd_ptr
0412 )
0413 {
0414   rtems_status_code sc;
0415   int rv;
0416   int fd;
0417 
0418   sc = rtems_blkdev_create(
0419     dev,
0420     block_size,
0421     block_count,
0422     disk_ioctl,
0423     NULL
0424   );
0425   ASSERT_SC(sc);
0426 
0427   fd = open(dev, O_RDWR);
0428   rtems_test_assert(fd >= 0);
0429 
0430   rv = rtems_disk_fd_get_disk_device(fd, dd_ptr);
0431   rtems_test_assert(rv == 0);
0432 
0433   rv = close(fd);
0434   rtems_test_assert(rv == 0);
0435 }
0436 
0437 static rtems_task Init(rtems_task_argument argument)
0438 {
0439   rtems_status_code sc = RTEMS_SUCCESSFUL;
0440   unsigned i = 0;
0441 
0442   TEST_BEGIN();
0443 
0444   task_id_init = rtems_task_self();
0445 
0446   disk_register("dd_b", BLOCK_SIZE_A, BLOCK_COUNT_A, &dd_a);
0447 
0448   disk_register("dd_a", BLOCK_SIZE_B, BLOCK_COUNT_B, &dd_b);
0449 
0450   sc = rtems_task_create(
0451     rtems_build_name(' ', 'L', 'O', 'W'),
0452     PRIORITY_LOW,
0453     0,
0454     RTEMS_DEFAULT_MODES,
0455     RTEMS_DEFAULT_ATTRIBUTES,
0456     &task_id_low
0457   );
0458   ASSERT_SC(sc);
0459 
0460   sc = rtems_task_start(task_id_low, task_low, 0);
0461   ASSERT_SC(sc);
0462 
0463   sc = rtems_task_create(
0464     rtems_build_name('H', 'I', 'G', 'H'),
0465     PRIORITY_HIGH,
0466     0,
0467     RTEMS_DEFAULT_MODES,
0468     RTEMS_DEFAULT_ATTRIBUTES,
0469     &task_id_high
0470   );
0471   ASSERT_SC(sc);
0472 
0473   sc = rtems_task_start(task_id_high, task_high, 0);
0474   ASSERT_SC(sc);
0475 
0476   sc = rtems_task_create(
0477     rtems_build_name('R', 'E', 'S', 'U'),
0478     PRIORITY_RESUME,
0479     0,
0480     RTEMS_DEFAULT_MODES,
0481     RTEMS_DEFAULT_ATTRIBUTES,
0482     &task_id_resume
0483   );
0484   ASSERT_SC(sc);
0485 
0486   sc = rtems_task_start(task_id_resume, task_resume, 0);
0487   ASSERT_SC(sc);
0488 
0489   sc = rtems_task_suspend(task_id_low);
0490   ASSERT_SC(sc);
0491 
0492   sc = rtems_task_suspend(task_id_high);
0493   ASSERT_SC(sc);
0494 
0495   for (trig = SUSP; trig <= CONT; ++trig) {
0496     for (trig_get = GET; trig_get <= READ; ++trig_get) {
0497       for (low_get = GET; low_get <= READ; ++low_get) {
0498         for (high_get = GET; high_get <= READ; ++high_get) {
0499           for (trig_blk = BLK_A0; trig_blk <= BLK_B0; ++trig_blk) {
0500             for (low_blk = BLK_A0; low_blk <= BLK_B0; ++low_blk) {
0501               for (high_blk = BLK_A0; high_blk <= BLK_B0; ++high_blk) {
0502                 for (trig_rel = REL; trig_rel <= SYNC; ++trig_rel) {
0503                   for (low_rel = REL; low_rel <= SYNC; ++low_rel) {
0504                     for (high_rel = REL; high_rel <= SYNC; ++high_rel) {
0505                       execute_test(i);
0506                       ++i;
0507                     }
0508                   }
0509                 }
0510               }
0511             }
0512           }
0513         }
0514       }
0515     }
0516   }
0517 
0518   TEST_END();
0519 
0520   exit(0);
0521 }
0522 
0523 #define CONFIGURE_INIT
0524 
0525 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0526 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0527 #define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
0528 
0529 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 5
0530 
0531 #define CONFIGURE_MAXIMUM_TASKS 4
0532 
0533 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0534 
0535 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0536 
0537 #define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_INIT
0538 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
0539 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0540 
0541 #define CONFIGURE_SWAPOUT_TASK_PRIORITY PRIORITY_SWAPOUT
0542 
0543 #define CONFIGURE_BDBUF_BUFFER_MIN_SIZE BLOCK_SIZE_A
0544 #define CONFIGURE_BDBUF_BUFFER_MAX_SIZE BLOCK_SIZE_B
0545 #define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE BLOCK_SIZE_B
0546 
0547 #include <rtems/confdefs.h>