/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @ingroup psxtests * * @brief Test that the workspace size estimate is correct. */ /* * Copyright (c) 2014. On-Line Applications Research Corporation (OAR). * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include const char rtems_test_name[] = "PSXCONFIG 1"; #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 5 #define CONFIGURE_MAXIMUM_POSIX_KEYS 23 #if CONFIGURE_MAXIMUM_POSIX_KEYS > 0 #define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS CONFIGURE_MAXIMUM_POSIX_KEYS #endif #define CONFIGURE_MAXIMUM_BARRIERS 2 #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 7 #define CONFIGURE_MAXIMUM_PARTITIONS 37 #define CONFIGURE_MAXIMUM_PERIODS 41 #define CONFIGURE_MAXIMUM_REGIONS 43 #define CONFIGURE_MAXIMUM_SEMAPHORES 47 #define CONFIGURE_MAXIMUM_TASKS 11 #define CONFIGURE_MAXIMUM_TIMERS 59 #define CONFIGURE_MAXIMUM_USER_EXTENSIONS 17 #define POSIX_MQ_COUNT 5 #ifdef RTEMS_POSIX_API #define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 7 #endif #define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 41 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_MINIMUM_POSIX_THREAD_STACK_SIZE CPU_STACK_MINIMUM_SIZE #define CONFIGURE_MAXIMUM_POSIX_THREADS 3 #ifdef RTEMS_POSIX_API #define CONFIGURE_MAXIMUM_POSIX_TIMERS 47 #endif #ifndef CONFIGURE_MAXIMUM_TASKS #define CONFIGURE_MAXIMUM_TASKS 1 #endif #if CONFIGURE_MAXIMUM_MESSAGE_QUEUES > 0 #define MQ_0_COUNT 2 #define MQ_1_COUNT 3 #define MQ_2_COUNT 5 #define MQ_3_COUNT 7 #define MQ_4_COUNT 11 #define MQ_5_COUNT 13 #define MQ_6_COUNT 17 #define MQ_0_SIZE 101 #define MQ_1_SIZE 103 #define MQ_2_SIZE 107 #define MQ_3_SIZE 109 #define MQ_4_SIZE 113 #define MQ_5_SIZE 127 #define MQ_6_SIZE 131 #define MQ_BUFFER_MEMORY \ (CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_0_COUNT, MQ_0_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_1_COUNT, MQ_1_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_2_COUNT, MQ_2_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_3_COUNT, MQ_3_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_4_COUNT, MQ_4_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_5_COUNT, MQ_5_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MQ_6_COUNT, MQ_6_SIZE)) static const uint8_t mq_counts [CONFIGURE_MAXIMUM_MESSAGE_QUEUES] = { MQ_0_COUNT, MQ_1_COUNT, MQ_2_COUNT, MQ_3_COUNT, MQ_4_COUNT, MQ_5_COUNT, MQ_6_COUNT }; static const uint8_t mq_sizes [CONFIGURE_MAXIMUM_MESSAGE_QUEUES] = { MQ_0_SIZE, MQ_1_SIZE, MQ_2_SIZE, MQ_3_SIZE, MQ_4_SIZE, MQ_5_SIZE, MQ_6_SIZE }; #else #define MQ_BUFFER_MEMORY 0 #endif #if POSIX_MQ_COUNT > 0 #define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES POSIX_MQ_COUNT #define POSIX_MQ_0_COUNT 2 #define POSIX_MQ_1_COUNT 3 #define POSIX_MQ_2_COUNT 5 #define POSIX_MQ_3_COUNT 7 #define POSIX_MQ_4_COUNT 11 #define POSIX_MQ_0_SIZE 137 #define POSIX_MQ_1_SIZE 139 #define POSIX_MQ_2_SIZE 149 #define POSIX_MQ_3_SIZE 151 #define POSIX_MQ_4_SIZE 157 #define POSIX_MQ_BUFFER_MEMORY \ (CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(POSIX_MQ_0_COUNT, POSIX_MQ_0_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(POSIX_MQ_1_COUNT, POSIX_MQ_1_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(POSIX_MQ_2_COUNT, POSIX_MQ_2_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(POSIX_MQ_3_COUNT, POSIX_MQ_3_SIZE) \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(POSIX_MQ_4_COUNT, POSIX_MQ_4_SIZE)) static const uint8_t posix_mq_counts [POSIX_MQ_COUNT] = { POSIX_MQ_0_COUNT, POSIX_MQ_1_COUNT, POSIX_MQ_2_COUNT, POSIX_MQ_3_COUNT, POSIX_MQ_4_COUNT }; static const uint8_t posix_mq_sizes [POSIX_MQ_COUNT] = { POSIX_MQ_0_SIZE, POSIX_MQ_1_SIZE, POSIX_MQ_2_SIZE, POSIX_MQ_3_SIZE, POSIX_MQ_4_SIZE }; #else #define POSIX_MQ_BUFFER_MEMORY 0 #endif #define CONFIGURE_MESSAGE_BUFFER_MEMORY \ (MQ_BUFFER_MEMORY + POSIX_MQ_BUFFER_MEMORY) #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE #define CONFIGURE_INIT static rtems_task Init(rtems_task_argument argument); #include typedef struct RTEMS_ALIGNED(RTEMS_PARTITION_ALIGNMENT) { uint64_t data [16]; } area; #if CONFIGURE_MAXIMUM_PARTITIONS > 0 static area partition_areas [CONFIGURE_MAXIMUM_PARTITIONS]; #endif #if CONFIGURE_MAXIMUM_REGIONS > 0 static area region_areas [CONFIGURE_MAXIMUM_REGIONS]; #endif static char posix_name [_POSIX_PATH_MAX + 1]; static char *get_posix_name(char a, char b, char c, int i) { posix_name [_POSIX_PATH_MAX - 4] = a; posix_name [_POSIX_PATH_MAX - 3] = b; posix_name [_POSIX_PATH_MAX - 2] = c; posix_name [_POSIX_PATH_MAX - 1] = 'A' + i; return posix_name; } static void *posix_thread(void *arg RTEMS_UNUSED) { rtems_test_assert(0); } static void posix_key_dtor(void *key RTEMS_UNUSED) { /* Do nothing */ } static void print_info(void) { Heap_Information_block info; bool ok = rtems_workspace_get_information(&info); rtems_test_assert(ok); printf( "used blocks = %" PRIuPTR ", " "largest used block = %" PRIuPTR ", " "used space = %" PRIuPTR "\n" "free blocks = %" PRIuPTR ", " "largest free block = %" PRIuPTR ", " "free space = %" PRIuPTR "\n", info.Used.number, info.Used.largest, info.Used.total, info.Free.number, info.Free.largest, info.Free.total ); } static rtems_task Init(rtems_task_argument argument) { rtems_status_code sc = RTEMS_SUCCESSFUL; int eno = 0; rtems_id id = RTEMS_ID_NONE; rtems_name name = rtems_build_name('C', 'O', 'N', 'F'); rtems_extensions_table table; rtems_resource_snapshot snapshot; int i = 0; pthread_key_t key; TEST_BEGIN(); memset(posix_name, 'P', sizeof(posix_name) - 1); print_info(); rtems_resource_snapshot_take(&snapshot); rtems_test_assert(rtems_resource_snapshot_equal(&snapshot, &snapshot)); rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); #if CONFIGURE_MAXIMUM_FILE_DESCRIPTORS > 0 for (i = 3; i < CONFIGURE_MAXIMUM_FILE_DESCRIPTORS; ++i) { int oflag = O_WRONLY | O_CREAT | O_TRUNC; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; char path [] = { 'F', 'I', 'L', 'E', 'A' + i, '\0' }; int fd = open(path, oflag, mode); rtems_test_assert(fd == i); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.open_files == CONFIGURE_MAXIMUM_FILE_DESCRIPTORS ); #endif #if CONFIGURE_MAXIMUM_USER_EXTENSIONS > 0 memset(&table, 0, sizeof(table)); for (i = 0; i < CONFIGURE_MAXIMUM_USER_EXTENSIONS; ++i) { sc = rtems_extension_create(name, &table, &id); directive_failed(sc, "rtems_extension_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_extensions == CONFIGURE_MAXIMUM_USER_EXTENSIONS ); #endif #if CONFIGURE_MAXIMUM_POSIX_KEYS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_KEYS; ++i) { eno = pthread_key_create(&key, posix_key_dtor); rtems_test_assert(eno == 0); eno = pthread_setspecific(key, (void *) (uintptr_t)(i + 1)); rtems_test_assert(eno == 0); } eno = pthread_key_create(&key, posix_key_dtor); rtems_test_assert(eno == EAGAIN); rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.active_posix_keys == CONFIGURE_MAXIMUM_POSIX_KEYS ); rtems_test_assert( snapshot.active_posix_key_value_pairs == CONFIGURE_MAXIMUM_POSIX_KEYS ); #else (void) key; #endif #if CONFIGURE_MAXIMUM_BARRIERS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_BARRIERS; ++i) { sc = rtems_barrier_create(name, RTEMS_DEFAULT_ATTRIBUTES, 1, &id); directive_failed(sc, "rtems_barrier_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_barriers == CONFIGURE_MAXIMUM_BARRIERS ); #endif #if CONFIGURE_MAXIMUM_MESSAGE_QUEUES > 0 for (i = 0; i < CONFIGURE_MAXIMUM_MESSAGE_QUEUES; ++i) { sc = rtems_message_queue_create( name, mq_counts [i], mq_sizes [i], RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed(sc, "rtems_message_queue_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_message_queues == CONFIGURE_MAXIMUM_MESSAGE_QUEUES ); #endif #if CONFIGURE_MAXIMUM_PARTITIONS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_PARTITIONS; ++i) { sc = rtems_partition_create( name, partition_areas + i, sizeof(partition_areas [0]), sizeof(partition_areas [0]), RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed(sc, "rtems_partition_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_partitions == CONFIGURE_MAXIMUM_PARTITIONS ); #endif #if CONFIGURE_MAXIMUM_PERIODS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_PERIODS; ++i) { sc = rtems_rate_monotonic_create(name, &id); directive_failed(sc, "rtems_rate_monotonic_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_periods == CONFIGURE_MAXIMUM_PERIODS ); #endif #if CONFIGURE_MAXIMUM_REGIONS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_REGIONS; ++i) { sc = rtems_region_create( name, region_areas + i, sizeof(region_areas [0]), 1, RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed(sc, "rtems_region_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_regions == CONFIGURE_MAXIMUM_REGIONS ); #endif #if CONFIGURE_MAXIMUM_SEMAPHORES > 0 for (i = 0; i < CONFIGURE_MAXIMUM_SEMAPHORES; ++i) { sc = rtems_semaphore_create( name, 0, RTEMS_DEFAULT_ATTRIBUTES, 0, &id ); directive_failed(sc, "rtems_semaphore_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_semaphores >= CONFIGURE_MAXIMUM_SEMAPHORES ); #endif #if CONFIGURE_MAXIMUM_TASKS > 0 for (i = 1; i < CONFIGURE_MAXIMUM_TASKS; ++i) { sc = rtems_task_create( name, RTEMS_MINIMUM_PRIORITY, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_LOCAL | RTEMS_FLOATING_POINT, &id ); directive_failed(sc, "rtems_task_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_tasks == CONFIGURE_MAXIMUM_TASKS ); #endif #if CONFIGURE_MAXIMUM_TIMERS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_TIMERS; ++i) { sc = rtems_timer_create(name, &id); directive_failed(sc, "rtems_timer_create"); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.rtems_api.active_timers == CONFIGURE_MAXIMUM_TIMERS ); #endif #if POSIX_MQ_COUNT > 0 for (i = 0; i < POSIX_MQ_COUNT; ++i) { int oflag = O_RDWR | O_CREAT | O_EXCL; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; struct mq_attr attr = { .mq_maxmsg = posix_mq_counts [i], .mq_msgsize = posix_mq_sizes [i] }; char *path = get_posix_name('M', 'S', 'Q', i); mqd_t mq = mq_open(path, oflag, mode, &attr); rtems_test_assert(mq >= 0); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.posix_api.active_message_queues == CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES ); #endif #if CONFIGURE_MAXIMUM_POSIX_SEMAPHORES > 0 for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_SEMAPHORES; ++i) { int oflag = O_RDWR | O_CREAT | O_EXCL; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; unsigned int value = 0; char *path = get_posix_name('S', 'E', 'M', i); sem_t *sem = sem_open(path, oflag, mode, value); rtems_test_assert(sem != SEM_FAILED); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.posix_api.active_semaphores == CONFIGURE_MAXIMUM_POSIX_SEMAPHORES ); #endif #if CONFIGURE_MAXIMUM_POSIX_THREADS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_THREADS; ++i) { pthread_t thread; pthread_attr_t attr; size_t stack_size; eno = pthread_create(&thread, NULL, posix_thread, NULL); rtems_test_assert(eno == 0); eno = pthread_getattr_np(thread, &attr); rtems_test_assert(eno == 0); eno = pthread_attr_getstacksize(&attr, &stack_size); rtems_test_assert(eno == 0); rtems_test_assert(stack_size >= CPU_STACK_MINIMUM_SIZE); rtems_test_assert( stack_size <= CPU_STACK_MINIMUM_SIZE + CPU_STACK_ALIGNMENT - CPU_HEAP_ALIGNMENT ); eno = pthread_attr_destroy(&attr); rtems_test_assert(eno == 0); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.posix_api.active_threads == CONFIGURE_MAXIMUM_POSIX_THREADS ); #endif #if CONFIGURE_MAXIMUM_POSIX_TIMERS > 0 for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_TIMERS; ++i) { timer_t timer_id; int rv; rv = timer_create(CLOCK_REALTIME, NULL, &timer_id); rtems_test_assert(rv == 0); } rtems_resource_snapshot_take(&snapshot); rtems_test_assert( snapshot.posix_api.active_timers == CONFIGURE_MAXIMUM_POSIX_TIMERS ); #endif printf("object creation done\n"); print_info(); TEST_END(); rtems_test_exit(0); }