yay, linux bin semaph finished

This commit is contained in:
Robin Müller 2020-05-29 00:47:54 +02:00
parent 60872f936c
commit 8676fcd9a9
7 changed files with 203 additions and 8 deletions

View File

@ -0,0 +1,127 @@
#include <framework/osal/linux/BinarySemaphore.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
extern "C" {
#include <errno.h>
#include <string.h>
}
BinarySemaphore::BinarySemaphore() {
// Using unnamed semaphores for now
initSemaphore();
}
BinarySemaphore::~BinarySemaphore() {
sem_destroy(&handle);
}
BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) {
initSemaphore();
}
BinarySemaphore& BinarySemaphore::operator =(
BinarySemaphore&& s) {
initSemaphore();
return * this;
}
ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) {
int result = 0;
if(timeoutMs == SemaphoreIF::NO_TIMEOUT) {
result = sem_trywait(&handle);
}
if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) {
result = sem_wait(&handle);
}
else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){
timespec timeOut;
clock_gettime(CLOCK_REALTIME, &timeOut);
uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec;
nseconds += timeoutMs * 1000000;
timeOut.tv_sec = nseconds / 1000000000;
timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000;
result = sem_timedwait(&handle, &timeOut);
if(result != 0 and errno == EINVAL) {
sif::debug << "BinarySemaphore::acquire: Invalid time value possible"
<< std::endl;
}
}
if(result == 0) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(result) {
case(EAGAIN):
// Operation could not be performed without blocking (for sem_trywait)
case(ETIMEDOUT):
// Semaphore is 0
return SemaphoreIF::SEMAPHORE_TIMEOUT;
case(EINVAL):
// Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID;
case(EINTR):
// Call was interrupted by signal handler
sif::debug << "BinarySemaphore::acquire: Signal handler interrupted"
<< std::endl;
/* No break */
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t BinarySemaphore::release() {
return release(&this->handle);
}
ReturnValue_t BinarySemaphore::release(sem_t *handle) {
int result = sem_post(handle);
if(result == 0) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(errno) {
case(EINVAL):
// Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID;
case(EOVERFLOW):
// SEM_MAX_VALUE overflow. This should never happen
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint8_t BinarySemaphore::getSemaphoreCounter() const {
// And another ugly cast :-D
return getSemaphoreCounter(const_cast<sem_t*>(&this->handle));
}
uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) {
int value = 0;
int result = sem_getvalue(handle, &value);
if (result == 0) {
return value;
}
else if(result != 0 and errno == EINVAL) {
sif::debug << "BInarySemaphore::getSemaphoreCounter: Invalid"
" Semaphore." << std::endl;
return 0;
}
else {
// This should never happen.
return 0;
}
}
void BinarySemaphore::initSemaphore() {
auto result = sem_init(&handle, true, 1);
if(result == -1) {
switch(errno) {
case(EINVAL):
// Value excees SEM_VALUE_MAX
case(ENOSYS):
// System does not support process-shared semaphores
sif::error << "BinarySemaphore: Init failed with" << strerror(errno)
<< std::endl;
}
}
}

View File

@ -0,0 +1,68 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/SemaphoreIF.h>
extern "C" {
#include <semaphore.h>
}
/**
* @brief OS Tool to achieve synchronization of between tasks or between
* task and ISR. The default semaphore implementation creates a
* binary semaphore, which can only be taken once.
* @details
* See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html
* @author R. Mueller
* @ingroup osal
*/
class BinarySemaphore: public SemaphoreIF,
public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! @brief Default ctor
BinarySemaphore();
//! @brief Copy ctor, deleted explicitely.
BinarySemaphore(const BinarySemaphore&) = delete;
//! @brief Copy assignment, deleted explicitely.
BinarySemaphore& operator=(const BinarySemaphore&) = delete;
//! @brief Move ctor
BinarySemaphore (BinarySemaphore &&);
//! @brief Move assignment
BinarySemaphore & operator=(BinarySemaphore &&);
//! @brief Destructor
virtual ~BinarySemaphore();
void initSemaphore();
uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounter(sem_t* handle);
/**
* Take the binary semaphore.
* If the semaphore has already been taken, the task will be blocked
* for a maximum of #timeoutMs or until the semaphore is given back,
* for example by an ISR or another task.
* @param timeoutMs
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/
ReturnValue_t acquire(uint32_t timeoutMs =
SemaphoreIF::NO_TIMEOUT) override;
/**
* Release the binary semaphore.
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available.
*/
ReturnValue_t release() override;
static ReturnValue_t release(sem_t* handle);
protected:
sem_t handle;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */

View File

@ -7,7 +7,7 @@
#include <framework/osal/linux/MessageQueue.h>
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize) :
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
id(0), lastPartner(0), defaultDestination(NO_QUEUE) {
//debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl;
mq_attr attributes;

View File

@ -1,5 +1,5 @@
#ifndef OS_RTEMS_MUTEX_H_
#define OS_RTEMS_MUTEX_H_
#ifndef OS_LINUX_MUTEX_H_
#define OS_LINUX_MUTEX_H_
#include <framework/ipc/MutexIF.h>

View File

@ -20,18 +20,18 @@ SemaphoreFactory* SemaphoreFactory::instance() {
return SemaphoreFactory::factoryInstance;
}
SemaphoreIF* SemaphoreFactory::createBinarySemaphore() {
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) {
sif::error << "Semaphore not implemented for Linux yet" << std::endl;
return nullptr;
}
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count,
uint8_t initCount) {
uint8_t initCount, uint32_t arguments) {
sif::error << "Counting Semaphore not implemented for "
"Linux yet" << std::endl;
return nullptr;
}
void SemaphoreFactory::deleteMutex(SemaphoreIF* semaphore) {
void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) {
delete semaphore;
}

View File

@ -36,7 +36,7 @@ public:
SemaphoreIF* createCountingSemaphore(const uint8_t maxCount,
uint8_t initCount, uint32_t arguments = 0);
void deleteSemaphore(SemaphoreIF* mutex);
void deleteSemaphore(SemaphoreIF* semaphore);
private:
/**

View File

@ -30,7 +30,7 @@ public:
static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1);
//! The current semaphore can not be given, because it is not owned
static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3);
static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3);
/**
* Generic call to acquire a semaphore.