diff options
Diffstat (limited to 'libs/os')
-rwxr-xr-x | libs/os/include/os/arch/cortex_m0/os/os_arch.h | 12 | ||||
-rwxr-xr-x | libs/os/include/os/arch/cortex_m4/os/os_arch.h | 12 | ||||
-rw-r--r-- | libs/os/include/os/os_mbuf.h | 12 | ||||
-rw-r--r-- | libs/os/include/os/os_mempool.h | 3 | ||||
-rw-r--r-- | libs/os/src/arch/cortex_m0/m0/HAL_CM0.s | 1 | ||||
-rwxr-xr-x | libs/os/src/arch/cortex_m0/os_arch_arm.c | 34 | ||||
-rwxr-xr-x | libs/os/src/arch/cortex_m4/m4/HAL_CM4.s | 2 | ||||
-rwxr-xr-x | libs/os/src/arch/cortex_m4/os_arch_arm.c | 35 | ||||
-rw-r--r-- | libs/os/src/arch/sim/os_arch_sim.c | 2 | ||||
-rw-r--r-- | libs/os/src/os.c | 4 | ||||
-rw-r--r-- | libs/os/src/os_callout.c | 4 | ||||
-rw-r--r-- | libs/os/src/os_eventq.c | 33 | ||||
-rw-r--r-- | libs/os/src/os_mbuf.c | 181 | ||||
-rw-r--r-- | libs/os/src/os_mempool.c | 74 | ||||
-rw-r--r-- | libs/os/src/os_priv.h | 10 | ||||
-rw-r--r-- | libs/os/src/os_task.c | 3 | ||||
-rw-r--r-- | libs/os/src/os_time.c | 12 | ||||
-rw-r--r-- | libs/os/src/test/callout_test.c | 330 | ||||
-rw-r--r-- | libs/os/src/test/eventq_test.c | 297 | ||||
-rw-r--r-- | libs/os/src/test/os_test.c | 2 | ||||
-rw-r--r-- | libs/os/src/test/os_test_priv.h | 2 |
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 |