fsfw/osal/linux/Mutex.cpp

111 lines
3.5 KiB
C++
Raw Normal View History

2020-08-13 20:53:35 +02:00
#include "Mutex.h"
2021-06-03 12:29:06 +02:00
#include "unixUtility.h"
2018-07-13 18:28:26 +02:00
2021-06-03 12:29:06 +02:00
#include "../../serviceinterface/ServiceInterface.h"
#include "../../timemanager/Clock.h"
2018-07-13 18:28:26 +02:00
#include <cstring>
#include <errno.h>
2021-06-03 12:29:06 +02:00
uint8_t Mutex::count = 0;
2018-07-13 18:28:26 +02:00
Mutex::Mutex() {
pthread_mutexattr_t mutexAttr;
int status = pthread_mutexattr_init(&mutexAttr);
if (status != 0) {
2021-06-03 12:29:06 +02:00
utility::printUnixErrorGeneric("Mutex", "Mutex", "pthread_mutexattr_init");
2018-07-13 18:28:26 +02:00
}
status = pthread_mutexattr_setprotocol(&mutexAttr, PTHREAD_PRIO_INHERIT);
if (status != 0) {
2021-06-03 12:29:06 +02:00
utility::printUnixErrorGeneric("Mutex", "Mutex", "pthread_mutexattr_setprotocol");
2018-07-13 18:28:26 +02:00
}
status = pthread_mutex_init(&mutex, &mutexAttr);
if (status != 0) {
2021-06-03 12:29:06 +02:00
utility::printUnixErrorGeneric("Mutex", "Mutex", "pthread_mutex_init");
2018-07-13 18:28:26 +02:00
}
2020-08-07 22:16:10 +02:00
// After a mutex attributes object has been used to initialize one or more
// mutexes, any function affecting the attributes object
// (including destruction) shall not affect any previously initialized mutexes.
2018-07-13 18:28:26 +02:00
status = pthread_mutexattr_destroy(&mutexAttr);
if (status != 0) {
2021-06-03 12:29:06 +02:00
utility::printUnixErrorGeneric("Mutex", "Mutex", "pthread_mutexattr_destroy");
2018-07-13 18:28:26 +02:00
}
}
Mutex::~Mutex() {
//No Status check yet
pthread_mutex_destroy(&mutex);
}
2020-08-07 22:16:10 +02:00
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
2018-07-13 18:28:26 +02:00
int status = 0;
2020-08-07 22:16:10 +02:00
if(timeoutType == TimeoutType::POLLING) {
status = pthread_mutex_trylock(&mutex);
2020-06-04 20:25:15 +02:00
}
2020-08-07 22:16:10 +02:00
else if (timeoutType == TimeoutType::WAITING) {
2018-07-13 18:28:26 +02:00
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;
status = pthread_mutex_timedlock(&mutex, &timeOut);
}
2020-08-07 22:16:10 +02:00
else if(timeoutType == TimeoutType::BLOCKING) {
status = pthread_mutex_lock(&mutex);
}
2020-06-04 20:25:15 +02:00
2018-07-13 18:28:26 +02:00
switch (status) {
case EINVAL:
2020-08-07 22:16:10 +02:00
// The mutex was created with the protocol attribute having the value
// PTHREAD_PRIO_PROTECT and the calling thread's priority is higher
// than the mutex's current priority ceiling.
2018-07-13 18:28:26 +02:00
return WRONG_ATTRIBUTE_SETTING;
2020-08-07 22:16:10 +02:00
// The process or thread would have blocked, and the abs_timeout
// parameter specified a nanoseconds field value less than zero or
// greater than or equal to 1000 million.
// The value specified by mutex does not refer to an initialized mutex object.
2018-07-13 18:28:26 +02:00
//return MUTEX_NOT_FOUND;
case EBUSY:
2020-08-07 22:16:10 +02:00
// The mutex could not be acquired because it was already locked.
2018-07-13 18:28:26 +02:00
return MUTEX_ALREADY_LOCKED;
case ETIMEDOUT:
2020-08-07 22:16:10 +02:00
// The mutex could not be locked before the specified timeout expired.
2018-07-13 18:28:26 +02:00
return MUTEX_TIMEOUT;
case EAGAIN:
2020-08-07 22:16:10 +02:00
// The mutex could not be acquired because the maximum number of
// recursive locks for mutex has been exceeded.
2018-07-13 18:28:26 +02:00
return MUTEX_MAX_LOCKS;
case EDEADLK:
2020-08-07 22:16:10 +02:00
// A deadlock condition was detected or the current thread
// already owns the mutex.
2018-07-13 18:28:26 +02:00
return CURR_THREAD_ALREADY_OWNS_MUTEX;
case 0:
//Success
return HasReturnvaluesIF::RETURN_OK;
default:
return HasReturnvaluesIF::RETURN_FAILED;
};
}
ReturnValue_t Mutex::unlockMutex() {
int status = pthread_mutex_unlock(&mutex);
switch (status) {
case EINVAL:
//The value specified by mutex does not refer to an initialized mutex object.
return MUTEX_NOT_FOUND;
case EAGAIN:
//The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
return MUTEX_MAX_LOCKS;
case EPERM:
//The current thread does not own the mutex.
return CURR_THREAD_DOES_NOT_OWN_MUTEX;
case 0:
//Success
return HasReturnvaluesIF::RETURN_OK;
default:
return HasReturnvaluesIF::RETURN_FAILED;
};
}