Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2017, 2020 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 <sys/stat.h>
0033 #include <errno.h>
0034 #include <fcntl.h>
0035 #include <string.h>
0036 #include <unistd.h>
0037 
0038 #include <rtems/imfs.h>
0039 #include <rtems/libio_.h>
0040 #include <rtems/test-info.h>
0041 #include <rtems/test.h>
0042 
0043 const char rtems_test_name[] = "SPINTRCRITICAL 24";
0044 
0045 typedef struct {
0046   int fd;
0047   rtems_libio_t *iop;
0048   long early_count;
0049   long late_count;
0050   long potential_hit_count;
0051   long append_count;
0052   long no_append_count;
0053   volatile bool closed;
0054 } test_context;
0055 
0056 static const char path[] = "generic";
0057 
0058 static int handler_close(rtems_libio_t *iop)
0059 {
0060   test_context *ctx;
0061 
0062   ctx = IMFS_generic_get_context_by_iop(iop);
0063   ctx->closed = true;
0064 
0065   if (rtems_libio_iop_is_append(iop)) {
0066     ++ctx->append_count;
0067   } else {
0068     ++ctx->no_append_count;
0069   }
0070 
0071   return 0;
0072 }
0073 
0074 static const rtems_filesystem_file_handlers_r node_handlers = {
0075   .open_h = rtems_filesystem_default_open,
0076   .close_h = handler_close,
0077   .fstat_h = rtems_filesystem_default_fstat,
0078   .fcntl_h = rtems_filesystem_default_fcntl
0079 };
0080 
0081 static const IMFS_node_control node_control = {
0082   .handlers = &node_handlers,
0083   .node_initialize = IMFS_node_initialize_generic,
0084   .node_remove = IMFS_node_remove_default,
0085   .node_destroy = IMFS_node_destroy_default
0086 };
0087 
0088 static T_interrupt_test_state interrupt(void *arg)
0089 {
0090   test_context *ctx;
0091   T_interrupt_test_state state;
0092   int rv;
0093   unsigned int flags;
0094 
0095   state = T_interrupt_test_get_state();
0096 
0097   if (state != T_INTERRUPT_TEST_ACTION) {
0098     return T_INTERRUPT_TEST_CONTINUE;
0099   }
0100 
0101   ctx = arg;
0102   flags = rtems_libio_iop_flags_set(ctx->iop, 0);
0103 
0104   if ((flags & LIBIO_FLAGS_OPEN) != 0) {
0105     ++ctx->early_count;
0106     state = T_INTERRUPT_TEST_EARLY;
0107   } else if (ctx->closed) {
0108     ++ctx->late_count;
0109     state = T_INTERRUPT_TEST_LATE;
0110   } else {
0111     ++ctx->potential_hit_count;
0112 
0113     if (ctx->potential_hit_count >= 13) {
0114       state = T_INTERRUPT_TEST_DONE;
0115     } else {
0116       state = T_INTERRUPT_TEST_CONTINUE;
0117     }
0118   }
0119 
0120   rv = fcntl(ctx->fd, F_SETFL, O_APPEND);
0121 
0122   if (rv != 0) {
0123     T_quiet_psx_error(rv, EBADF);
0124   }
0125 
0126   return state;
0127 }
0128 
0129 static void prepare(void *arg)
0130 {
0131   test_context *ctx;
0132 
0133   ctx = arg;
0134 
0135   ctx->fd = open(path, O_RDWR);
0136   T_quiet_ge_int(ctx->fd, 0);
0137 
0138   ctx->closed = false;
0139   ctx->iop = rtems_libio_iop(ctx->fd);
0140 }
0141 
0142 static void action(void *arg)
0143 {
0144   test_context *ctx;
0145   int rv;
0146 
0147   ctx = arg;
0148 
0149   rv = close(ctx->fd);
0150   T_quiet_psx_success(rv);
0151 
0152   T_interrupt_test_busy_wait_for_interrupt();
0153 }
0154 
0155 static const T_interrupt_test_config config = {
0156   .prepare = prepare,
0157   .action = action,
0158   .interrupt = interrupt,
0159   .max_iteration_count = 10000
0160 };
0161 
0162 T_TEST_CASE(CloseInterrupt)
0163 {
0164   test_context ctx;
0165   const char *path = "generic";
0166   int rv;
0167   T_interrupt_test_state state;
0168 
0169   memset(&ctx, 0, sizeof(ctx));
0170 
0171   rv = IMFS_make_generic_node(
0172     path,
0173     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0174     &node_control,
0175     &ctx
0176   );
0177   T_psx_success(rv);
0178 
0179   state = T_interrupt_test(&config, &ctx);
0180   T_eq_int(state, T_INTERRUPT_TEST_DONE);
0181 
0182   T_log(T_NORMAL, "early count = %ld", ctx.early_count);
0183   T_log(T_NORMAL, "late count = %ld", ctx.late_count);
0184   T_log(T_NORMAL, "potential hit count = %ld", ctx.potential_hit_count);
0185   T_log(T_NORMAL, "append count = %ld", ctx.append_count);
0186   T_log(T_NORMAL, "no append count = %ld", ctx.no_append_count);
0187 
0188   /* There is no reliable indicator if the test case has been hit */
0189   T_gt_int(ctx.early_count, 0);
0190   T_gt_int(ctx.late_count, 0);
0191   T_gt_int(ctx.potential_hit_count, 0);
0192   T_gt_int(ctx.append_count, 0);
0193   T_gt_int(ctx.no_append_count, 0);
0194 
0195   rv = unlink(path);
0196   T_psx_success(rv);
0197 }
0198 
0199 static void Init(rtems_task_argument arg)
0200 {
0201   rtems_test_run(arg, TEST_STATE);
0202 }
0203 
0204 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0205 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0206 
0207 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0208 
0209 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
0210 
0211 #define CONFIGURE_MAXIMUM_TASKS 1
0212 
0213 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0214 
0215 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0216 
0217 #define CONFIGURE_INIT
0218 
0219 #include <rtems/confdefs.h>