From 1cb5088084f803c12d9caf8101dcbcb7cb966ca2 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Thu, 27 Sep 2012 21:59:27 +0200 Subject: [PATCH] Portable version of priority inheritance check (Posix API based). Signed-off-by: Pavel Pisa --- rtems-tests/Makefile.omk | 2 +- rtems-tests/prioinh_posix/Makefile | 14 ++ rtems-tests/prioinh_posix/Makefile.omk | 20 ++ rtems-tests/prioinh_posix/app_def.h | 32 +++ rtems-tests/prioinh_posix/init.c | 114 +++++++++ rtems-tests/prioinh_posix/prio_inherit_test.c | 224 ++++++++++++++++++ rtems-tests/prioinh_posix/system.h | 66 ++++++ 7 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 rtems-tests/prioinh_posix/Makefile create mode 100644 rtems-tests/prioinh_posix/Makefile.omk create mode 100644 rtems-tests/prioinh_posix/app_def.h create mode 100644 rtems-tests/prioinh_posix/init.c create mode 100644 rtems-tests/prioinh_posix/prio_inherit_test.c create mode 100644 rtems-tests/prioinh_posix/system.h diff --git a/rtems-tests/Makefile.omk b/rtems-tests/Makefile.omk index db47999..6c3121a 100644 --- a/rtems-tests/Makefile.omk +++ b/rtems-tests/Makefile.omk @@ -1,2 +1,2 @@ -SUBDIRS = prioinh_check libbar +SUBDIRS = prioinh_check prioinh_posix libbar diff --git a/rtems-tests/prioinh_posix/Makefile b/rtems-tests/prioinh_posix/Makefile new file mode 100644 index 0000000..76b56fd --- /dev/null +++ b/rtems-tests/prioinh_posix/Makefile @@ -0,0 +1,14 @@ +# Generic directory or leaf node makefile for OCERA make framework + +ifndef MAKERULES_DIR +MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) ) +endif + +ifeq ($(MAKERULES_DIR),) +all : default +.DEFAULT:: + @echo -e "\nThe Makefile.rules has not been found in this or parent directory\n" +else +include $(MAKERULES_DIR)/Makefile.rules +endif + diff --git a/rtems-tests/prioinh_posix/Makefile.omk b/rtems-tests/prioinh_posix/Makefile.omk new file mode 100644 index 0000000..2cf159a --- /dev/null +++ b/rtems-tests/prioinh_posix/Makefile.omk @@ -0,0 +1,20 @@ +default_CONFIG += CONFIG_OC_BUILD4RTEMS=y +default_CONFIG += CONFIG_OC_GDBSTUB=n + +bin_PROGRAMS = prioinh_posix + +#lib_LIBRARIES = + +#include_HEADERS = + +prioinh_posix_SOURCES += prio_inherit_test.c + +ifeq ($(strip $(OMK_RULES_TYPE)),rtems) +prioinh_posix_SOURCES += init.c +INCLUDES += -D COMPILE_FOR_RTEMS +else +lib_LOADLIBES += pthread +endif + +#appfoo_EMBEDTARFILES = rootfs + diff --git a/rtems-tests/prioinh_posix/app_def.h b/rtems-tests/prioinh_posix/app_def.h new file mode 100644 index 0000000..c900ba4 --- /dev/null +++ b/rtems-tests/prioinh_posix/app_def.h @@ -0,0 +1,32 @@ +#ifndef _APP_DEF_H +#define _APP_DEF_H + +#ifndef COND_EXTERN + #ifdef CONFIGURE_INIT + #define COND_EXTERN + #else + #define COND_EXTERN extern + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Posix style startup task */ +void *Task_1(void *argument); + +#define SHELL_TASK_PRIORITY 14 +#define TASK_HI_PRIORITY 13 +#define TASK_MID_PRIORITY 12 +#define TASK_1_PRIORITY 11 +#define TASK_LO_PRIORITY 10 + +void bad_status(int status, int fail_level, const char *text); + +#ifdef __cplusplus +} +#endif + +#endif /*_APP_DEF_H*/ diff --git a/rtems-tests/prioinh_posix/init.c b/rtems-tests/prioinh_posix/init.c new file mode 100644 index 0000000..d2a3353 --- /dev/null +++ b/rtems-tests/prioinh_posix/init.c @@ -0,0 +1,114 @@ +/* Init + * + * This routine is the initialization task for this test program. + * It is called from init_exec and has the responsibility for creating + * and starting the tasks that make up the test. If the time of day + * clock is required for the test, it should also be set to a known + * value by this function. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: init.c,v 1.12.4.1 2003/09/04 18:46:30 joel Exp $ + */ + +#define CONFIGURE_INIT +#include "system.h" +#include "app_def.h" +#include +#include +#include +#include +#include +#include + +#define VER_CODE(major,minor,patch) (major*0x10000+minor*0x100+patch) + +#define BUILD_VERSION_STRING(major,minor,patch) \ + __XSTRING(major) "." __XSTRING(minor) "." __XSTRING(patch) + +#define RTEMS_VER_CODE VER_CODE(__RTEMS_MAJOR__ ,__RTEMS_MINOR__ ,__RTEMS_REVISION__) + +#if RTEMS_VER_CODE < VER_CODE(4,7,99) + #define rtems_shell_add_cmd shell_add_cmd + #define rtems_shell_init(m_task_name,m_task_stacksize,m_task_priority,m_devname,m_forever,m_wait,m_login_check) \ + shell_init(m_task_name,m_task_stacksize,m_task_priority,m_devname,B19200 | CS8,m_forever) +#elif RTEMS_VER_CODE < VER_CODE(4,9,99) + #define rtems_shell_init(m_task_name,m_task_stacksize,m_task_priority,m_devname,m_forever,m_wait,m_login_check) \ + rtems_shell_init(m_task_name,m_task_stacksize,m_task_priority,m_devname,m_forever,m_wait) +#endif + +void +bad_rtems_status(rtems_status_code status, int fail_level, const char *text) +{ + printf("ERROR: %s status %s\n", text, rtems_status_text(status)); + status = rtems_task_delete( RTEMS_SELF ); +} + +int testcmd_forshell(int argc, char **argv) +{ + int i; + printf("Command %s called\n",argv[0]); + for(i=1;i +#include +#include +#include +#include +#include +#include + +#include "app_def.h" + +pthread_mutex_t shared_with_hi_mtx; +pthread_mutex_t shared_with_lo_mtx; + +sem_t release_hi_sem; +sem_t release_mid_sem; +sem_t release_lo_sem; + +pthread_t hi_task_id; +pthread_t mid_task_id; +pthread_t lo_task_id; + + +void bad_status(int status, int fail_level, const char *text) +{ + printf("ERROR: %s status %d\n", text, status); + exit(1); +} + + +void block_delay(int delay) +{ + volatile int l; + + while(delay--) { + l = 100000; + while(l--); + } +} + + +void *hi_task(void *arg) +{ + int status; + + printf("THI created\n"); fflush(stdout); + while(1){ + status=sem_wait(&release_hi_sem); + if(status!=0) bad_status(status, 0, "sem_wait RHI from THI"); + printf("THI released (RHI)\n"); fflush(stdout); + + status=pthread_mutex_lock(&shared_with_hi_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_lock SHI from THI"); + printf("THI obtained SHI\n"); fflush(stdout); + + block_delay(100); + + printf("THI going to release SHI\n"); fflush(stdout); + status=pthread_mutex_unlock(&shared_with_hi_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_unlock SHI from THI"); + printf("THI released SHI\n"); fflush(stdout); + } +} + +void *mid_task(void *arg) +{ + int status; + + printf("TMID created\n"); fflush(stdout); + while(1){ + status=sem_wait(&release_mid_sem); + if(status!=0) bad_status(status, 0, "sem_wait RMID from TMID"); + printf("MID released (RMID)\n"); fflush(stdout); + + block_delay(100); + + printf("MID going to sleep\n"); fflush(stdout); + } +} + +void *lo_task(void *arg) +{ + int status; + + printf("LO created\n"); fflush(stdout); + while(1){ + status=sem_wait(&release_lo_sem); + if(status!=0) bad_status(status, 0, "sem_wait RLO from TLO"); + printf("TLO released (RLO)\n"); fflush(stdout); + + status=pthread_mutex_lock(&shared_with_lo_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_lock SLO from TLO"); + printf("TLO obtained SLO\n"); fflush(stdout); + + block_delay(100); + + printf("TLO going to release SLO\n"); fflush(stdout); + status=pthread_mutex_unlock(&shared_with_lo_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_unlock SLO from TLO"); + printf("TLO released SLO\n"); fflush(stdout); + } +} + + +void *Task_1(void *argument) +{ + int status; + pthread_mutexattr_t mutexattr; + pthread_attr_t taskattr; + struct sched_param schedparam; + + sleep(1); + + printf("*** Starting up Task_1 ***\n"); + + schedparam.sched_priority = sched_get_priority_min(SCHED_FIFO) + TASK_1_PRIORITY; + status = pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedparam); + if(status!=0) bad_status(status, 0, "pthread_setschedparam" ); + + status = pthread_mutexattr_init(&mutexattr); + if(status!=0) bad_status(status, 0, "pthread_mutexattr_init" ); + status=pthread_mutexattr_setprotocol(&mutexattr, PTHREAD_PRIO_INHERIT); + if(status!=0) bad_status(status, 0, "pthread_mutexattr_setprotocol" ); + + status=pthread_mutex_init(&shared_with_hi_mtx, &mutexattr); + if(status!=0) bad_status(status, 0, "pthread_mutex_init SHI" ); + + status=pthread_mutex_init(&shared_with_lo_mtx, &mutexattr); + if(status!=0) bad_status(status, 0, "pthread_mutex_init SLO" ); + + status=sem_init(&release_hi_sem, 0, 0); + if(status!=0) bad_status(status, 0, "sem_init RHI" ); + + status=sem_init(&release_mid_sem, 0, 0); + if(status!=0) bad_status(status, 0, "sem_init RMID" ); + + status=sem_init(&release_lo_sem, 0, 0); + if(status!=0) bad_status(status, 0, "sem_init RLO" ); + + status = pthread_attr_init(&taskattr); + if(status!=0) bad_status(status, 0, "pthread_attr_init" ); + status = pthread_attr_setinheritsched(&taskattr, PTHREAD_EXPLICIT_SCHED); + if(status!=0) bad_status(status, 0, "pthread_attr_setinheritsched" ); + status = pthread_attr_setschedpolicy(&taskattr, SCHED_FIFO); + if(status!=0) bad_status(status, 0, "pthread_attr_setschedpolicy" ); + + schedparam.sched_priority = sched_get_priority_min(SCHED_FIFO) + TASK_HI_PRIORITY; + status = pthread_attr_setschedparam(&taskattr, &schedparam); + if(status!=0) bad_status(status, 0, "pthread_attr_setschedparam" ); + + status = pthread_create(&hi_task_id, &taskattr, hi_task, NULL); + if(status!=0) bad_status(status, 0, "pthread_create THI\n"); + + schedparam.sched_priority = sched_get_priority_min(SCHED_FIFO) + TASK_MID_PRIORITY; + status = pthread_attr_setschedparam(&taskattr, &schedparam); + if(status!=0) bad_status(status, 0, "pthread_attr_setschedparam" ); + + status = pthread_create(&hi_task_id, &taskattr, mid_task, NULL); + if(status!=0) bad_status(status, 0, "pthread_create TMID\n"); + + schedparam.sched_priority = sched_get_priority_min(SCHED_FIFO) + TASK_LO_PRIORITY; + status = pthread_attr_setschedparam(&taskattr, &schedparam); + if(status!=0) bad_status(status, 0, "pthread_attr_setschedparam" ); + + status = pthread_create(&hi_task_id, &taskattr, lo_task, NULL); + if(status!=0) bad_status(status, 0, "pthread_create TLO\n"); + + sleep(1); + + while(1){ + + status=pthread_mutex_lock(&shared_with_lo_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_lock SLO"); + printf("1 obtained SLO\n"); fflush(stdout); + + printf("1 going to release RLO\n"); fflush(stdout); + status=sem_post(&release_lo_sem); + if(status!=0) bad_status(status, 0, "sem_post RLO"); + + status=pthread_mutex_lock(&shared_with_hi_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_lock SHI"); + printf("1 obtained SHI\n"); fflush(stdout); + + printf("1 going to release RHI\n"); fflush(stdout); + status=sem_post(&release_hi_sem); + if(status!=0) bad_status(status, 0, "sem_post RHI"); + + sleep(1); + + printf("1 going to release RMID\n"); fflush(stdout); + status=sem_post(&release_mid_sem); + if(status!=0) bad_status(status, 0, "sem_post RMID"); + + block_delay(100); + + printf("1 going to release SHI\n"); fflush(stdout); + status=pthread_mutex_unlock(&shared_with_hi_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_unlock SHI"); + + block_delay(100); + + printf("1 going to release SLO\n"); fflush(stdout); + status=pthread_mutex_unlock(&shared_with_lo_mtx); + if(status!=0) bad_status(status, 0, "pthread_mutex_unlock SLO"); + printf("1 released both SHI and SLO\n"); fflush(stdout); + + block_delay(100); + + printf("1 going to sleep\n"); fflush(stdout); + sleep(1); + } +} + +#ifndef COMPILE_FOR_RTEMS + +int main(int argc, char *argv[]) +{ + Task_1(NULL); + return 0; +} + +#endif /*COMPILE_FOR_RTEMS*/ diff --git a/rtems-tests/prioinh_posix/system.h b/rtems-tests/prioinh_posix/system.h new file mode 100644 index 0000000..7279551 --- /dev/null +++ b/rtems-tests/prioinh_posix/system.h @@ -0,0 +1,66 @@ +/* system.h + * + * This include file contains information that is included in every + * function in the test set. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: system.h,v 1.13.6.1 2003/09/04 18:46:30 joel Exp $ + */ + +#include + +/* functions */ + +rtems_task Init( + rtems_task_argument argument +); + +/* configuration information */ + +#include /* for device driver prototypes */ + +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define TICKS_PER_SECOND 1000 + +#define CONFIGURE_MAXIMUM_TIMERS 32 +#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 32 +#define CONFIGURE_MAXIMUM_SEMAPHORES 32 +#define CONFIGURE_MAXIMUM_TASKS 32 +#define CONFIGURE_MAXIMUM_PERIODS 4 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 2 +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 +#define CONFIGURE_MAXIMUM_DRIVERS (CONFIGURE_NUMBER_OF_DRIVERS+10) + +#ifdef RTEMS_POSIX_API +#define CONFIGURE_MAXIMUM_POSIX_THREADS 32 +#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 20 +#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 10 +#endif /*RTEMS_POSIX_API*/ + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM +/*#define CONFIGURE_USE_MINIIMFS_AS_BASE_FILESYSTEM*/ + +#define CONFIGURE_MICROSECONDS_PER_TICK 1000 + +#define CONFIGURE_INIT_TASK_STACK_SIZE (10*1024) +#define CONFIGURE_INIT_TASK_PRIORITY 120 +#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \ + RTEMS_NO_TIMESLICE | \ + RTEMS_NO_ASR | \ + RTEMS_INTERRUPT_LEVEL(0)) + +#include + +/* end of include file */ -- 2.39.2