Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/org.eclipse.etrice.runtime.c/src')
-rw-r--r--runtime/org.eclipse.etrice.runtime.c/src/platforms/MT_POSIX_GENERIC_GCC/etThread.c81
1 files changed, 71 insertions, 10 deletions
diff --git a/runtime/org.eclipse.etrice.runtime.c/src/platforms/MT_POSIX_GENERIC_GCC/etThread.c b/runtime/org.eclipse.etrice.runtime.c/src/platforms/MT_POSIX_GENERIC_GCC/etThread.c
index fecbae4ad..8b7af981c 100644
--- a/runtime/org.eclipse.etrice.runtime.c/src/platforms/MT_POSIX_GENERIC_GCC/etThread.c
+++ b/runtime/org.eclipse.etrice.runtime.c/src/platforms/MT_POSIX_GENERIC_GCC/etThread.c
@@ -26,6 +26,7 @@
#include <time.h>
#include <sys/unistd.h>
#include <errno.h>
+#include <limits.h>
typedef void *(*threadFunc)(void *);
void* etThread_execute(etThread* self);
@@ -51,38 +52,99 @@ void etThread_construct(
ET_MSC_LOGGER_SYNC_EXIT
}
+/* TODO: improve this using a logger */
+static void etThread_handleError(int err, const char* msg) {
+ errno = err;
+ perror(msg);
+}
+
void etThread_start(etThread* self) {
ET_MSC_LOGGER_SYNC_ENTRY("etThread", "start")
{
struct sched_param param;
pthread_attr_t attr;
+ int ret;
+ /* set policy round robin */
const int policy = SCHED_RR;
+
+ /* adjust priority if out of range */
int minPriority = sched_get_priority_min(policy);
int maxPriority = sched_get_priority_max(policy);
-
if (self->priority<minPriority)
self->priority = minPriority;
if (self->priority>maxPriority)
self->priority = maxPriority;
+ /* adjust stacksize if too small */
+ if (self->stacksize < PTHREAD_STACK_MIN)
+ self->stacksize = PTHREAD_STACK_MIN;
+
+ /* initialize attributes */
+ ret = pthread_attr_init(&attr);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_init");
+ }
+
+ /* initialize parameters */
+ ret = pthread_attr_getschedparam(&attr, &param);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_getschedparam");
+ }
param.sched_priority = self->priority;
- pthread_attr_init(&attr);
- pthread_attr_setschedparam(&attr, &param);
- pthread_attr_setschedpolicy(&attr, policy);
- pthread_attr_setstacksize(&attr, self->stacksize);
- pthread_create(&(self->osData), &attr, (threadFunc) etThread_execute, self);
- pthread_attr_destroy(&attr);
+ ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_setinheritsched");
+ }
+ ret = pthread_attr_setschedpolicy(&attr, policy);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_setschedpolicy");
+ }
+ ret = pthread_attr_setschedparam(&attr, &param);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_setschedparam");
+ }
+ ret = pthread_attr_setstacksize(&attr, self->stacksize);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_setstacksize");
+ }
+
+ /* try to create the thread with these settings (note: setting scheduling requires higher privileges) */
+ ret = pthread_create(&(self->osData), &attr, (threadFunc) etThread_execute, self);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_create");
+ if (ret==EPERM) {
+ printf("pthread_create failed with insufficient permissions, falling back to inherited scheduling\n");
+ ret = pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_setinheritsched");
+ }
+ ret = pthread_create(&(self->osData), &attr, (threadFunc) etThread_execute, self);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_create");
+ }
+ }
+ }
+ ret = pthread_attr_destroy(&attr);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_attr_destroy");
+ }
}
ET_MSC_LOGGER_SYNC_EXIT
}
void* etThread_execute(etThread* self){
ET_MSC_LOGGER_SYNC_ENTRY("etThread", "execute")
+ int ret;
self->started = ET_TRUE;
+
/* set cancel state, thread must not change to PTHREAD_CANCEL_DISABLE */
- pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, NULL);
+ ret = pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, NULL);
+ if (ret!=0) {
+ etThread_handleError(ret, "pthread_setcancelstate");
+ }
+
/* etThread_execute redirects the call from the thread to the execute function in the eTrice runtime to enable correct synchronous MSC logging */
self->threadFunction(self->threadFunctionData);
ET_MSC_LOGGER_SYNC_EXIT
@@ -91,9 +153,8 @@ void* etThread_execute(etThread* self){
void etThread_destruct(etThread* self){
ET_MSC_LOGGER_SYNC_ENTRY("etThread", "destruct")
+ /* Note: thread must not be in state PTHREAD_CANCEL_DISABLE */
if (self->started) {
- self->started = ET_FALSE;
- /* Note: thread must not be in state PTHREAD_CANCEL_DISABLE */
pthread_cancel(self->osData);
pthread_join(self->osData, NULL);
}

Back to the top