47#if OPENMRN_FEATURE_MUTEX_FREERTOS
48#include "freertos_includes.h"
50#if OPENMRN_FEATURE_DEVICE_SELECT
51#include <event_groups.h>
54#if OPENMRN_FEATURE_MUTEX_PTHREAD
60#include <mach/mach_time.h>
63#if defined (__WIN32__)
77#define OS_INLINE extern inline __attribute__((__gnu_inline__))
90#if defined (__FreeRTOS__)
92extern void hw_init(
void);
95extern const size_t main_stack_size;
98extern const int main_priority;
101#if OPENMRN_FEATURE_MUTEX_FREERTOS
102typedef xTaskHandle os_thread_t;
105 xSemaphoreHandle
sem;
108typedef xQueueHandle os_mq_t;
113typedef xSemaphoreHandle os_sem_t;
115#if OPENMRN_FEATURE_MUTEX_FAKE
128typedef unsigned os_thread_t;
129typedef void *os_mq_t;
131#if OPENMRN_FEATURE_MUTEX_PTHREAD
132typedef pthread_t os_thread_t;
133typedef pthread_mutex_t os_mutex_t;
134typedef void *os_mq_t;
135typedef pthread_once_t os_thread_once_t;
142 pthread_mutex_t mutex;
155#define container_of(_ptr, _type, _member) \
157 const typeof( ((_type *)0)->_member ) *__mptr = (_ptr); \
158 (_type *)( (char *)__mptr - offsetof(_type,_member) ); \
172#ifndef OPENMRN_FEATURE_MUTEX_PTHREAD
177 OS_THREAD_ONCE_NEVER = 0,
178 OS_THREAD_ONCE_INPROGRESS,
182#define OS_THREAD_ONCE_INIT { OS_THREAD_ONCE_NEVER }
185#define OS_THREAD_ONCE_INIT PTHREAD_ONCE_INIT
188#ifndef OPENMRN_FEATURE_MUTEX_PTHREAD
203 return pthread_once(once, routine);
208#define OS_PRIO_DEFAULT 0
209#define OS_PRIO_MAX 32
212#define OS_MQ_TIMEDOUT 1
217#define OPENMRN_OS_WAIT_FOREVER LLONG_MAX
219#define OPENMRN_OS_WAIT_FOREVER __LONG_LONG_MAX__
226#define NSEC_TO_USEC(_nsec) (((long long)_nsec) / 1000LL)
232#define NSEC_TO_MSEC(_nsec) (((long long)_nsec) / 1000000LL)
238#define NSEC_TO_SEC(_nsec) (((long long)_nsec) / 1000000000LL)
244#define NSEC_TO_MIN(_nsec) (((long long)_nsec) / 60000000000LL)
250#define USEC_TO_NSEC(_usec) (((long long)_usec) * 1000LL)
256#define USEC_TO_MSEC(_usec) (((long long)_usec) / 1000LL)
262#define USEC_TO_SEC(_usec) (((long long)_usec) / 1000000LL)
268#define MSEC_TO_NSEC(_msec) (((long long)_msec) * 1000000LL)
274#define MSEC_TO_USEC(_msec) (((long long)_msec) * 1000LL)
280#define MSEC_TO_SEC(_msec) (((long long)_msec) / 1000LL)
286#define SEC_TO_NSEC(_sec) (((long long)_sec) * 1000000000LL)
292#define SEC_TO_USEC(_sec) (((long long)_sec) * 1000000LL)
298#define SEC_TO_MSEC(_sec) (((long long)_sec) * 1000LL)
304#define NSEC_TO_USEC_ROUNDED(_nsec) \
305 ((((long long)_nsec) + 500LL) / 1000LL)
311#define NSEC_TO_MSEC_ROUNDED(_nsec) \
312 ((((long long)_nsec) + 500000LL) / 1000000LL)
318#define NSEC_TO_SEC_ROUNDED(_nsec) \
319 ((((long long)_nsec) + 500000000LL) / 1000000000LL)
325#define NSEC_TO_MIN_ROUNDED(_nsec) \
326 ((((long long)_nsec) + 30000000000LL) / 60000000000LL)
332#define USEC_TO_MSEC_ROUNDED(_usec) \
333 ((((long long)_usec) + 500LL) / 1000LL)
339#define USEC_TO_SEC_ROUNDED(_usec) \
340 ((((long long)_usec) +500000LL) / 1000000LL)
346#define MSEC_TO_SEC_ROUNDED(_msec) \
347 ((((long long)_msec) + 500LL) / 1000LL)
360 void *(*start_routine) (
void *),
void *arg);
372#if OPENMRN_FEATURE_MUTEX_FREERTOS
373 return xTaskGetCurrentTaskHandle();
374#elif OPENMRN_FEATURE_SINGLE_THREADED
376#elif OPENMRN_FEATURE_MUTEX_PTHREAD
377 return pthread_self();
387#if OPENMRN_FEATURE_MUTEX_FREERTOS
388 return uxTaskPriorityGet(thread);
389#elif OPENMRN_FEATURE_SINGLE_THREADED
391#elif OPENMRN_FEATURE_MUTEX_PTHREAD
392 struct sched_param params;
394 pthread_getschedparam(thread, &policy, ¶ms);
395 return params.sched_priority;
404#if OPENMRN_FEATURE_MUTEX_FREERTOS
406#elif OPENMRN_FEATURE_SINGLE_THREADED
408#elif OPENMRN_FEATURE_MUTEX_PTHREAD
409 return sched_get_priority_min(SCHED_FIFO);
418#if OPENMRN_FEATURE_MUTEX_FREERTOS
419 return configMAX_PRIORITIES - 1;
420#elif OPENMRN_FEATURE_SINGLE_THREADED
422#elif OPENMRN_FEATURE_MUTEX_PTHREAD
423 return sched_get_priority_max(SCHED_FIFO);
427#if OPENMRN_FEATURE_MUTEX_FREERTOS
429#define OS_MUTEX_INITIALIZER {NULL, 0}
431#define OS_RECURSIVE_MUTEX_INITIALIZER {NULL, 1}
432#elif OPENMRN_FEATURE_MUTEX_FAKE
434#define OS_MUTEX_INITIALIZER {0, 0}
436#define OS_RECURSIVE_MUTEX_INITIALIZER {0, 1}
437#elif OPENMRN_FEATURE_MUTEX_PTHREAD
439#define OS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
441#if defined (__nuttx__)
443#define OS_RECURSIVE_MUTEX_INITIALIZER {0, SEM_INITIALIZER(1), PTHREAD_MUTEX_RECURSIVE, 0}
444#elif defined (__MACH__)
445#define OS_RECURSIVE_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER
448#define OS_RECURSIVE_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
453extern void os_emscripten_yield();
462#if OPENMRN_FEATURE_MUTEX_FREERTOS
463 mutex->recursive = 0;
464 mutex->sem = xSemaphoreCreateMutex();
467#elif OPENMRN_FEATURE_MUTEX_FAKE
469 mutex->recursive = 0;
471#elif OPENMRN_FEATURE_MUTEX_PTHREAD
472 return pthread_mutex_init(mutex, NULL);
482#if OPENMRN_FEATURE_MUTEX_FREERTOS
483 mutex->recursive = 1;
484 mutex->sem = xSemaphoreCreateRecursiveMutex();
487#elif OPENMRN_FEATURE_MUTEX_FAKE
489 mutex->recursive = 1;
491#elif OPENMRN_FEATURE_MUTEX_PTHREAD
492 pthread_mutexattr_t attr;
495 result = pthread_mutexattr_init(&attr);
501 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
507 return pthread_mutex_init(mutex, &attr);
517#if OPENMRN_FEATURE_MUTEX_FREERTOS
518 vSemaphoreDelete(mutex->sem);
521#elif OPENMRN_FEATURE_MUTEX_FAKE
524#elif OPENMRN_FEATURE_MUTEX_PTHREAD
525 return pthread_mutex_destroy(mutex);
535#if OPENMRN_FEATURE_MUTEX_FREERTOS
537 if (mutex->sem == NULL)
539 if (mutex->recursive)
541 mutex->sem = xSemaphoreCreateRecursiveMutex();
545 mutex->sem = xSemaphoreCreateMutex();
550 if (mutex->recursive)
552 xSemaphoreTakeRecursive(mutex->sem, portMAX_DELAY);
556 xSemaphoreTake(mutex->sem, portMAX_DELAY);
559#elif OPENMRN_FEATURE_MUTEX_FAKE
560 if (mutex->locked && !mutex->recursive)
562 DIE(
"Mutex deadlock.");
566#elif OPENMRN_FEATURE_MUTEX_PTHREAD
567 return pthread_mutex_lock(mutex);
577#if OPENMRN_FEATURE_MUTEX_FREERTOS
578 if (mutex->recursive)
580 xSemaphoreGiveRecursive(mutex->sem);
584 xSemaphoreGive(mutex->sem);
587#elif OPENMRN_FEATURE_MUTEX_FAKE
588 if (mutex->locked <= 0)
590 DIE(
"Unlocking a not locked mutex");
594#elif OPENMRN_FEATURE_MUTEX_PTHREAD
595 return pthread_mutex_unlock(mutex);
606#if OPENMRN_FEATURE_MUTEX_FREERTOS
607 *
sem = xSemaphoreCreateCounting(LONG_MAX, value);
612#elif OPENMRN_FEATURE_MUTEX_FAKE
613 sem->counter = value;
615#elif OPENMRN_FEATURE_MUTEX_PTHREAD
616 pthread_cond_init(&
sem->cond, NULL);
617 pthread_mutex_init(&
sem->mutex, NULL);
618 sem->counter = value;
629#if OPENMRN_FEATURE_MUTEX_FREERTOS
630 vSemaphoreDelete(*
sem);
632#elif OPENMRN_FEATURE_MUTEX_FAKE
634#elif OPENMRN_FEATURE_MUTEX_PTHREAD
635 pthread_cond_destroy(&
sem->cond);
636 pthread_mutex_destroy(&
sem->mutex);
647#if OPENMRN_FEATURE_MUTEX_FREERTOS
648 xSemaphoreGive(*
sem);
650#elif OPENMRN_FEATURE_MUTEX_FAKE
653#elif OPENMRN_FEATURE_MUTEX_PTHREAD
654 pthread_mutex_lock(&
sem->mutex);
656 pthread_cond_signal(&
sem->cond);
657 pthread_mutex_unlock(&
sem->mutex);
662#if OPENMRN_FEATURE_RTOS_FROM_ISR
668OS_INLINE int os_sem_post_from_isr(os_sem_t *
sem,
int *woken)
670 portBASE_TYPE local_woken = 0;
671 xSemaphoreGiveFromISR(*
sem, &local_woken);
672 *woken |= local_woken;
683#if OPENMRN_FEATURE_MUTEX_FREERTOS
684 xSemaphoreTake(*
sem, portMAX_DELAY);
686#elif defined(__EMSCRIPTEN__)
687 while (!
sem->counter)
689 os_emscripten_yield();
693#elif OPENMRN_FEATURE_MUTEX_FAKE
695 DIE(
"Semaphore deadlock.");
699#elif OPENMRN_FEATURE_MUTEX_PTHREAD
700 pthread_mutex_lock(&
sem->mutex);
701 while (
sem->counter == 0)
703 pthread_cond_wait(&
sem->cond, &
sem->mutex);
706 pthread_mutex_unlock(&
sem->mutex);
711#if OPENMRN_FEATURE_SEM_TIMEDWAIT
717OS_INLINE int os_sem_timedwait(os_sem_t *
sem,
long long timeout)
723#if OPENMRN_FEATURE_MUTEX_FREERTOS
724 if (xSemaphoreTake(*
sem, NSEC_TO_TICK(timeout)) == pdTRUE)
733#elif defined(__EMSCRIPTEN__)
734 long long end_time = 0;
750 os_emscripten_yield();
753#elif OPENMRN_FEATURE_MUTEX_PTHREAD
756 gettimeofday(&tv, NULL);
757 timeout += ((
long long)tv.tv_sec * 1000000000LL) + ((
long long) tv.tv_usec * 1000LL);
758 ts.tv_sec = timeout / 1000000000LL;
759 ts.tv_nsec = timeout % 1000000000LL;
760 pthread_mutex_lock(&
sem->mutex);
761 while (
sem->counter == 0)
763 if (pthread_cond_timedwait(&
sem->cond, &
sem->mutex, &ts) == ETIMEDOUT)
765 pthread_mutex_unlock(&
sem->mutex);
771 pthread_mutex_unlock(&
sem->mutex);
779#if !defined (OPENMRN_FEATURE_MUTEX_FREERTOS)
782typedef struct queue_priv
789 unsigned int indexSend;
790 unsigned int indexReceive;
802#if OPENMRN_FEATURE_MUTEX_FREERTOS
803 return xQueueCreate(length, item_size);
805 QueuePriv *q = (QueuePriv*)malloc(
sizeof(QueuePriv));
813 q->buffer = (
char*)malloc(length * item_size);
814 q->itemSize = item_size;
815 q->bytes = length * item_size;
830#if OPENMRN_FEATURE_MUTEX_FREERTOS
831 xQueueSend(queue, data, portMAX_DELAY);
833 QueuePriv *q = (QueuePriv*)queue;
838 memcpy(q->buffer + q->indexSend, data, q->itemSize);
839 q->indexSend += q->itemSize;
840 if (q->indexSend >= q->bytes)
857#if OPENMRN_FEATURE_MUTEX_FREERTOS
858 portTickType ticks = NSEC_TO_TICK(timeout);
860 if (xQueueSend(queue, data, ticks) != pdTRUE)
865 DIE(
"unimplemented.");
877#if OPENMRN_FEATURE_MUTEX_FREERTOS
878 xQueueReceive(queue, data, portMAX_DELAY);
880 QueuePriv *q = (QueuePriv*)queue;
885 memcpy(q->buffer + q->indexReceive, data, q->itemSize);
886 q->indexReceive += q->itemSize;
887 if (q->indexReceive >= q->bytes)
904#if OPENMRN_FEATURE_MUTEX_FREERTOS
905 portTickType ticks = NSEC_TO_TICK(timeout);
907 if (xQueueReceive(queue, data, ticks) != pdTRUE)
912 DIE(
"unimplemented.");
925#if OPENMRN_FEATURE_MUTEX_FREERTOS
926 portBASE_TYPE local_woken;
927 if (xQueueSendFromISR(queue, data, &local_woken) != pdTRUE)
931 *woken |= local_woken;
933 DIE(
"unimplemented.");
944#if OPENMRN_FEATURE_MUTEX_FREERTOS
945 return xQueueIsQueueFullFromISR(queue);
947 DIE(
"unimplemented.");
961#if OPENMRN_FEATURE_MUTEX_FREERTOS
962 portBASE_TYPE local_woken;
963 if (xQueueReceiveFromISR(queue, data, &local_woken) != pdTRUE)
967 *woken |= local_woken;
969 DIE(
"unimplemented.");
980#if OPENMRN_FEATURE_MUTEX_FREERTOS
981 return uxQueueMessagesWaiting(queue);
983 DIE(
"unimplemented.");
994#if OPENMRN_FEATURE_MUTEX_FREERTOS
995 return uxQueueMessagesWaitingFromISR(queue);
997 DIE(
"unimplemented.");
1008#if OPENMRN_FEATURE_MUTEX_FREERTOS
1009 return uxQueueSpacesAvailable(queue);
1011 DIE(
"unimplemented.");
1016#if defined (__FreeRTOS__)
1019#if !defined (portEND_SWITCHING_ISR)
1020#define portEND_SWITCHING_ISR(_woken) \
1023 portYIELD_FROM_ISR(); \
1027#ifdef TARGET_PIC32MX
1029void __attribute__((nomips16)) os_isr_exit_yield_test(
int woken);
1035#define os_isr_exit_yield_test(_woken) \
1038 portEND_SWITCHING_ISR(_woken); \
1049#if defined (__WIN32__)
1053OS_INLINE unsigned sleep(
unsigned seconds)
1055 usleep(seconds * 1000);
OSSem sem[1]
One semaphore required per instance pointer.
#define DIE(MSG)
Unconditionally terminates the current process with a message.
OS_INLINE void os_mq_receive(os_mq_t queue, void *data)
Blocking receive a message from a queue.
#define OS_MQ_FULL
error code for queue being full
OS_INLINE int os_mq_num_pending_from_isr(os_mq_t queue)
Return the number of messages pending in the queue from ISR context.
OS_INLINE os_mq_t os_mq_create(size_t length, size_t item_size)
Create a new message queue.
OS_INLINE int os_recursive_mutex_init(os_mutex_t *mutex)
Initialize recursive mutex.
OS_INLINE int os_mq_send_from_isr(os_mq_t queue, const void *data, int *woken)
Send of a message to a queue from ISR context.
ssize_t os_get_free_heap(void)
OS_INLINE int os_mutex_lock(os_mutex_t *mutex)
Lock a mutex.
OS_INLINE int os_mq_is_full_from_isr(os_mq_t queue)
Check if a queue is full from ISR context.
void os_thread_cancel(os_thread_t thread)
Destroy a thread.
#define OPENMRN_OS_WAIT_FOREVER
maximum timeout period
OS_INLINE int os_thread_once(os_thread_once_t *once, void(*routine)(void))
One time intialization routine.
OS_INLINE int os_thread_get_priority_max(void)
Get the maximum thread priority.
OS_INLINE int os_sem_init(os_sem_t *sem, unsigned int value)
Initialize a semaphore.
OS_INLINE int os_mq_timedsend(os_mq_t queue, const void *data, long long timeout)
Send a message to a queue with a timeout.
OS_INLINE int os_mutex_destroy(os_mutex_t *mutex)
Destroy a mutex.
int appl_main(int argc, char *argv[])
Entry point to application.
OS_INLINE int os_thread_get_priority_min(void)
Get the minimum thread priority.
OS_INLINE int os_sem_post(os_sem_t *sem)
Post a semaphore.
long long os_get_fake_time(void)
Get the fake time for a unit test.
OS_INLINE int os_sem_wait(os_sem_t *sem)
Wait on a semaphore.
OS_INLINE int os_mutex_unlock(os_mutex_t *mutex)
Unock a mutex.
OS_INLINE int os_thread_get_priority(os_thread_t thread)
Return the current thread priority.
OS_INLINE os_thread_t os_thread_self(void)
Return a handle to the calling thread.
OS_INLINE int os_mq_timedreceive(os_mq_t queue, void *data, long long timeout)
Receive a message from a queue.
OS_INLINE int os_mq_receive_from_isr(os_mq_t queue, void *data, int *woken)
Receive a message from a queue from ISR context.
#define OS_MQ_TIMEDOUT
error code for timedout for message queues
OS_INLINE int os_mutex_init(os_mutex_t *mutex)
Initialize mutex.
long long os_get_time_monotonic(void)
Get the monotonic time since the system started.
int os_thread_create(os_thread_t *thread, const char *name, int priority, size_t stack_size, void *(*start_routine)(void *), void *arg)
Creates a thread.
#define OS_INLINE
Forces one definition of each inline function to be compiled.
OS_INLINE int os_sem_destroy(os_sem_t *sem)
Destroy a semaphore.
OS_INLINE int os_mq_num_spaces(os_mq_t queue)
Return the number of spaces available in the queue.
OS_INLINE void os_mq_send(os_mq_t queue, const void *data)
Blocking send of a message to a queue.
OS_INLINE int os_mq_num_pending(os_mq_t queue)
Return the number of messages pending in the queue.
#define OS_MQ_NONE
error code for no error for message queues
#define OS_MQ_EMPTY
error code for the queue being empty