#include "fosa_configuration_parameters.h"
#include "fosa_threads_and_signals.h"
+#ifdef OMK_FOR_USER /* If compiled by OMK, use the config */
+#include "fosa_config.h"
+#endif
+
/*************************
* Storage of thread-specific keys
*************************/
/* Initialize the keys data structure */
int init_keys()
{
- int i, error;
+ int i, ret;
pthread_mutexattr_t attr;
for(i = 0; i < FOSA_MAX_KEYS; i++)
key_in_use[i] = false;
- if ((error = pthread_mutexattr_init(&attr)) != 0)
- return error;
+ ret = pthread_mutexattr_init(&attr);
+ if (ret) return errno;
- if ((error = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) != 0)
- return error;
+#ifndef CONFIG_NO_PRIO_INHERIT /* Not supported on older systems */
+ ret = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+ if (ret) return errno;
+#endif
- if ((error = pthread_mutex_init(&key_lock,&attr)) != 0)
- return error;
+ ret = pthread_mutex_init(&key_lock,&attr);
+ if (ret) return errno;
return 0;
}
* Thread attributes
*************************/
+static inline int __fosa_check_thread(const fosa_thread_id_t *tid)
+{
+ if (tid->linux_pid == tid->linux_tid)
+ return 0;
+
+ return 1;
+}
+
/**
* fosa_thread_attr_init()
*
**/
int fosa_thread_attr_init(fosa_thread_attr_t *attr)
{
- fosa_thread_id_t self;
-
- /* only POSIX threads have attributes */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
-
return pthread_attr_init(attr);
}
**/
int fosa_thread_attr_destroy(fosa_thread_attr_t *attr)
{
- fosa_thread_id_t self;
-
- /* only POSIX threads can have attributes */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
-
return pthread_attr_destroy(attr);
}
int fosa_thread_attr_set_stacksize(fosa_thread_attr_t *attr,
size_t stacksize)
{
- fosa_thread_id_t self;
-
- /* only POSIX threads can set the size of the stack */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
-
return pthread_attr_setstacksize(attr, stacksize);
}
int fosa_thread_attr_get_stacksize(const fosa_thread_attr_t *attr,
size_t *stacksize)
{
- fosa_thread_id_t self;
-
- /* only POSIX threads can set the size of the stack */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
-
return pthread_attr_getstacksize(attr, stacksize);
}
**/
int fosa_key_create(int *key)
{
- int i, error = 0;
+ int i, ret;
bool found = false;
- fosa_thread_id_t self;
- /* only POSIX threads can have specific data */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
-
- if ((error = pthread_mutex_lock(&key_lock)) != 0)
- return error;
+ ret = pthread_mutex_lock(&key_lock);
+ if (ret) return ret;
/* find an unused key */
for (i = 0; i < FOSA_MAX_KEYS; i++) {
if (!key_in_use[i]) {
+ ret = pthread_key_create(&(key_list[i]), NULL);
+ if (ret) return ret;
+
*key = i;
key_in_use[i] = true;
- error = pthread_key_create(&(key_list[i]), NULL);
found = true;
+
break;
}
}
- if ((error = pthread_mutex_unlock(&key_lock))!= 0)
- return error;
+ ret = pthread_mutex_unlock(&key_lock);
+ if (ret) return ret;
- return (!found ? FOSA_EINVAL : error);
+ return (!found ? FOSA_EINVAL : ret);
}
/**
**/
int fosa_key_destroy(int key)
{
- int error;
- fosa_thread_id_t self;
+ int ret;
- /* only POSIX threads can have specific data */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
+ ret = pthread_mutex_lock(&key_lock);
+ if (ret) return ret;
- if ((error = pthread_mutex_lock(&key_lock)) != 0)
- return error;
+ ret = pthread_key_delete(key_list[key]);
+ if (ret) return ret;
- if ((error = pthread_key_delete(key_list[key])) != 0)
- key_in_use[key]=false;
+ key_in_use[key]=false;
- if ((error = pthread_mutex_unlock(&key_lock)) != 0)
- return error;
+ ret = pthread_mutex_unlock(&key_lock);
+ if (ret) return ret;
return 0;
}
fosa_thread_id_t tid,
const void * value)
{
- fosa_thread_id_t self;
+ int ret;
/* only POSIX threads can have specific data */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
+ if (!__fosa_check_thread(&tid))
+ return FOSA_EINVAL;
+
+ ret = pthread_setspecific(key_list[key], value);
- return pthread_setspecific(key_list[key], value);
+ return ret ? ret : 0;
}
/**
fosa_thread_id_t tid,
void ** value)
{
- fosa_thread_id_t self;
-
/* only POSIX threads can have specific data */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
+ if (!__fosa_check_thread(&tid))
return EINVAL;
- if ((value = pthread_getspecific(key_list[key])) != NULL)
- return EINVAL;
- else
- return 0;
+ value = pthread_getspecific(key_list[key]);
+
+ return !value ? FOSA_EINVAL : 0;
}
/******************************************************************
**/
int fosa_get_priority_max()
{
- return sched_get_priority_max(SCHED_RR);
+ int ret;
+
+ ret = sched_get_priority_max(SCHED_RR);
+
+ return ret ? errno : 0;
}
/**
**/
int fosa_get_priority_min()
{
- return sched_get_priority_min(SCHED_RR);
+ int ret;
+
+ ret = sched_get_priority_min(SCHED_RR);
+
+ return ret ? errno : 0;
}
/**
**/
int fosa_thread_attr_set_prio(fosa_thread_attr_t *attr, int prio)
{
- int error;
- fosa_thread_id_t self;
+ int ret;
struct sched_param param;
- /* normal UNIX processes have no attributes */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
-
param.sched_priority = prio;
- if ((error = pthread_attr_setschedpolicy(attr, SCHED_RR)) == 0)
- return error;
+ ret = pthread_attr_setschedpolicy(attr, SCHED_RR);
+ if (ret) return ret;
return pthread_attr_setschedparam(attr, ¶m);
}
**/
int fosa_thread_attr_get_prio(const fosa_thread_attr_t *attr, int *prio)
{
- int error;
- fosa_thread_id_t self;
+ int ret;
struct sched_param param;
- /* normal UNIX processes have no attributes */
- self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return EINVAL;
+ ret = pthread_attr_getschedparam(attr, ¶m);
+ if (ret) return ret;
- if ((error = pthread_attr_getschedparam(attr, ¶m)) == 0)
- *prio = param.sched_priority;
+ *prio = param.sched_priority;
- return error;
+ return 0;
}
/**
**/
int fosa_thread_set_prio(fosa_thread_id_t tid, int prio)
{
+ int ret;
struct sched_param param;
- param.sched_priority=prio;
+ param.sched_priority = prio;
+
+ ret = sched_setscheduler(0, SCHED_RR, ¶m);
- return sched_setscheduler(0, SCHED_RR, ¶m);
+ return ret ? errno : 0;
}
/**
int fosa_thread_get_prio(fosa_thread_id_t tid, int *prio)
{
struct sched_param param;
- int error;
+ int ret;
- error = sched_getparam(0, ¶m);
+ ret = sched_getparam(0, ¶m);
*prio = param.sched_priority;
- return error;
+ return ret ? errno : 0;
}
/*******************************************************************
**/
int fosa_set_accepted_signals(fosa_signal_t set[], int size)
{
- int i, error;
+ int i, ret;
fosa_thread_id_t self;
sigset_t sigset;
struct sigaction action;
- if ((error = sigemptyset(&sigset)) != 0)
- return error;
+ ret = sigemptyset(&sigset);
+ if (ret) goto err;
action.sa_handler = SIG_DFL;
action.sa_mask = sigset;
action.sa_sigaction = NULL;
for (i = 0; i < size; i++) {
- if ((error = sigaddset(&sigset, set[i])) != 0)
- return error;
- if ((error = sigaction(set[i], &action, NULL)) != 0)
- return error;
+ ret = sigaddset(&sigset, set[i]);
+ if (ret) goto err;
+ ret = sigaction(set[i], &action, NULL);
+ if (ret) goto err;
}
self = fosa_thread_self();
- if (self.linux_pid == self.linux_tid)
- return pthread_sigmask(SIG_BLOCK, &sigset, NULL);
- else
- return sigprocmask(SIG_BLOCK, &sigset, NULL);
+ if (__fosa_check_thread(&self)) {
+ ret = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+ if (ret) return ret;
+ } else {
+ ret = sigprocmask(SIG_BLOCK, &sigset, NULL);
+ if (ret) goto err;
+ }
+
+ return 0;
+err:
+ return errno;
}
/**
fosa_signal_info_t info,
fosa_thread_id_t receiver)
{
- int error;
+ int ret;
timer_t fake_timer;
struct itimerspec fake_time;
struct sigevent fake_event;
- timer_create(CLOCK_MONOTONIC, &fake_event, &fake_timer);
+ ret = timer_create(FOSA_CLOCK_REALTIME, &fake_event, &fake_timer);
+ if (ret) goto err;
fake_time.it_value.tv_sec = fake_time.it_value.tv_nsec = 0;
fake_time.it_interval.tv_sec = fake_time.it_interval.tv_nsec = 0;
fake_event.sigev_value.sival_int = info.sival_int;
fake_event._sigev_un._tid = receiver.linux_tid;
- error = timer_settime(fake_timer, TIMER_ABSTIME, &fake_time, NULL);
- timer_delete(fake_timer);
+ ret = timer_settime(fake_timer, TIMER_ABSTIME, &fake_time, NULL);
+ if (ret) {
+ timer_delete(fake_timer);
+ goto err;
+ }
+
+ ret = timer_delete(fake_timer);
+ if (ret) goto err;
- return error;
+ return 0;
+err:
+ return errno;
}
/**
fosa_signal_t *signal_received,
fosa_signal_info_t *info)
{
- int i, error;
+ int i, ret;
sigset_t sigset;
siginfo_t siginfo;
- if ((error = sigemptyset(&sigset)) != 0)
- return error;
+ ret = sigemptyset(&sigset);
+ if (ret) goto err;
- for (i = 0; i < size; i++)
- if ((error = sigaddset(&sigset,set[i])) != 0)
- return error;
+ for (i = 0; i < size; i++) {
+ ret = sigaddset(&sigset,set[i]);
+ if (ret) goto err;
+ }
- if ((error = sigwaitinfo(&sigset, &siginfo)) != 0)
- return error;
+ ret = sigwaitinfo(&sigset, &siginfo);
+ if (ret) goto err;
if (info != NULL && signal_received != NULL)
*signal_received = siginfo.si_signo;
*info = (fosa_signal_info_t) siginfo.si_value.sival_int;
return 0;
+err:
+ return errno;
}
/**
fosa_signal_info_t *info,
const struct timespec *timeout)
{
- int i, error;
+ int i, ret;
sigset_t signalset;
siginfo_t siginfo;
- if ((error = sigemptyset(&signalset)) != 0)
- return error;
+ ret = sigemptyset(&signalset);
+ if (ret) goto err;
- for (i = 0; i < size; i++)
- if ((error = sigaddset(&signalset,set[i])) != 0)
- return error;
+ for (i = 0; i < size; i++) {
+ ret = sigaddset(&signalset,set[i]);
+ if (ret) goto err;
+ }
- if ((error = sigtimedwait(&signalset,&siginfo,timeout)) != 0)
- return error;
+ ret = sigtimedwait(&signalset,&siginfo,timeout);
+ if (ret) goto err;
if (signal_received != NULL)
*signal_received = siginfo.si_signo;
*info = (fosa_signal_info_t) siginfo.si_value.sival_int;
return 0;
+err:
+ return errno;
}