diff options
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.c | 81 |
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, ¶m); + if (ret!=0) { + etThread_handleError(ret, "pthread_attr_getschedparam"); + } param.sched_priority = self->priority; - pthread_attr_init(&attr); - pthread_attr_setschedparam(&attr, ¶m); - 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, ¶m); + 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); } |