added linux implementations
This commit is contained in:
parent
adb80a68fc
commit
b4c6a04d4a
148
osal/linux/BinarySemaphore.cpp
Normal file
148
osal/linux/BinarySemaphore.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
#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);
|
||||
}
|
||||
else 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(errno) {
|
||||
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."
|
||||
"Code " << strerror(errno) << std::endl;
|
||||
/* No break */
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t BinarySemaphore::release() {
|
||||
return BinarySemaphore::release(&this->handle);
|
||||
}
|
||||
|
||||
ReturnValue_t BinarySemaphore::release(sem_t *handle) {
|
||||
ReturnValue_t countResult = checkCount(handle, 1);
|
||||
if(countResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
return countResult;
|
||||
}
|
||||
|
||||
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) {
|
||||
// Could be called from interrupt, use lightweight printf
|
||||
printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// This should never happen.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BinarySemaphore::initSemaphore(uint8_t initCount) {
|
||||
auto result = sem_init(&handle, true, initCount);
|
||||
if(result == -1) {
|
||||
switch(errno) {
|
||||
case(EINVAL):
|
||||
// Value exceeds SEM_VALUE_MAX
|
||||
case(ENOSYS):
|
||||
// System does not support process-shared semaphores
|
||||
sif::error << "BinarySemaphore: Init failed with" << strerror(errno)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) {
|
||||
int value = getSemaphoreCounter(handle);
|
||||
if(value >= maxCount) {
|
||||
if(maxCount == 1 and value > 1) {
|
||||
// Binary Semaphore special case.
|
||||
// This is a config error use lightweight printf is this is called
|
||||
// from an interrupt
|
||||
printf("BinarySemaphore::release: Value of binary semaphore greater"
|
||||
" than 1!\n");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
81
osal/linux/BinarySemaphore.h
Normal file
81
osal/linux/BinarySemaphore.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_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 initCount = 1);
|
||||
|
||||
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.
|
||||
*/
|
||||
virtual ReturnValue_t release() override;
|
||||
/**
|
||||
* This static function can be used to release a semaphore by providing
|
||||
* its handle.
|
||||
* @param handle
|
||||
* @return
|
||||
*/
|
||||
static ReturnValue_t release(sem_t* handle);
|
||||
|
||||
/** Checks the validity of the semaphore count against a specified
|
||||
* known maxCount
|
||||
* @param handle
|
||||
* @param maxCount
|
||||
* @return
|
||||
*/
|
||||
static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount);
|
||||
protected:
|
||||
sem_t handle;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */
|
54
osal/linux/CountingSemaphore.cpp
Normal file
54
osal/linux/CountingSemaphore.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include <framework/osal/linux/CountingSemaphore.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount):
|
||||
maxCount(maxCount), initCount(initCount) {
|
||||
if(initCount > maxCount) {
|
||||
sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
|
||||
"intial cout. Setting initial count to max count." << std::endl;
|
||||
initCount = maxCount;
|
||||
}
|
||||
|
||||
initSemaphore(initCount);
|
||||
}
|
||||
|
||||
CountingSemaphore::CountingSemaphore(CountingSemaphore&& other):
|
||||
maxCount(other.maxCount), initCount(other.initCount) {
|
||||
initSemaphore(initCount);
|
||||
}
|
||||
|
||||
CountingSemaphore& CountingSemaphore::operator =(
|
||||
CountingSemaphore&& other) {
|
||||
initSemaphore(other.initCount);
|
||||
return * this;
|
||||
}
|
||||
|
||||
ReturnValue_t CountingSemaphore::release() {
|
||||
ReturnValue_t result = checkCount(&handle, maxCount);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CountingSemaphore::release(&this->handle);
|
||||
}
|
||||
|
||||
ReturnValue_t CountingSemaphore::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 CountingSemaphore::getMaxCount() const {
|
||||
return maxCount;
|
||||
}
|
||||
|
37
osal/linux/CountingSemaphore.h
Normal file
37
osal/linux/CountingSemaphore.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_
|
||||
#include <framework/osal/linux/BinarySemaphore.h>
|
||||
|
||||
/**
|
||||
* @brief Counting semaphores, which can be acquired more than once.
|
||||
* @details
|
||||
* See: https://www.freertos.org/CreateCounting.html
|
||||
* API of counting semaphores is almost identical to binary semaphores,
|
||||
* so we just inherit from binary semaphore and provide the respective
|
||||
* constructors.
|
||||
*/
|
||||
class CountingSemaphore: public BinarySemaphore {
|
||||
public:
|
||||
CountingSemaphore(const uint8_t maxCount, uint8_t initCount);
|
||||
//! @brief Copy ctor, disabled
|
||||
CountingSemaphore(const CountingSemaphore&) = delete;
|
||||
//! @brief Copy assignment, disabled
|
||||
CountingSemaphore& operator=(const CountingSemaphore&) = delete;
|
||||
//! @brief Move ctor
|
||||
CountingSemaphore (CountingSemaphore &&);
|
||||
//! @brief Move assignment
|
||||
CountingSemaphore & operator=(CountingSemaphore &&);
|
||||
|
||||
ReturnValue_t release() override;
|
||||
static ReturnValue_t release(sem_t* sem);
|
||||
/* Same API as binary semaphore otherwise. acquire() can be called
|
||||
* until there are not semaphores left and release() can be called
|
||||
* until maxCount is reached. */
|
||||
|
||||
uint8_t getMaxCount() const;
|
||||
private:
|
||||
const uint8_t maxCount;
|
||||
uint8_t initCount = 0;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */
|
36
osal/linux/SemaphoreFactory.cpp
Normal file
36
osal/linux/SemaphoreFactory.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include <framework/tasks/SemaphoreFactory.h>
|
||||
#include <framework/osal/linux/BinarySemaphore.h>
|
||||
#include <framework/osal/linux/CountingSemaphore.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
const uint32_t SemaphoreIF::NO_TIMEOUT = 0;
|
||||
const uint32_t SemaphoreIF::MAX_TIMEOUT = 0xFFFFFFFF;
|
||||
|
||||
SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr;
|
||||
|
||||
SemaphoreFactory::SemaphoreFactory() {
|
||||
}
|
||||
|
||||
SemaphoreFactory::~SemaphoreFactory() {
|
||||
delete factoryInstance;
|
||||
}
|
||||
|
||||
SemaphoreFactory* SemaphoreFactory::instance() {
|
||||
if (factoryInstance == nullptr){
|
||||
factoryInstance = new SemaphoreFactory();
|
||||
}
|
||||
return SemaphoreFactory::factoryInstance;
|
||||
}
|
||||
|
||||
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) {
|
||||
return new BinarySemaphore();
|
||||
}
|
||||
|
||||
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount,
|
||||
uint8_t initCount, uint32_t arguments) {
|
||||
return new CountingSemaphore(maxCount, initCount);
|
||||
}
|
||||
|
||||
void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) {
|
||||
delete semaphore;
|
||||
}
|
Loading…
Reference in New Issue
Block a user