diff options
-rwxr-xr-x | AudioManagerDaemon/src/main.cpp | 13 | ||||
-rw-r--r-- | AudioManagerUtilities/include/CAmSocketHandler.h | 22 | ||||
-rw-r--r-- | AudioManagerUtilities/src/CAmSocketHandler.cpp | 35 | ||||
-rw-r--r-- | AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp | 79 | ||||
-rw-r--r-- | AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h | 16 | ||||
-rwxr-xr-x | CMakeLists.txt | 17 | ||||
-rw-r--r-- | 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:"<<strerror(errno)<<std::endl; - std::cerr << "Try running as root"<<std::endl; - } - + //Set runtime-scheduler with priority and policy for all threads. You can define the priority and policy via cmake. + //If the cmake option WITH_REALTIME_SCHEDULER is OFF the following macro is empty. + //If a thread needs other settings you can use CAmSocketHandler::setRuntimeScheduler(...) + SET_REALTIME_SCHEDULER() + (void) envp; listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR)); listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR)); diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h index 53010ba..2fd5c42 100644 --- a/AudioManagerUtilities/include/CAmSocketHandler.h +++ b/AudioManagerUtilities/include/CAmSocketHandler.h @@ -492,7 +492,29 @@ public: void exit_mainloop(); bool fatalErrorOccurred(); +#ifdef WITH_REALTIME_SCHEDULER + /** + * Set scheduling algorithm and/or parameters for a thread whose ID is specified in pid. + * If pid equals zero, the scheduling policy and parameters of the calling thread will be set. + * @param pid_t pid thread id + * @param int policy equals specified policies in sched_setscheduler documentation + * @param int priority between 1 and 99 + * @return on success 0 and on error -1 + */ + static int setRuntimeScheduler(const pid_t pid, const int policy, const int priority); +#endif }; +#ifdef WITH_REALTIME_SCHEDULER +#define SET_REALTIME_SCHEDULER()\ + if ( CAmSocketHandler::setRuntimeScheduler(0, AM_REALTIME_POLICY, AM_PROCESS_PRIORITY) != 0 )\ + {\ + std::cerr <<"sched_setscheduler:"<<strerror(errno)<<std::endl;\ + std::cerr << "Try running as root"<<std::endl;\ + } +#else +#define SET_REALTIME_SCHEDULER() +#endif + } /* namespace am */ #endif /* SOCKETHANDLER_H_ */ diff --git a/AudioManagerUtilities/src/CAmSocketHandler.cpp b/AudioManagerUtilities/src/CAmSocketHandler.cpp index 250d731..ef5d09a 100644 --- a/AudioManagerUtilities/src/CAmSocketHandler.cpp +++ b/AudioManagerUtilities/src/CAmSocketHandler.cpp @@ -246,9 +246,22 @@ void CAmSocketHandler::exit_mainloop() bool CAmSocketHandler::fatalErrorOccurred() { - return ((mInternalCodes&internal_codes_e::PIPE_ERROR)>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<uint8_t> & 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<uint8_t> & 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<v return err; } - auto actionPoll = [](const pollfd pollfd, const sh_pollHandle_t handle, void* userData) + auto actionPoll = [this](const pollfd pollfd, const sh_pollHandle_t handle, void* userData) { uint64_t mExpirations; - if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1) + if(read(pollfd.fd, &mExpirations, sizeof(uint64_t))!=sizeof(uint64_t)) { - //error received...try again - read(pollfd.fd, &mExpirations, sizeof(uint64_t)); + //error received... + logError("Failed to read from timer fd"); + throw std::runtime_error(std::string("Failed to read from timer fd.")); } }; diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp index b0c00d4..c4af4c1 100644 --- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp +++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp @@ -30,11 +30,9 @@ #include <fcntl.h> #include <sys/un.h> #include <sys/poll.h> - +#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:"<<strerror(errno)<<std::endl; - std::cerr << "Try running as root"<<std::endl; - } - + //Set runtime-scheduler with priority and policy for all threads. You can define the priority and policy via cmake. + //If the cmake option WITH_REALTIME_SCHEDULER is OFF the following macro is empty. + //If a thread needs other settings you can use CAmSocketHandler::setRuntimeScheduler(...) + SET_REALTIME_SCHEDULER() + ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } @@ -779,11 +778,11 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType mSocketHandler(mySocketHandler), // mConnecthandle(), // mReceiveHandle(), // - msgList() + msgList(), + mSocket(-1) { int yes = 1; - int socketHandle; struct sockaddr_in servAddr; struct sockaddr_un unixAddr; unsigned int servPort = 6060; @@ -791,26 +790,30 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType switch (socketType) { case UNIX: - socketHandle = socket(AF_UNIX, SOCK_STREAM, 0); + mSocket = socket(AF_UNIX, SOCK_STREAM, 0); + if(mSocket==-1) + return; unixAddr.sun_family = AF_UNIX; strcpy(unixAddr.sun_path, SOCK_PATH); unlink(unixAddr.sun_path); - bind(socketHandle, (struct sockaddr *) &unixAddr, strlen(unixAddr.sun_path) + sizeof(unixAddr.sun_family)); + bind(mSocket, (struct sockaddr *) &unixAddr, strlen(unixAddr.sun_path) + sizeof(unixAddr.sun_family)); break; case INET: - socketHandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); + mSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if(mSocket==-1) + return; + setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = INADDR_ANY; servAddr.sin_port = htons(servPort); - bind(socketHandle, (struct sockaddr *) &servAddr, sizeof(servAddr)); + bind(mSocket, (struct sockaddr *) &servAddr, sizeof(servAddr)); break; default: break; } - if (listen(socketHandle, 3) < 0) + if (listen(mSocket, 3) < 0) { #ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT std::cout << "listen ok" << std::endl; @@ -818,12 +821,12 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType } /* if */ int a = 1; - ioctl(socketHandle, FIONBIO, (char *) &a); - setsockopt(socketHandle, SOL_SOCKET, SO_KEEPALIVE, (char *) &a, sizeof(a)); + ioctl(mSocket, FIONBIO, (char *) &a); + setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, (char *) &a, sizeof(a)); short events = 0; events |= POLLIN; - mySocketHandler->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<CAmSamplePlugin> receiveFiredCB; TAmShPollDispatch<CAmSamplePlugin> sampleDispatchCB; TAmShPollCheck<CAmSamplePlugin> sampleCheckCB; - + bool isSocketOpened() { return mSocket>-1; } protected: CAmSocketHandler *mSocketHandler; sh_pollHandle_t mConnecthandle, mReceiveHandle; std::queue<std::string> msgList; + int mSocket; }; class CAmTimerSockethandlerController: public MockIAmTimerCb @@ -242,11 +240,11 @@ namespace am std::vector<CAmTimerStressTest2*> 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<CAmTimerStressTest2*> & 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@ |