From d6481481d86408a5b1c74162012167ed57ac6ee9 Mon Sep 17 00:00:00 2001 From: Aleksandar Donchev Date: Mon, 27 Nov 2017 15:39:53 +0100 Subject: Cmake parameters for real-time scheduler's priority and policy and throw runtime error if read fails. Signed-off-by: Christian Linke Change-Id: I6a7a2c424bc8fac62c76a66545a231c518edb2e1 --- AudioManagerDaemon/src/main.cpp | 13 ++-- AudioManagerUtilities/include/CAmSocketHandler.h | 22 ++++++ AudioManagerUtilities/src/CAmSocketHandler.cpp | 35 +++++++--- .../AmSocketHandlerTest/CAmSocketHandlerTest.cpp | 79 +++++++++++----------- .../AmSocketHandlerTest/CAmSocketHandlerTest.h | 16 ++--- CMakeLists.txt | 17 ++++- cmake/config.cmake.in | 3 + 7 files changed, 120 insertions(+), 65 deletions(-) diff --git a/AudioManagerDaemon/src/main.cpp b/AudioManagerDaemon/src/main.cpp index 8838ceb..879687d 100755 --- a/AudioManagerDaemon/src/main.cpp +++ b/AudioManagerDaemon/src/main.cpp @@ -387,14 +387,11 @@ iControlSender.setControllerReady(); */ int main(int argc, char *argv[], char** envp) { - struct sched_param param; - param.sched_priority = 50;//mid rt proprity - if (sched_setscheduler(0, SCHED_FIFO, & param) != 0) - { - std::cerr <<"sched_setscheduler:"<0)||((mInternalCodes&internal_codes_e::FD_ERROR)>0); + return ((mInternalCodes&internal_codes_e::PIPE_ERROR)>0)||((mInternalCodes&internal_codes_e::FD_ERROR)>0); } +#ifdef WITH_REALTIME_SCHEDULER +int CAmSocketHandler::setRuntimeScheduler(const pid_t pid, const int policy, const int priority) +{ + //The following structure is used to set a processes priority + struct sched_param param; + //Set the priority of the process + param.sched_priority = priority; + + int ret = sched_setscheduler(pid, policy, & param); + return ret; +} +#endif + am_Error_e CAmSocketHandler::getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData) { VectorListPoll_t::iterator iterator = mListPoll.begin(); @@ -324,7 +337,7 @@ am_Error_e CAmSocketHandler::listenToSignals(const std::vector & listSi if(0==mSignalFdHandle) { /* Create the signalfd */ - int signalHandlerFd = signalfd(-1, &sigset, 0); + int signalHandlerFd = signalfd(-1, &sigset, SFD_NONBLOCK); if (signalHandlerFd == -1) { logError("Could not open signal fd!"); @@ -337,8 +350,13 @@ am_Error_e CAmSocketHandler::listenToSignals(const std::vector & listSi /* We have a valid signal, read the info from the fd */ struct signalfd_siginfo info; ssize_t bytes = read(pollfd.fd, &info, sizeof(info)); - assert(bytes == sizeof(info)); - + if(bytes != sizeof(info)) + { + //error received... + logError("Failed to read from signal fd"); + throw std::runtime_error(std::string("Failed to read from signal fd.")); + } + /* Notify all listeners */ for(auto it: signalHandlers) it.callback(it.handle, info, it.userData); @@ -608,13 +626,14 @@ am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function #include #include - +#include "CAmDltWrapper.h" #include "CAmSocketHandler.h" -//todo: expand test, implement more usecases -//todo: test removeFD #undef ENABLED_SOCKETHANDLER_TEST_OUTPUT #undef ENABLED_TIMERS_TEST_OUTPUT @@ -274,10 +272,11 @@ void* playWithSocketServer(void* data) servAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*) (host->h_addr_list[0]))); servAddr.sin_port = htons(servPort); sleep(1); - - if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + int ret = connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)); + if (ret < 0) { - std::cout << "ERROR: connect() failed\n" << std::endl; + std::cerr << "ERROR: connect() failed\n" << std::endl; + return (NULL); } for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) @@ -299,10 +298,11 @@ void* playWithUnixSocketServer(void* data) strcpy(servAddr.sun_path, SOCK_PATH); servAddr.sun_family = AF_UNIX; sleep(1); - - if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + int ret = connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)); + if ( ret < 0) { - std::cout << "ERROR: connect() failed\n" << std::endl; + std::cerr << "ERROR: connect() failed\n" << std::endl; + return (NULL); } for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) @@ -314,8 +314,6 @@ void* playWithUnixSocketServer(void* data) send(socket_, stringToSend.c_str(), stringToSend.size(), 0); return (NULL); - - } void* threadCallbackUnixSocketAndTimers(void* data) @@ -326,9 +324,11 @@ void* threadCallbackUnixSocketAndTimers(void* data) strcpy(servAddr.sun_path, SOCK_PATH); servAddr.sun_family = AF_UNIX; sleep(1); - if (connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + int ret = connect(socket_, (struct sockaddr *) &servAddr, sizeof(servAddr)); + if ( ret < 0) { - std::cout << "ERROR: connect() failed\n" << std::endl; + std::cerr << "ERROR: connect() failed\n" << std::endl; + return (NULL); } for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++) @@ -369,6 +369,7 @@ TEST(CAmSocketHandlerTest, stressTestUnixSocketAndTimers) { std::cout << "socket problem" << std::endl; } + ASSERT_GT(socket_, -1); //creates a thread that handles the serverpart pthread_create(&serverThread, NULL, threadCallbackUnixSocketAndTimers, &socket_); @@ -376,6 +377,7 @@ TEST(CAmSocketHandlerTest, stressTestUnixSocketAndTimers) myHandler.start_listenting(); pthread_join(serverThread, NULL); + shutdown(socket_, SHUT_RDWR); } TEST(CAmSocketHandlerTest, timersOneshot) @@ -709,6 +711,7 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets) ASSERT_FALSE(myHandler.fatalErrorOccurred()); CAmSamplePlugin::sockType_e type = CAmSamplePlugin::UNIX; CAmSamplePlugin myplugin(&myHandler, type); + ASSERT_TRUE(myplugin.isSocketOpened()); EXPECT_CALL(myplugin,receiveData(_,_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); @@ -718,14 +721,14 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets) { std::cout << "socket problem" << std::endl; } - + ASSERT_GT(socket_, -1); //creates a thread that handles the serverpart pthread_create(&serverThread, NULL, playWithUnixSocketServer, &socket_); myHandler.start_listenting(); pthread_join(serverThread, NULL); - + shutdown(socket_, SHUT_RDWR); } TEST(CAmSocketHandlerTest,playWithSockets) @@ -737,7 +740,7 @@ TEST(CAmSocketHandlerTest,playWithSockets) ASSERT_FALSE(myHandler.fatalErrorOccurred()); CAmSamplePlugin::sockType_e type = CAmSamplePlugin::INET; CAmSamplePlugin myplugin(&myHandler, type); - + ASSERT_TRUE(myplugin.isSocketOpened()); EXPECT_CALL(myplugin,receiveData(_,_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1); @@ -745,28 +748,24 @@ TEST(CAmSocketHandlerTest,playWithSockets) if ((socket_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { std::cout << "socket problem" << std::endl; - } - + ASSERT_GT(socket_, -1); //creates a thread that handles the serverpart pthread_create(&serverThread, NULL, playWithSocketServer, &socket_); myHandler.start_listenting(); pthread_join(serverThread, NULL); - + shutdown(socket_, SHUT_RDWR); } int main(int argc, char **argv) { - struct sched_param param; - param.sched_priority = 50;//mid rt proprity - if (sched_setscheduler(0, SCHED_FIFO, & param) != 0) - { - std::cerr <<"sched_setscheduler:"<addFDPoll(socketHandle, events, NULL, &connectFiredCB, NULL, NULL, NULL, mConnecthandle); + mySocketHandler->addFDPoll(mSocket, events, NULL, &connectFiredCB, NULL, NULL, NULL, mConnecthandle); #ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT std::cout << "setup server - listening" << std::endl; #endif diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h index 269e5da..6cda2b3 100644 --- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h +++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h @@ -101,10 +101,7 @@ namespace am UNIX, INET }; CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType_e socketType); - virtual ~CAmSamplePlugin() - { - } - ; + virtual ~CAmSamplePlugin(){ shutdown(mSocket, SHUT_RDWR); } void connectSocket(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); virtual void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); virtual bool dispatchData(const sh_pollHandle_t handle, void* userData); @@ -113,11 +110,12 @@ namespace am TAmShPollFired receiveFiredCB; TAmShPollDispatch sampleDispatchCB; TAmShPollCheck sampleCheckCB; - + bool isSocketOpened() { return mSocket>-1; } protected: CAmSocketHandler *mSocketHandler; sh_pollHandle_t mConnecthandle, mReceiveHandle; std::queue msgList; + int mSocket; }; class CAmTimerSockethandlerController: public MockIAmTimerCb @@ -242,11 +240,11 @@ namespace am std::vector mTimers; public: CAmSamplePluginStressTest(CAmSocketHandler *mySocketHandler, sockType_e socketType); - ~CAmSamplePluginStressTest(); + virtual ~CAmSamplePluginStressTest(); - virtual void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); - virtual bool dispatchData(const sh_pollHandle_t handle, void* userData); - virtual bool check(const sh_pollHandle_t handle, void* userData); + void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) final; + bool dispatchData(const sh_pollHandle_t handle, void* userData) final; + bool check(const sh_pollHandle_t handle, void* userData) final; std::vector & getTimers() { return mTimers; } }; diff --git a/CMakeLists.txt b/CMakeLists.txt index 38d1a68..6a14717 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,13 @@ option ( WITH_SHARED_CORE "Build audio manager core as dynamic library" OFF) option ( WITH_TIMERFD - "Build with the linux specific TIMERFD feature to support timing without using signals" ON) + "Build with timer fd support" ON ) + +option ( WITH_REALTIME_SCHEDULER + "Use real time scheduler" OFF ) +option( WITH_TESTS + "Build together with all available unitTest" ON ) set(DBUS_SERVICE_PREFIX "org.genivi.audiomanager" CACHE PROPERTY "The dbus service prefix for the AM - only changable for legacy dbus") @@ -94,6 +99,12 @@ set(AM_MAX_CONNECTIONS 0x1000 set(AM_MAX_MAIN_CONNECTIONS 0x1000 CACHE INTEGER "Number of max Mainconnections before rollover") +set(AM_PROCESS_PRIORITY 50 + CACHE INTEGER "Set the priority of the process. The priority is between 1 and 99.") + +set(AM_REALTIME_POLICY SCHED_FIFO + CACHE PROPERTY "The real-time policies that may be specified. See the sched_setscheduler documentation for more details.") + set(AUDIOMANGER_APP_ID "AUDI" CACHE PROPERTY "The application ID that is used by the audiomanager") @@ -209,7 +220,6 @@ if(WITH_DOCUMENTATION) PATTERN "def" EXCLUDE) endif(WITH_DOCUMENTATION) - message(STATUS) message(STATUS "${PROJECT_NAME} Configuration:") message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") @@ -224,6 +234,7 @@ message(STATUS "WITH_DBUS_WRAPPER = ${WITH_DBUS_WRAPPER}") message(STATUS "WITH_SHARED_UTILITIES = ${WITH_SHARED_UTILITIES}") message(STATUS "WITH_SHARED_CORE = ${WITH_SHARED_CORE}") message(STATUS "WITH_TIMERFD = ${WITH_TIMERFD}") +message(STATUS "WITH_REALTIME_SCHEDULER = ${WITH_REALTIME_SCHEDULER}") message(STATUS "DYNAMIC_ID_BOUNDARY = ${DYNAMIC_ID_BOUNDARY}") message(STATUS "LIB_INSTALL_SUFFIX = ${LIB_INSTALL_SUFFIX}") message(STATUS "TEST_EXECUTABLE_INSTALL_PATH = ${TEST_EXECUTABLE_INSTALL_PATH}") @@ -235,6 +246,8 @@ message(STATUS "AM_SHARE_FOLDER = ${AM_SHARE_FOLDER}") message(STATUS "AM_MAP_CAPACITY = ${AM_MAP_CAPACITY}") message(STATUS "AM_MAX_CONNECTIONS = ${AM_MAX_CONNECTIONS}") message(STATUS "AM_MAX_MAIN_CONNECTIONS = ${AM_MAX_MAIN_CONNECTIONS}") +message(STATUS "AM_PROCESS_PRIORITY = ${AM_PROCESS_PRIORITY}") +message(STATUS "AM_REALTIME_POLICY = ${AM_REALTIME_POLICY}") message(STATUS "BUILD_TESTING = ${BUILD_TESTING}") message(STATUS "CMAKE_INSTALL_DOCDIR = ${CMAKE_INSTALL_DOCDIR}") message(STATUS "AUDIOMANGER_APP_ID = ${AUDIOMANGER_APP_ID}") diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in index 1501393..268fbf2 100644 --- a/cmake/config.cmake.in +++ b/cmake/config.cmake.in @@ -10,6 +10,7 @@ #cmakedefine GLIB_DBUS_TYPES_TOLERANT #cmakedefine WITH_SYSTEMD_WATCHDOG #cmakedefine WITH_TIMERFD +#cmakedefine WITH_REALTIME_SCHEDULER #cmakedefine DEFAULT_PLUGIN_DIR "@DEFAULT_PLUGIN_DIR@" #cmakedefine DEFAULT_PLUGIN_COMMAND_DIR "@DEFAULT_PLUGIN_COMMAND_DIR@" @@ -29,6 +30,8 @@ #cmakedefine AM_MAP_CAPACITY @AM_MAP_CAPACITY@ #cmakedefine AM_MAX_CONNECTIONS @AM_MAX_CONNECTIONS@ #cmakedefine AM_MAX_MAIN_CONNECTIONS @AM_MAX_MAIN_CONNECTIONS@ +#cmakedefine AM_PROCESS_PRIORITY @AM_PROCESS_PRIORITY@ +#cmakedefine AM_REALTIME_POLICY @AM_REALTIME_POLICY@ #cmakedefine LIB_COMMAND_INTERFACE_VERSION @LIB_COMMAND_INTERFACE_VERSION@ #cmakedefine LIB_CONTROL_INTERFACE_VERSION @LIB_CONTROL_INTERFACE_VERSION@ #cmakedefine LIB_ROUTING_INTERFACE_VERSION @LIB_ROUTING_INTERFACE_VERSION@ -- cgit v1.2.1