summaryrefslogtreecommitdiff
path: root/libs/os
diff options
context:
space:
mode:
Diffstat (limited to 'libs/os')
-rwxr-xr-xlibs/os/include/os/arch/cortex_m0/os/os_arch.h12
-rwxr-xr-xlibs/os/include/os/arch/cortex_m4/os/os_arch.h12
-rw-r--r--libs/os/include/os/os_mbuf.h12
-rw-r--r--libs/os/include/os/os_mempool.h3
-rw-r--r--libs/os/src/arch/cortex_m0/m0/HAL_CM0.s1
-rwxr-xr-xlibs/os/src/arch/cortex_m0/os_arch_arm.c34
-rwxr-xr-xlibs/os/src/arch/cortex_m4/m4/HAL_CM4.s2
-rwxr-xr-xlibs/os/src/arch/cortex_m4/os_arch_arm.c35
-rw-r--r--libs/os/src/arch/sim/os_arch_sim.c2
-rw-r--r--libs/os/src/os.c4
-rw-r--r--libs/os/src/os_callout.c4
-rw-r--r--libs/os/src/os_eventq.c33
-rw-r--r--libs/os/src/os_mbuf.c181
-rw-r--r--libs/os/src/os_mempool.c74
-rw-r--r--libs/os/src/os_priv.h10
-rw-r--r--libs/os/src/os_task.c3
-rw-r--r--libs/os/src/os_time.c12
-rw-r--r--libs/os/src/test/callout_test.c330
-rw-r--r--libs/os/src/test/eventq_test.c297
-rw-r--r--libs/os/src/test/os_test.c2
-rw-r--r--libs/os/src/test/os_test_priv.h2
21 files changed, 961 insertions, 104 deletions
diff --git a/libs/os/include/os/arch/cortex_m0/os/os_arch.h b/libs/os/include/os/arch/cortex_m0/os/os_arch.h
index e986702a..1a83ba9b 100755
--- a/libs/os/include/os/arch/cortex_m0/os/os_arch.h
+++ b/libs/os/include/os/arch/cortex_m0/os/os_arch.h
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -17,8 +17,8 @@
* under the License.
*/
-#ifndef _OS_ARCH_ARM_H
-#define _OS_ARCH_ARM_H
+#ifndef _OS_ARCH_ARM_H
+#define _OS_ARCH_ARM_H
#include <stdint.h>
#include <mcu/cortex_m0.h>
@@ -48,7 +48,7 @@ typedef uint32_t os_stack_t;
(OS_ALIGN((__nmemb), OS_STACK_ALIGNMENT))
/* Enter a critical section, save processor state, and block interrupts */
-#define OS_ENTER_CRITICAL(__os_sr) (__os_sr = os_arch_save_sr())
+#define OS_ENTER_CRITICAL(__os_sr) (__os_sr = os_arch_save_sr())
/* Exit a critical section, restore processor state and unblock interrupts */
#define OS_EXIT_CRITICAL(__os_sr) (os_arch_restore_sr(__os_sr))
#define OS_ASSERT_CRITICAL() (assert(os_arch_in_critical()))
@@ -63,7 +63,7 @@ void os_arch_init(void);
uint32_t os_arch_start(void);
os_error_t os_arch_os_init(void);
os_error_t os_arch_os_start(void);
-void os_set_env(void);
+void os_set_env(os_stack_t *);
void os_arch_init_task_stack(os_stack_t *sf);
void os_default_irq_asm(void);
@@ -71,4 +71,4 @@ void os_default_irq_asm(void);
void os_bsp_systick_init(uint32_t os_ticks_per_sec, int prio);
void os_bsp_ctx_sw(void);
-#endif /* _OS_ARCH_X86_H */
+#endif /* _OS_ARCH_ARM_H */
diff --git a/libs/os/include/os/arch/cortex_m4/os/os_arch.h b/libs/os/include/os/arch/cortex_m4/os/os_arch.h
index 8c67f09f..9e43a7a2 100755
--- a/libs/os/include/os/arch/cortex_m4/os/os_arch.h
+++ b/libs/os/include/os/arch/cortex_m4/os/os_arch.h
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -17,8 +17,8 @@
* under the License.
*/
-#ifndef _OS_ARCH_ARM_H
-#define _OS_ARCH_ARM_H
+#ifndef _OS_ARCH_ARM_H
+#define _OS_ARCH_ARM_H
#include <stdint.h>
#include "mcu/cortex_m4.h"
@@ -48,7 +48,7 @@ typedef uint32_t os_stack_t;
(OS_ALIGN((__nmemb), OS_STACK_ALIGNMENT))
/* Enter a critical section, save processor state, and block interrupts */
-#define OS_ENTER_CRITICAL(__os_sr) (__os_sr = os_arch_save_sr())
+#define OS_ENTER_CRITICAL(__os_sr) (__os_sr = os_arch_save_sr())
/* Exit a critical section, restore processor state and unblock interrupts */
#define OS_EXIT_CRITICAL(__os_sr) (os_arch_restore_sr(__os_sr))
#define OS_ASSERT_CRITICAL() (assert(os_arch_in_critical()))
@@ -63,7 +63,7 @@ void os_arch_init(void);
uint32_t os_arch_start(void);
os_error_t os_arch_os_init(void);
os_error_t os_arch_os_start(void);
-void os_set_env(void);
+void os_set_env(os_stack_t *);
void os_arch_init_task_stack(os_stack_t *sf);
void os_default_irq_asm(void);
@@ -72,4 +72,4 @@ void os_bsp_systick_init(uint32_t os_tick_per_sec, int prio);
void os_bsp_idle(os_time_t ticks);
void os_bsp_ctx_sw(void);
-#endif /* _OS_ARCH_X86_H */
+#endif /* _OS_ARCH_ARM_H */
diff --git a/libs/os/include/os/os_mbuf.h b/libs/os/include/os/os_mbuf.h
index 74b9548d..f3c48aeb 100644
--- a/libs/os/include/os/os_mbuf.h
+++ b/libs/os/include/os/os_mbuf.h
@@ -259,7 +259,8 @@ struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
/* Duplicate a mbuf from the pool */
struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
-struct os_mbuf * os_mbuf_off(struct os_mbuf *om, int off, int *out_off);
+struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
+ uint16_t *out_off);
/* Copy data from an mbuf to a flat buffer. */
int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
@@ -267,6 +268,9 @@ int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
/* Append data onto a mbuf */
int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+ uint16_t src_off, uint16_t len);
+
/* Free a mbuf */
int os_mbuf_free(struct os_mbuf *mb);
@@ -274,10 +278,14 @@ int os_mbuf_free(struct os_mbuf *mb);
int os_mbuf_free_chain(struct os_mbuf *om);
void os_mbuf_adj(struct os_mbuf *mp, int req_len);
-int os_mbuf_memcmp(const struct os_mbuf *om, int off, const void *data,
+int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data,
int len);
+int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+ const struct os_mbuf *om2, uint16_t offset2,
+ uint16_t len);
struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
+struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
diff --git a/libs/os/include/os/os_mempool.h b/libs/os/include/os/os_mempool.h
index 6b0f24c1..a7316184 100644
--- a/libs/os/include/os/os_mempool.h
+++ b/libs/os/include/os/os_mempool.h
@@ -82,6 +82,9 @@ typedef uint64_t os_membuf_t;
os_error_t os_mempool_init(struct os_mempool *mp, int blocks, int block_size,
void *membuf, char *name);
+/* Checks if a memory block was allocated from the specified mempool. */
+int os_memblock_from(struct os_mempool *mp, void *block_addr);
+
/* Get a memory block from the pool */
void *os_memblock_get(struct os_mempool *mp);
diff --git a/libs/os/src/arch/cortex_m0/m0/HAL_CM0.s b/libs/os/src/arch/cortex_m0/m0/HAL_CM0.s
index 03d79577..de7d46c7 100644
--- a/libs/os/src/arch/cortex_m0/m0/HAL_CM0.s
+++ b/libs/os/src/arch/cortex_m0/m0/HAL_CM0.s
@@ -52,7 +52,6 @@ os_set_env:
.fnstart
.cantunwind
- MOV R0,SP /* Copy MSP to PSP */
MSR PSP,R0
LDR R0,=os_flags
LDRB R0,[R0]
diff --git a/libs/os/src/arch/cortex_m0/os_arch_arm.c b/libs/os/src/arch/cortex_m0/os_arch_arm.c
index 40b92549..ef1be4d6 100755
--- a/libs/os/src/arch/cortex_m0/os_arch_arm.c
+++ b/libs/os/src/arch/cortex_m0/os_arch_arm.c
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -23,6 +23,8 @@
#include <hal/hal_os_tick.h>
#include <bsp/cmsis_nvic.h>
+#include "os_priv.h"
+
/*
* From HAL_CM0.s
*/
@@ -223,13 +225,6 @@ os_arch_os_init(void)
/* Set the SVC interrupt to priority 0 (highest configurable) */
NVIC_SetPriority(SVCall_IRQn, SVC_PRIO);
- /*
- * Set the os environment. This will set stack pointers and, based
- * on the contents of os_flags, will determine if the tasks run in
- * priviliged or un-privileged mode.
- */
- os_set_env();
-
/* Check if privileged or not */
if ((__get_CONTROL() & 1) == 0) {
os_arch_init();
@@ -273,17 +268,26 @@ static inline void svc_os_arch_start(void)
}
/**
- * Start the OS. First check to see if we are running with the correct stack
- * pointer set (PSP) and privilege mode (PRIV).
- *
- *
- * @return os_error_t
+ * Start the OS. First check to see if we are running with the correct stack
+ * pointer set (PSP) and privilege mode (PRIV).
+ *
+ * @return os_error_t
*/
os_error_t
os_arch_os_start(void)
{
os_error_t err;
+ /*
+ * Set the os environment. This will set stack pointers and, based
+ * on the contents of os_flags, will determine if the tasks run in
+ * priviliged or un-privileged mode.
+ *
+ * We switch to using "empty" part of idle task's stack until
+ * the svc_os_arch_start() executes SVC, and we will never return.
+ */
+ os_set_env(g_idle_task.t_stackptr - 1);
+
err = OS_ERR_IN_ISR;
if (__get_IPSR() == 0) {
/*
@@ -304,7 +308,7 @@ os_arch_os_start(void)
err = OS_ERR_PRIV;
break;
case 0x02:
- /*
+ /*
* We are running in Privileged Thread mode w/SP = PSP but we
* are supposed to be un-privileged.
*/
@@ -313,7 +317,7 @@ os_arch_os_start(void)
}
break;
case 0x03:
- /*
+ /*
* We are running in Unprivileged Thread mode w/SP = PSP but we
* are supposed to be privileged.
*/
diff --git a/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s b/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
index c9ae1037..9c6ab521 100755
--- a/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
+++ b/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
@@ -52,7 +52,6 @@ os_set_env:
.fnstart
.cantunwind
- MOV R0,SP /* Copy MSP to PSP */
MSR PSP,R0
LDR R0,=os_flags
LDRB R0,[R0]
@@ -63,6 +62,7 @@ os_set_env:
.fnend
.size os_set_env, .-os_set_env
+
/*--------------------------- os_set_env ------------------------------------*/
diff --git a/libs/os/src/arch/cortex_m4/os_arch_arm.c b/libs/os/src/arch/cortex_m4/os_arch_arm.c
index 2bd084ab..48f69769 100755
--- a/libs/os/src/arch/cortex_m4/os_arch_arm.c
+++ b/libs/os/src/arch/cortex_m4/os_arch_arm.c
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -23,6 +23,8 @@
#include <hal/hal_os_tick.h>
#include <bsp/cmsis_nvic.h>
+#include "os_priv.h"
+
/* Initial program status register */
#define INITIAL_xPSR 0x01000000
@@ -217,13 +219,6 @@ os_arch_os_init(void)
/* Set the SVC interrupt to priority 0 (highest configurable) */
NVIC_SetPriority(SVCall_IRQn, SVC_PRIO);
- /*
- * Set the os environment. This will set stack pointers and, based
- * on the contents of os_flags, will determine if the tasks run in
- * priviliged or un-privileged mode.
- */
- os_set_env();
-
/* Check if privileged or not */
if ((__get_CONTROL() & 1) == 0) {
os_arch_init();
@@ -267,17 +262,27 @@ static inline void svc_os_arch_start(void)
}
/**
- * Start the OS. First check to see if we are running with the correct stack
- * pointer set (PSP) and privilege mode (PRIV).
- *
- *
- * @return os_error_t
+ * Start the OS. First check to see if we are running with the correct stack
+ * pointer set (PSP) and privilege mode (PRIV).
+ *
+ *
+ * @return os_error_t
*/
os_error_t
os_arch_os_start(void)
{
os_error_t err;
+ /*
+ * Set the os environment. This will set stack pointers and, based
+ * on the contents of os_flags, will determine if the tasks run in
+ * privileged or un-privileged mode.
+ *
+ * We switch to using "empty" part of idle task's stack until
+ * the svc_os_arch_start() executes SVC, and we will never return.
+ */
+ os_set_env(g_idle_task.t_stackptr - 1);
+
err = OS_ERR_IN_ISR;
if (__get_IPSR() == 0) {
/*
@@ -298,7 +303,7 @@ os_arch_os_start(void)
err = OS_ERR_PRIV;
break;
case 0x02:
- /*
+ /*
* We are running in Privileged Thread mode w/SP = PSP but we
* are supposed to be un-privileged.
*/
@@ -307,7 +312,7 @@ os_arch_os_start(void)
}
break;
case 0x03:
- /*
+ /*
* We are running in Unprivileged Thread mode w/SP = PSP but we
* are supposed to be privileged.
*/
diff --git a/libs/os/src/arch/sim/os_arch_sim.c b/libs/os/src/arch/sim/os_arch_sim.c
index 287b4fc1..49705220 100644
--- a/libs/os/src/arch/sim/os_arch_sim.c
+++ b/libs/os/src/arch/sim/os_arch_sim.c
@@ -404,7 +404,7 @@ os_arch_os_init(void)
mypid = getpid();
g_current_task = NULL;
- TAILQ_INIT(&g_os_task_list);
+ STAILQ_INIT(&g_os_task_list);
TAILQ_INIT(&g_os_run_list);
TAILQ_INIT(&g_os_sleep_list);
diff --git a/libs/os/src/os.c b/libs/os/src/os.c
index 5ec71ec2..90f972ea 100644
--- a/libs/os/src/os.c
+++ b/libs/os/src/os.c
@@ -19,6 +19,7 @@
#include "os/os.h"
#include "os/queue.h"
+#include "os_priv.h"
#include "hal/hal_os_tick.h"
@@ -105,6 +106,9 @@ os_init(void)
{
os_error_t err;
+ TAILQ_INIT(&g_callout_list);
+ STAILQ_INIT(&g_os_task_list);
+
err = os_arch_os_init();
assert(err == OS_OK);
}
diff --git a/libs/os/src/os_callout.c b/libs/os/src/os_callout.c
index 02462c0b..bc36a195 100644
--- a/libs/os/src/os_callout.c
+++ b/libs/os/src/os_callout.c
@@ -18,12 +18,12 @@
*/
#include "os/os.h"
+#include "os_priv.h"
#include <assert.h>
#include <string.h>
-TAILQ_HEAD(, os_callout) g_callout_list =
- TAILQ_HEAD_INITIALIZER(g_callout_list);
+struct os_callout_list g_callout_list;
static void
_os_callout_init(struct os_callout *c, struct os_eventq *evq, void *ev_arg)
diff --git a/libs/os/src/os_eventq.c b/libs/os/src/os_eventq.c
index b3ff26f7..f9cc2837 100644
--- a/libs/os/src/os_eventq.c
+++ b/libs/os/src/os_eventq.c
@@ -117,6 +117,29 @@ pull_one:
return (ev);
}
+static struct os_event *
+os_eventq_poll_0timo(struct os_eventq **evq, int nevqs)
+{
+ struct os_event *ev;
+ os_sr_t sr;
+ int i;
+
+ ev = NULL;
+
+ OS_ENTER_CRITICAL(sr);
+ for (i = 0; i < nevqs; i++) {
+ ev = STAILQ_FIRST(&evq[i]->evq_list);
+ if (ev) {
+ STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
+ ev->ev_queued = 0;
+ break;
+ }
+ }
+ OS_EXIT_CRITICAL(sr);
+
+ return ev;
+}
+
/**
* Poll the list of event queues specified by the evq parameter
* (size nevqs), and return the "first" event available on any of
@@ -137,6 +160,13 @@ os_eventq_poll(struct os_eventq **evq, int nevqs, os_time_t timo)
int i, j;
os_sr_t sr;
+ /* If the timeout is 0, don't involve the scheduler at all. Grab an event
+ * if one is available, else return immediately.
+ */
+ if (timo == 0) {
+ return os_eventq_poll_0timo(evq, nevqs);
+ }
+
ev = NULL;
OS_ENTER_CRITICAL(sr);
@@ -147,8 +177,7 @@ os_eventq_poll(struct os_eventq **evq, int nevqs, os_time_t timo)
if (ev) {
STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
ev->ev_queued = 0;
- /* Reset the items that already have an evq task set
- */
+ /* Reset the items that already have an evq task set. */
for (j = 0; j < i; j++) {
evq[j]->evq_task = NULL;
}
diff --git a/libs/os/src/os_mbuf.c b/libs/os/src/os_mbuf.c
index 85232d88..a2302df7 100644
--- a/libs/os/src/os_mbuf.c
+++ b/libs/os/src/os_mbuf.c
@@ -37,6 +37,7 @@
#include <assert.h>
#include <string.h>
+#include <limits.h>
STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
@@ -509,6 +510,49 @@ err:
return (rc);
}
+/**
+ * Reads data from one mbuf and appends it to another. On error, the specified
+ * data range may be partially appended. Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst The mbuf to append to.
+ * @param src The mbuf to copy data from.
+ * @param src_off The absolute offset within the source mbuf
+ * chain to read from.
+ * @param len The number of bytes to append.
+ *
+ * @return 0 on success;
+ * OS_EINVAL if the specified range extends beyond
+ * the end of the source mbuf chain.
+ */
+int
+os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+ uint16_t src_off, uint16_t len)
+{
+ const struct os_mbuf *src_cur_om;
+ uint16_t src_cur_off;
+ uint16_t chunk_sz;
+ int rc;
+
+ src_cur_om = os_mbuf_off(src, src_off, &src_cur_off);
+ while (len > 0) {
+ if (src_cur_om == NULL) {
+ return OS_EINVAL;
+ }
+
+ chunk_sz = min(len, src_cur_om->om_len - src_cur_off);
+ rc = os_mbuf_append(dst, src_cur_om->om_data + src_cur_off, chunk_sz);
+ if (rc != 0) {
+ return rc;
+ }
+
+ len -= chunk_sz;
+ src_cur_om = SLIST_NEXT(src_cur_om, om_next);
+ src_cur_off = 0;
+ }
+
+ return 0;
+}
/**
* Duplicate a chain of mbufs. Return the start of the duplicated chain.
@@ -576,26 +620,30 @@ err:
* NULL if the specified offset is out of bounds.
*/
struct os_mbuf *
-os_mbuf_off(struct os_mbuf *om, int off, int *out_off)
+os_mbuf_off(const struct os_mbuf *om, int off, uint16_t *out_off)
{
struct os_mbuf *next;
+ struct os_mbuf *cur;
+
+ /* Cast away const. */
+ cur = (struct os_mbuf *)om;
while (1) {
- if (om == NULL) {
+ if (cur == NULL) {
return NULL;
}
- next = SLIST_NEXT(om, om_next);
+ next = SLIST_NEXT(cur, om_next);
- if (om->om_len > off ||
- (om->om_len == off && next == NULL)) {
+ if (cur->om_len > off ||
+ (cur->om_len == off && next == NULL)) {
*out_off = off;
- return om;
+ return cur;
}
- off -= om->om_len;
- om = next;
+ off -= cur->om_len;
+ cur = next;
}
}
@@ -739,14 +787,14 @@ os_mbuf_adj(struct os_mbuf *mp, int req_len)
*
* @return 0 if both memory regions are identical;
* A memcmp return code if there is a mismatch;
- * -1 if the mbuf is too short.
+ * INT_MAX if the mbuf is too short.
*/
int
-os_mbuf_memcmp(const struct os_mbuf *om, int off, const void *data, int len)
+os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len)
{
- int chunk_sz;
- int data_off;
- int om_off;
+ uint16_t chunk_sz;
+ uint16_t data_off;
+ uint16_t om_off;
int rc;
if (len <= 0) {
@@ -754,10 +802,10 @@ os_mbuf_memcmp(const struct os_mbuf *om, int off, const void *data, int len)
}
data_off = 0;
- om = os_mbuf_off((struct os_mbuf *)om, off, &om_off);
+ om = os_mbuf_off(om, off, &om_off);
while (1) {
if (om == NULL) {
- return -1;
+ return INT_MAX;
}
chunk_sz = min(om->om_len - om_off, len - data_off);
@@ -777,12 +825,84 @@ os_mbuf_memcmp(const struct os_mbuf *om, int off, const void *data, int len)
om_off = 0;
if (om == NULL) {
- return -1;
+ return INT_MAX;
}
}
}
/**
+ * Compares the contents of two mbuf chains. The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter. Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1 The first mbuf chain to compare.
+ * @param offset1 The absolute offset within om1 at which to
+ * start the comparison.
+ * @param om2 The second mbuf chain to compare.
+ * @param offset2 The absolute offset within om2 at which to
+ * start the comparison.
+ * @param len The number of bytes to compare.
+ *
+ * @return 0 if both mbuf segments are identical;
+ * A memcmp() return code if the segment contents
+ * differ;
+ * INT_MAX if a specified range extends beyond the
+ * end of its corresponding mbuf chain.
+ */
+int
+os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+ const struct os_mbuf *om2, uint16_t offset2,
+ uint16_t len)
+{
+ const struct os_mbuf *cur1;
+ const struct os_mbuf *cur2;
+ uint16_t bytes_remaining;
+ uint16_t chunk_sz;
+ uint16_t om1_left;
+ uint16_t om2_left;
+ uint16_t om1_off;
+ uint16_t om2_off;
+ int rc;
+
+ cur1 = os_mbuf_off(om1, offset1, &om1_off);
+ cur2 = os_mbuf_off(om2, offset2, &om2_off);
+
+ bytes_remaining = len;
+ while (1) {
+ if (bytes_remaining == 0) {
+ return 0;
+ }
+
+ while (cur1 != NULL && om1_off >= cur1->om_len) {
+ cur1 = SLIST_NEXT(cur1, om_next);
+ om1_off = 0;
+ }
+ while (cur2 != NULL && om2_off >= cur2->om_len) {
+ cur2 = SLIST_NEXT(cur2, om_next);
+ om2_off = 0;
+ }
+
+ if (cur1 == NULL || cur2 == NULL) {
+ return INT_MAX;
+ }
+
+ om1_left = cur1->om_len - om1_off;
+ om2_left = cur2->om_len - om2_off;
+ chunk_sz = min(min(om1_left, om2_left), bytes_remaining);
+
+ rc = memcmp(cur1->om_data + om1_off, cur2->om_data + om2_off,
+ chunk_sz);
+ if (rc != 0) {
+ return rc;
+ }
+
+ om1_off += chunk_sz;
+ om2_off += chunk_sz;
+ bytes_remaining -= chunk_sz;
+ }
+}
+
+/**
* Increases the length of an mbuf chain by adding data to the front. If there
* is insufficient room in the leading mbuf, additional mbufs are allocated and
* prepended as necessary. If this function fails to allocate an mbuf, the
@@ -851,6 +971,33 @@ os_mbuf_prepend(struct os_mbuf *om, int len)
}
/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous. If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om The mbuf chain to prepend to.
+ * @param len The number of bytes to prepend and pullup.
+ *
+ * @return The modified mbuf on success;
+ * NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *
+os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len)
+{
+ om = os_mbuf_prepend(om, len);
+ if (om == NULL) {
+ return NULL;
+ }
+
+ om = os_mbuf_pullup(om, len);
+ if (om == NULL) {
+ return NULL;
+ }
+
+ return om;
+}
+
+/**
* Copies the contents of a flat buffer into an mbuf chain, starting at the
* specified destination offset. If the mbuf is too small for the source data,
* it is extended as necessary. If the destination mbuf contains a packet
@@ -870,8 +1017,8 @@ os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len)
struct os_mbuf *next;
struct os_mbuf *cur;
const uint8_t *sptr;
+ uint16_t cur_off;
int copylen;
- int cur_off;
int rc;
/* Find the mbuf,offset pair for the start of the destination. */
diff --git a/libs/os/src/os_mempool.c b/libs/os/src/os_mempool.c
index 1e7428ca..e940ba42 100644
--- a/libs/os/src/os_mempool.c
+++ b/libs/os/src/os_mempool.c
@@ -41,21 +41,29 @@ STAILQ_HEAD(, os_mempool) g_os_mempool_list =
* @return os_error_t
*/
os_error_t
-os_mempool_init(struct os_mempool *mp, int blocks, int block_size, void *membuf,
- char *name)
+os_mempool_init(struct os_mempool *mp, int blocks, int block_size,
+ void *membuf, char *name)
{
int true_block_size;
uint8_t *block_addr;
struct os_memblock *block_ptr;
/* Check for valid parameters */
- if ((!mp) || (!membuf) || (blocks <= 0) || (block_size <= 0)) {
+ if ((!mp) || (blocks < 0) || (block_size <= 0)) {
return OS_INVALID_PARM;
}
- /* Blocks need to be sized properly and memory buffer should be aligned */
- if (((uint32_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
- return OS_MEM_NOT_ALIGNED;
+ if ((!membuf) && (blocks != 0)) {
+ return OS_INVALID_PARM;
+ }
+
+ if (membuf != NULL) {
+ /* Blocks need to be sized properly and memory buffer should be
+ * aligned
+ */
+ if (((uint32_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
+ return OS_MEM_NOT_ALIGNED;
+ }
}
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(block_size);
@@ -86,6 +94,42 @@ os_mempool_init(struct os_mempool *mp, int blocks, int block_size, void *membuf,
}
/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp The mempool to check as parent.
+ * @param block_addr The memory block to check as child.
+ *
+ * @return 0 if the block does not belong to the mempool;
+ * 1 if the block does belong to the mempool.
+ */
+int
+os_memblock_from(struct os_mempool *mp, void *block_addr)
+{
+ uint32_t true_block_size;
+ uint32_t baddr32;
+ uint32_t end;
+
+ _Static_assert(sizeof block_addr == sizeof baddr32,
+ "Pointer to void must be 32-bits.");
+
+ baddr32 = (uint32_t)block_addr;
+ true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp->mp_block_size);
+ end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
+
+ /* Check that the block is in the memory buffer range. */
+ if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
+ return 0;
+ }
+
+ /* All freed blocks should be on true block size boundaries! */
+ if (((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
* os memblock get
*
* Get a memory block from a memory pool
@@ -135,9 +179,6 @@ os_error_t
os_memblock_put(struct os_mempool *mp, void *block_addr)
{
os_sr_t sr;
- uint32_t end;
- uint32_t true_block_size;
- uint32_t baddr32;
struct os_memblock *block;
/* Make sure parameters are valid */
@@ -146,23 +187,10 @@ os_memblock_put(struct os_mempool *mp, void *block_addr)
}
/* Check that the block we are freeing is a valid block! */
- baddr32 = (uint32_t)block_addr;
- true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp->mp_block_size);
- end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
- if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
- return OS_INVALID_PARM;
- }
-
- /* All freed blocks should be on true block size boundaries! */
- if (((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
+ if (!os_memblock_from(mp, block_addr)) {
return OS_INVALID_PARM;
}
- /*
- * XXX: we should do boundary checks here! The block had better be within
- * the pool. If it fails, do we return an error or assert()? Add this when
- * we add the memory debug.
- */
block = (struct os_memblock *)block_addr;
OS_ENTER_CRITICAL(sr);
diff --git a/libs/os/src/os_priv.h b/libs/os/src/os_priv.h
index dfc9e384..b5c8f65e 100644
--- a/libs/os/src/os_priv.h
+++ b/libs/os/src/os_priv.h
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -20,11 +20,17 @@
#ifndef H_OS_PRIV_
#define H_OS_PRIV_
+#include "os/queue.h"
+
TAILQ_HEAD(os_task_list, os_task);
+TAILQ_HEAD(os_callout_list, os_callout);
+STAILQ_HEAD(os_task_stailq, os_task);
+extern struct os_task g_idle_task;
extern struct os_task_list g_os_run_list;
extern struct os_task_list g_os_sleep_list;
-extern struct os_task_list g_os_task_list;
+extern struct os_task_stailq g_os_task_list;
extern struct os_task *g_current_task;
+extern struct os_callout_list g_callout_list;
#endif
diff --git a/libs/os/src/os_task.c b/libs/os/src/os_task.c
index 55c1da24..e48fdf97 100644
--- a/libs/os/src/os_task.c
+++ b/libs/os/src/os_task.c
@@ -19,12 +19,13 @@
#include "os/os.h"
+#include "os_priv.h"
#include <string.h>
uint8_t g_task_id;
-STAILQ_HEAD(, os_task) g_os_task_list = STAILQ_HEAD_INITIALIZER(g_os_task_list);
+struct os_task_stailq g_os_task_list;
static void
_clear_stack(os_stack_t *stack_bottom, int size)
diff --git a/libs/os/src/os_time.c b/libs/os/src/os_time.c
index 2ce379e8..4ef439f5 100644
--- a/libs/os/src/os_time.c
+++ b/libs/os/src/os_time.c
@@ -97,10 +97,14 @@ os_time_advance(int ticks)
assert(ticks >= 0);
if (ticks > 0) {
- os_time_tick(ticks);
- os_callout_tick();
- os_sched_os_timer_exp();
- os_sched(NULL);
+ if (!os_started()) {
+ g_os_time += ticks;
+ } else {
+ os_time_tick(ticks);
+ os_callout_tick();
+ os_sched_os_timer_exp();
+ os_sched(NULL);
+ }
}
}
diff --git a/libs/os/src/test/callout_test.c b/libs/os/src/test/callout_test.c
new file mode 100644
index 00000000..4e3811d7
--- /dev/null
+++ b/libs/os/src/test/callout_test.c
@@ -0,0 +1,330 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "testutil/testutil.h"
+#include "os/os.h"
+#include "os_test_priv.h"
+#include "os/os_eventq.h"
+#include "os/os_callout.h"
+#include "os/os_time.h"
+
+/* Task 1 for sending */
+#define CALLOUT_STACK_SIZE (5120)
+#define SEND_CALLOUT_TASK_PRIO (1)
+struct os_task callout_task_struct_send;
+os_stack_t callout_task_stack_send[CALLOUT_STACK_SIZE];
+
+#define RECEIVE_CALLOUT_TASK_PRIO (2)
+struct os_task callout_task_struct_receive;
+os_stack_t callout_task_stack_receive[CALLOUT_STACK_SIZE];
+
+/* Delearing variables for callout_func */
+struct os_callout_func callout_func_test;
+
+/* The event to be sent*/
+struct os_eventq callout_evq;
+struct os_event callout_ev;
+
+/* The callout_stop task */
+#define SEND_STOP_CALLOUT_TASK_PRIO (3)
+struct os_task callout_task_struct_stop_send;
+os_stack_t callout_task_stack_stop_send[CALLOUT_STACK_SIZE];
+
+#define RECEIVE_STOP_CALLOUT_TASK_PRIO (4)
+struct os_task callout_task_struct_stop_receive;
+os_stack_t callout_task_stack_stop_receive[CALLOUT_STACK_SIZE];
+
+/* Delearing variables for callout_stop_func */
+#define MULTI_SIZE (2)
+struct os_callout_func callout_func_stop_test[MULTI_SIZE];
+
+/* The event to be sent*/
+struct os_eventq callout_stop_evq[MULTI_SIZE];
+struct os_event callout_stop_ev;
+
+/* Declearing varables for callout_speak */
+#define SPEAK_CALLOUT_TASK_PRIO (5)
+struct os_task callout_task_struct_speak;
+os_stack_t callout_task_stack_speak[CALLOUT_STACK_SIZE];
+
+/* Declearing varaibles for listen */
+#define LISTEN_CALLOUT_TASK_PRIO (6)
+struct os_task callout_task_struct_listen;
+os_stack_t callout_task_stack_listen[CALLOUT_STACK_SIZE];
+
+struct os_callout_func callout_func_speak;
+
+/* Global variables to be used by the callout functions */
+int p;
+int q;
+int t;
+/* This is the function for callout_init*/
+void
+my_callout_func(void *arg)
+{
+ p = 4;
+}
+
+/* This is the function for callout_init of stop test_case*/
+void
+my_callout_stop_func(void *arg)
+{
+ q = 1;
+}
+/* This is the function for callout_init for speak test_case*/
+void
+my_callout_speak_func(void *arg)
+{
+ t = 2;
+}
+
+/* This is a callout task to send data */
+void
+callout_task_send(void *arg )
+{
+ int i;
+ /* Should say whether callout is armed or not */
+ i= os_callout_queued(&callout_func_test.cf_c);
+ TEST_ASSERT(i == 0);
+
+ /* Arm the callout */
+ i = os_callout_reset(&callout_func_test.cf_c, OS_TICKS_PER_SEC/ 50);
+ TEST_ASSERT_FATAL(i == 0);
+
+ /* Should say whether callout is armed or not */
+ i = os_callout_queued(&callout_func_test.cf_c);
+ TEST_ASSERT(i == 1);
+
+ /* Send the callout */
+ os_time_delay(OS_TICKS_PER_SEC );
+}
+
+/* This is the callout to receive data */
+void
+callout_task_receive( void *arg)
+{
+ int i;
+ struct os_event *event;
+ struct os_callout_func *callout;
+ os_time_t now;
+ os_time_t tm;
+ os_sr_t sr;
+ /* Recieve using the os_eventq_poll */
+ event = os_eventq_poll(&callout_func_test.cf_c.c_evq, 1, OS_WAIT_FOREVER);
+ TEST_ASSERT(event->ev_type == OS_EVENT_T_TIMER);
+ TEST_ASSERT(event->ev_arg == NULL);
+ callout = (struct os_callout_func *)event;
+ TEST_ASSERT(callout->cf_func == my_callout_func);
+
+ /* Should say whether callout is armed or not */
+ i = os_callout_queued(&callout_func_test.cf_c);
+ TEST_ASSERT(i == 0);
+
+ OS_ENTER_CRITICAL(sr);
+ now = os_time_get();
+ tm = os_callout_wakeup_ticks(now);
+ TEST_ASSERT(tm == OS_TIMEOUT_NEVER);
+ OS_EXIT_CRITICAL(sr);
+
+ /* Finishes the test when OS has been started */
+ os_test_restart();
+
+}
+
+/* This is callout to send the stop_callout */
+void
+callout_task_stop_send( void *arg)
+{
+ int k;
+ int j;
+ /* Should say whether callout is armed or not */
+ for(k = 0; k<MULTI_SIZE; k++){
+ j = os_callout_queued(&callout_func_stop_test[k].cf_c);
+ TEST_ASSERT(j == 0);
+ }
+
+
+ /* Show that callout is not armed after calling callout_stop */
+ for(k = 0; k<MULTI_SIZE; k++){
+ os_callout_stop(&callout_func_stop_test[k].cf_c);
+ j = os_callout_queued(&callout_func_stop_test[k].cf_c);
+ TEST_ASSERT(j == 0);
+ }
+ /* Arm the callout */
+ for(k = 0; k<MULTI_SIZE; k++){
+ j = os_callout_reset(&callout_func_stop_test[k].cf_c, OS_TICKS_PER_SEC/ 50);
+ TEST_ASSERT_FATAL(j == 0);
+ }
+ os_time_delay( OS_TICKS_PER_SEC );
+}
+
+/* This is the callout to receive stop_callout data */
+void
+callout_task_stop_receive( void *arg )
+{
+ int k;
+ struct os_event *event;
+ struct os_callout_func *callout;
+ /* Recieving using the os_eventq_poll */
+ for(k=0; k<MULTI_SIZE; k++){
+ event = os_eventq_poll(&callout_func_stop_test[k].cf_c.c_evq, 1,
+ OS_WAIT_FOREVER);
+ TEST_ASSERT(event->ev_type == OS_EVENT_T_TIMER);
+ TEST_ASSERT(event->ev_arg == NULL);
+ callout = (struct os_callout_func *)event;
+ TEST_ASSERT(callout->cf_func == my_callout_stop_func);
+
+
+ }
+
+ /* Show that event is removed from the queued after calling callout_stop */
+ for(k=0; k<MULTI_SIZE; k++){
+ os_callout_stop(&callout_func_stop_test[k].cf_c);
+ /* Testing that the event has been removed from queue */
+ TEST_ASSERT_FATAL(1);
+ }
+ /* Finishes the test when OS has been started */
+ os_test_restart();
+
+}
+
+/* This is a callout task to send data */
+void
+callout_task_stop_speak( void *arg )
+{
+ int i;
+ /* Arm the callout */
+ i = os_callout_reset(&callout_func_speak.cf_c, OS_TICKS_PER_SEC/ 50);
+ TEST_ASSERT_FATAL(i == 0);
+
+ /* should say whether callout is armed or not */
+ i = os_callout_queued(&callout_func_speak.cf_c);
+ TEST_ASSERT(i == 1);
+
+ os_callout_stop(&callout_func_speak.cf_c);
+
+ /* Send the callout */
+ os_time_delay(OS_TICKS_PER_SEC/ 100 );
+ /* Finishes the test when OS has been started */
+ os_test_restart();
+}
+
+void
+callout_task_stop_listen( void *arg )
+{
+ struct os_event *event;
+ struct os_callout_func *callout;
+ event = os_eventq_get(callout_func_speak.cf_c.c_evq);
+ TEST_ASSERT_FATAL(0);
+ callout = (struct os_callout_func *)event;
+ TEST_ASSERT(callout->cf_func == my_callout_speak_func);
+
+}
+
+/* Test case to test the basics of the callout */
+TEST_CASE(callout_test)
+{
+
+ /* Initializing the OS */
+ os_init();
+
+ /* Initialize the sending task */
+ os_task_init(&callout_task_struct_send, "callout_task_send",
+ callout_task_send, NULL, SEND_CALLOUT_TASK_PRIO, OS_WAIT_FOREVER,
+ callout_task_stack_send, CALLOUT_STACK_SIZE);
+
+ /* Initialize the receive task */
+ os_task_init(&callout_task_struct_receive, "callout_task_receive",
+ callout_task_receive, NULL, RECEIVE_CALLOUT_TASK_PRIO, OS_WAIT_FOREVER,
+ callout_task_stack_receive, CALLOUT_STACK_SIZE);
+
+ os_eventq_init(&callout_evq);
+
+ /* Initialize the callout function */
+ os_callout_func_init(&callout_func_test, &callout_evq,
+ my_callout_func, NULL);
+
+ /* Does not return until OS_restart is called */
+ os_start();
+}
+
+/* Test case of the callout_task_stop */
+TEST_CASE(callout_test_stop)
+{
+ int k;
+ /* Initializing the OS */
+ os_init();
+
+ /* Initialize the sending task */
+ os_task_init(&callout_task_struct_stop_send, "callout_task_stop_send",
+ callout_task_stop_send, NULL, SEND_STOP_CALLOUT_TASK_PRIO, OS_WAIT_FOREVER,
+ callout_task_stack_stop_send, CALLOUT_STACK_SIZE);
+
+ /* Initialize the receiving task */
+ os_task_init(&callout_task_struct_stop_receive, "callout_task_stop_receive",
+ callout_task_stop_receive, NULL, RECEIVE_STOP_CALLOUT_TASK_PRIO,
+ OS_WAIT_FOREVER, callout_task_stack_stop_receive, CALLOUT_STACK_SIZE);
+
+ for(k = 0; k< MULTI_SIZE; k++){
+ os_eventq_init(&callout_stop_evq[k]);
+ }
+
+ /* Initialize the callout function */
+ for(k = 0; k<MULTI_SIZE; k++){
+ os_callout_func_init(&callout_func_stop_test[k], &callout_stop_evq[k],
+ my_callout_stop_func, NULL);
+ }
+
+ /* Does not return until OS_restart is called */
+ os_start();
+
+}
+
+/* Test case to test case for speak and listen */
+TEST_CASE(callout_test_speak)
+{
+ /* Initializing the OS */
+ os_init();
+
+ /* Initialize the sending task */
+ os_task_init(&callout_task_struct_speak, "callout_task_speak",
+ callout_task_stop_speak, NULL, SPEAK_CALLOUT_TASK_PRIO, OS_WAIT_FOREVER,
+ callout_task_stack_speak, CALLOUT_STACK_SIZE);
+
+ /* Initialize the receive task */
+ os_task_init(&callout_task_struct_listen, "callout_task_listen",
+ callout_task_stop_listen, NULL, LISTEN_CALLOUT_TASK_PRIO, OS_WAIT_FOREVER,
+ callout_task_stack_listen, CALLOUT_STACK_SIZE);
+
+ os_eventq_init(&callout_evq);
+
+ /* Initialize the callout function */
+ os_callout_func_init(&callout_func_speak, &callout_evq,
+ my_callout_speak_func, NULL);
+ /* Does not return until OS_restart is called */
+ os_start();
+
+}
+
+TEST_SUITE(os_callout_test_suite)
+{
+ callout_test();
+ callout_test_stop();
+ callout_test_speak();
+}
diff --git a/libs/os/src/test/eventq_test.c b/libs/os/src/test/eventq_test.c
index 29e5fe30..cb1ed94b 100644
--- a/libs/os/src/test/eventq_test.c
+++ b/libs/os/src/test/eventq_test.c
@@ -17,21 +17,21 @@
* under the License.
*/
-
+#include <string.h>
#include "testutil/testutil.h"
#include "os/os.h"
#include "os_test_priv.h"
#include "os/os_eventq.h"
#define MY_STACK_SIZE (5120)
-
-/*Task 1 sending task*/
+#define POLL_STACK_SIZE (4096)
+/* Task 1 sending task */
/* Define task stack and task object */
#define SEND_TASK_PRIO (1)
struct os_task eventq_task_s;
os_stack_t eventq_task_stack_s[MY_STACK_SIZE];
-/*Task 2 receiving task*/
+/* Task 2 receiving task */
#define RECEIVE_TASK_PRIO (2)
struct os_task eventq_task_r;
os_stack_t eventq_task_stack_r[MY_STACK_SIZE];
@@ -48,6 +48,39 @@ struct os_event m_event[SIZE_MULTI_EVENT];
/* Setting the event to send and receive multiple data */
uint8_t my_event_type = 1;
+/* Setting up data for the poll */
+/* Define the task stack for the eventq_task_poll_send */
+#define SEND_TASK_POLL_PRIO (3)
+struct os_task eventq_task_poll_s;
+os_stack_t eventq_task_stack_poll_s[POLL_STACK_SIZE];
+
+/* Define the task stack for the eventq_task_poll_receive */
+#define RECEIVE_TASK_POLL_PRIO (4)
+struct os_task eventq_task_poll_r;
+os_stack_t eventq_task_stack_poll_r[POLL_STACK_SIZE ];
+
+/* Setting the data for the poll timeout */
+/* Define the task stack for the eventq_task_poll_timeout_send */
+#define SEND_TASK_POLL_TIMEOUT_PRIO (5)
+struct os_task eventq_task_poll_timeout_s;
+os_stack_t eventq_task_stack_poll_timeout_s[POLL_STACK_SIZE];
+
+/* Define the task stack for the eventq_task_poll_receive */
+#define RECEIVE_TASK_POLL_TIMEOUT_PRIO (6)
+struct os_task eventq_task_poll_timeout_r;
+os_stack_t eventq_task_stack_poll_timeout_r[POLL_STACK_SIZE];
+
+/* Setting the data for the poll single */
+/* Define the task stack for the eventq_task_poll_single_send */
+#define SEND_TASK_POLL_SINGLE_PRIO (7)
+struct os_task eventq_task_poll_single_s;
+os_stack_t eventq_task_stack_poll_single_s[POLL_STACK_SIZE];
+
+/* Define the task stack for the eventq_task_poll_single_receive */
+#define RECEIVE_TASK_POLL_SINGLE_PRIO (8)
+struct os_task eventq_task_poll_single_r;
+os_stack_t eventq_task_stack_poll_single_r[POLL_STACK_SIZE];
+
/* This is the task function to send data */
void
eventq_task_send(void *arg)
@@ -95,6 +128,138 @@ eventq_task_receive(void *arg)
os_test_restart();
}
+void
+eventq_task_poll_send(void *arg)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ int i;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ m_event[i].ev_type = i + 10;
+ m_event[i].ev_arg = NULL;
+
+ /* Put and send */
+ os_eventq_put(eventqs[i], &m_event[i]);
+ os_time_delay(OS_TICKS_PER_SEC / 2);
+ }
+
+ /* This task sleeps until the receive task completes the test. */
+ os_time_delay(1000000);
+}
+
+void
+eventq_task_poll_receive(void *arg)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ struct os_event *event;
+ int i;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ /* Recieving using the os_eventq_poll*/
+ for (i = 0; i < SIZE_MULTI_EVENT; i++) {
+ event = os_eventq_poll(eventqs, SIZE_MULTI_EVENT, OS_WAIT_FOREVER);
+ TEST_ASSERT(event->ev_type == i +10);
+ }
+
+ /* Finishes the test when OS has been started */
+ os_test_restart();
+
+}
+
+/* Sending with a time failure */
+void
+eventq_task_poll_timeout_send(void *arg)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ int i;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ os_time_delay(1000);
+
+ /* Put and send */
+ os_eventq_put(eventqs[i], &m_event[i]);
+ os_time_delay(OS_TICKS_PER_SEC / 2);
+ }
+
+ /* This task sleeps until the receive task completes the test. */
+ os_time_delay(1000000);
+
+}
+
+/* Receiving multiple event queues with a time failure */
+void
+eventq_task_poll_timeout_receive(void *arg)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ struct os_event *event;
+ int i;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ /* Recieving using the os_eventq_poll_timeout*/
+ for (i = 0; i < SIZE_MULTI_EVENT; i++) {
+ event = os_eventq_poll(eventqs, SIZE_MULTI_EVENT, 200);
+ TEST_ASSERT(event == NULL);
+ }
+
+ /* Finishes the test when OS has been started */
+ os_test_restart();
+
+}
+
+/* Sending a single event to poll */
+void
+eventq_task_poll_single_send(void *arg)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ int i;
+ int position = 2;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ /* Put and send */
+ os_eventq_put(eventqs[position], &m_event[position]);
+ os_time_delay(OS_TICKS_PER_SEC / 2);
+
+ /* This task sleeps until the receive task completes the test. */
+ os_time_delay(1000000);
+}
+
+/* Recieving the single event */
+void
+eventq_task_poll_single_receive(void *arg)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ struct os_event *event;
+ int i;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ /* Recieving using the os_eventq_poll*/
+ event = os_eventq_poll(eventqs, SIZE_MULTI_EVENT, OS_WAIT_FOREVER);
+ TEST_ASSERT(event->ev_type == 20);
+
+ /* Finishes the test when OS has been started */
+ os_test_restart();
+}
+
TEST_CASE(event_test_sr)
{
int i;
@@ -121,7 +286,131 @@ TEST_CASE(event_test_sr)
}
+/* To test for the basic function of os_eventq_poll() */
+TEST_CASE(event_test_poll_sr)
+{
+ int i;
+
+ /* Initializing the OS */
+ os_init();
+ /* Initialize the task */
+ os_task_init(&eventq_task_poll_s, "eventq_task_poll_s", eventq_task_poll_send,
+ NULL, SEND_TASK_POLL_PRIO, OS_WAIT_FOREVER, eventq_task_stack_poll_s,
+ POLL_STACK_SIZE);
+
+ /* Receive events and check whether the eevnts are correctly received */
+ os_task_init(&eventq_task_poll_r, "eventq_task_r", eventq_task_poll_receive,
+ NULL, RECEIVE_TASK_POLL_PRIO, OS_WAIT_FOREVER, eventq_task_stack_poll_r,
+ POLL_STACK_SIZE);
+
+ /* Initializing the eventqs. */
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ os_eventq_init(&multi_eventq[i]);
+ }
+
+ /* Does not return until OS_restart is called */
+ os_start();
+
+}
+
+/* Test case for poll timeout */
+TEST_CASE(event_test_poll_timeout_sr)
+{
+ int i;
+
+ /* Initializing the OS */
+ os_init();
+ /* Initialize the task */
+ os_task_init(&eventq_task_poll_timeout_s, "eventq_task_poll_timeout_s",
+ eventq_task_poll_timeout_send, NULL, SEND_TASK_POLL_TIMEOUT_PRIO,
+ OS_WAIT_FOREVER, eventq_task_stack_poll_timeout_s, POLL_STACK_SIZE);
+
+ /* Receive events and check whether the eevnts are correctly received */
+ os_task_init(&eventq_task_poll_timeout_r, "eventq_task_timeout_r",
+ eventq_task_poll_timeout_receive, NULL, RECEIVE_TASK_POLL_TIMEOUT_PRIO,
+ OS_WAIT_FOREVER, eventq_task_stack_poll_timeout_r, POLL_STACK_SIZE);
+
+ /* Initializing the eventqs. */
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ os_eventq_init(&multi_eventq[i]);
+
+ m_event[i].ev_type = i + 10;
+ m_event[i].ev_arg = NULL;
+ }
+
+ /* Does not return until OS_restart is called */
+ os_start();
+
+}
+
+/* The case for poll single */
+/* Test case for poll timeout */
+TEST_CASE(event_test_poll_single_sr)
+{
+ int i;
+
+ /* Initializing the OS */
+ os_init();
+ /* Initialize the task */
+ os_task_init(&eventq_task_poll_single_s, "eventq_task_poll_single_s",
+ eventq_task_poll_single_send, NULL, SEND_TASK_POLL_SINGLE_PRIO,
+ OS_WAIT_FOREVER, eventq_task_stack_poll_single_s, POLL_STACK_SIZE);
+
+ /* Receive events and check whether the eevnts are correctly received */
+ os_task_init(&eventq_task_poll_single_r, "eventq_task_single_r",
+ eventq_task_poll_single_receive, NULL, RECEIVE_TASK_POLL_SINGLE_PRIO,
+ OS_WAIT_FOREVER, eventq_task_stack_poll_single_r, POLL_STACK_SIZE);
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ os_eventq_init(&multi_eventq[i]);
+
+ m_event[i].ev_type = 10 * i;
+ m_event[i].ev_arg = NULL;
+ }
+
+ /* Does not return until OS_restart is called */
+ os_start();
+
+}
+
+/**
+ * Tests eventq_poll() with a timeout of 0. This should not involve the
+ * scheduler at all, so it should work without starting the OS.
+ */
+TEST_CASE(event_test_poll_0timo)
+{
+ struct os_eventq *eventqs[SIZE_MULTI_EVENT];
+ struct os_event *evp;
+ struct os_event ev;
+ int i;
+
+ for (i = 0; i < SIZE_MULTI_EVENT; i++){
+ os_eventq_init(&multi_eventq[i]);
+ eventqs[i] = &multi_eventq[i];
+ }
+
+ evp = os_eventq_poll(eventqs, SIZE_MULTI_EVENT, 0);
+ TEST_ASSERT(evp == NULL);
+
+ /* Ensure no eventq thinks a task is waiting on it. */
+ for (i = 0; i < SIZE_MULTI_EVENT; i++) {
+ TEST_ASSERT(eventqs[i]->evq_task == NULL);
+ }
+
+ /* Put an event on one of the queues. */
+ memset(&ev, 0, sizeof ev);
+ ev.ev_type = 1;
+ os_eventq_put(eventqs[3], &ev);
+
+ evp = os_eventq_poll(eventqs, SIZE_MULTI_EVENT, 0);
+ TEST_ASSERT(evp == &ev);
+}
+
TEST_SUITE(os_eventq_test_suite)
{
event_test_sr();
+ event_test_poll_sr();
+ event_test_poll_timeout_sr();
+ event_test_poll_single_sr();
+ event_test_poll_0timo();
}
diff --git a/libs/os/src/test/os_test.c b/libs/os/src/test/os_test.c
index 1b3af1ab..48f07206 100644
--- a/libs/os/src/test/os_test.c
+++ b/libs/os/src/test/os_test.c
@@ -31,7 +31,7 @@ os_test_all(void)
os_sem_test_suite();
os_mbuf_test_suite();
os_eventq_test_suite();
-
+ os_callout_test_suite();
return tu_case_failed;
}
diff --git a/libs/os/src/test/os_test_priv.h b/libs/os/src/test/os_test_priv.h
index 5193c33b..e923a6fa 100644
--- a/libs/os/src/test/os_test_priv.h
+++ b/libs/os/src/test/os_test_priv.h
@@ -27,6 +27,6 @@ int os_mbuf_test_suite(void);
int os_mutex_test_suite(void);
int os_sem_test_suite(void);
int os_eventq_test_suite(void);
-
+int os_callout_test_suite(void);
#endif