/* * Copyright (c) 2024 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include /* COMMON DEFFINITIONS */ #define STACK_SIZE 500 #define LIST_LEN 8 static struct k_sem sema; static struct k_thread tdata; static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); /* FIFO SCENARIO */ /* Thread A enters items into a fifo, starts Thread B and waits for a semaphore. */ /* Thread B extracts all items from the fifo and enters some items back into the fifo. */ /* Thread B gives the semaphore for Thread A to continue. */ /* Once the control is returned back to Thread A, it extracts all items from the fifo. */ /* Verify the data's correctness. */ static K_FIFO_DEFINE(fifo); struct fifo_item_t { void *fifo_reserved; /* 1st word reserved for use by FIFO */ uint8_t value; }; static struct fifo_item_t fifo_data[LIST_LEN]; static void thread_entry_fn_fifo(void *p1, void *p2, void *p3) { struct fifo_item_t *rx_data; uint32_t i; /* Get items from fifo */ for (i = 0U; i < LIST_LEN; i++) { rx_data = k_fifo_get((struct k_fifo *)p1, K_NO_WAIT); zassert_equal(rx_data->value, fifo_data[i].value); } /* Put items into fifo */ for (i = 0U; i < LIST_LEN; i++) { fifo_data[i].value *= i; k_fifo_put((struct k_fifo *)p1, &fifo_data[i]); } /* Give control back to Thread A */ k_sem_give(&sema); } ZTEST(kernel, test_fifo_usage) { struct fifo_item_t *rx_data; uint32_t i; /* Init binary semaphore */ k_sem_init(&sema, 0, 1); /* Set and Put items into fifo */ for (i = 0U; i < LIST_LEN; i++) { fifo_data[i].value = i; k_fifo_put(&fifo, &fifo_data[i]); } /* Create the Thread B */ k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_fn_fifo, &fifo, NULL, NULL, K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT); /* Let the thread B run */ k_sem_take(&sema, K_FOREVER); /* Get items from fifo */ for (i = 0U; i < LIST_LEN; i++) { rx_data = k_fifo_get(&fifo, K_NO_WAIT); zassert_equal(rx_data->value, fifo_data[i].value); } /* Clear the spawn thread */ k_thread_abort(tid); } /* LIFO SCENARIO */ /* Thread A enters items into a lifo, starts Thread B and waits for a semaphore. */ /* Thread B extracts all items from the lifo and enters some items back into the lifo. */ /* Thread B gives the semaphore for Thread A to continue. */ /* Once the control is returned back to Thread A, it extracts all items from the lifo. */ /* Verify the data's correctness. */ struct lifo_item_t { void *LIFO_reserved; /* 1st word reserved for use by LIFO */ uint8_t value; }; static struct lifo_item_t lifo_data[LIST_LEN]; K_LIFO_DEFINE(lifo); static void thread_entry_fn_lifo(void *p1, void *p2, void *p3) { struct lifo_item_t *rx_data; uint32_t i; /* Get items from lifo */ for (i = 0U; i < LIST_LEN; i++) { rx_data = k_lifo_get((struct k_lifo *)p1, K_NO_WAIT); zassert_equal(rx_data->value, lifo_data[LIST_LEN-1-i].value); } /* Put items into lifo */ for (i = 0U; i < LIST_LEN; i++) { lifo_data[i].value *= i; k_lifo_put((struct k_lifo *)p1, &lifo_data[i]); } /* Give control back to Thread A */ k_sem_give(&sema); } ZTEST(kernel, test_lifo_usage) { struct lifo_item_t *rx_data; uint32_t i; /* Init binary semaphore */ k_sem_init(&sema, 0, 1); /* Set and Put items into lifo */ for (i = 0U; i < LIST_LEN; i++) { lifo_data[i].value = i; k_lifo_put(&lifo, &lifo_data[i]); } /* Create the Thread B */ k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_fn_lifo, &lifo, NULL, NULL, K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT); /* Let the thread B run */ k_sem_take(&sema, K_FOREVER); /* Get items from lifo */ for (i = 0U; i < LIST_LEN; i++) { rx_data = k_lifo_get(&lifo, K_NO_WAIT); zassert_equal(rx_data->value, lifo_data[LIST_LEN-1-i].value); } /* Clear the spawn thread */ k_thread_abort(tid); } /* STACK SCENARIO */ /* Thread A enters items into a stack, starts thread B and waits for a semaphore. */ /* Thread B extracts all items from the stack and enters some items back into the stack. */ /* Thread B gives the semaphore for Thread A to continue. */ /* Once the control is returned back to Thread A, it extracts all items from the stack. */ /* Verify the data's correctness. */ #define STACK_LEN 8 #define MAX_ITEMS 8 K_STACK_DEFINE(stack, STACK_LEN); stack_data_t stack_data[MAX_ITEMS]; static void thread_entry_fn_stack(void *p1, void *p2, void *p3) { stack_data_t *rx_data; stack_data_t data[MAX_ITEMS]; /* fill data to compare */ for (int i = 0; i < STACK_LEN; i++) { data[i] = i; } /* read data from a stack */ for (int i = 0; i < STACK_LEN; i++) { k_stack_pop((struct k_stack *)p1, (stack_data_t *)&rx_data, K_NO_WAIT); } zassert_false(memcmp(rx_data, data, STACK_LEN), "Push & Pop items does not match"); /* Push data into a stack */ for (int i = 0; i < STACK_LEN; i++) { stack_data[i] *= i; k_stack_push((struct k_stack *)p1, (stack_data_t)&stack_data[i]); } /* Give control back to Thread A */ k_sem_give(&sema); } ZTEST(kernel, test_stack_usage) { stack_data_t *rx_data; /* Init binary semaphore */ k_sem_init(&sema, 0, 1); /* Push data into a stack */ for (int i = 0; i < STACK_LEN; i++) { stack_data[i] = i; k_stack_push(&stack, (stack_data_t)&stack_data[i]); } /* Create the Thread B */ k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_fn_stack, &stack, NULL, NULL, K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT); /* Let the thread B run */ k_sem_take(&sema, K_FOREVER); /* read data from a stack */ for (int i = 0; i < STACK_LEN; i++) { k_stack_pop(&stack, (stack_data_t *)&rx_data, K_NO_WAIT); } /* Verify the correctness */ zassert_false(memcmp(rx_data, stack_data, STACK_LEN), "Push & Pop items does not match"); /* Clear the spawn thread */ k_thread_abort(tid); } /* MUTEX SCENARIO */ /* Initialize the mutex. */ /* Start the two Threads with the entry points. */ /* The entry points change variable and use lock and unlock mutex functions to */ /* synchronize the access to that variable. */ /* Join all threads. */ /* Verify the variable. */ #define NUMBER_OF_ITERATIONS 10000 static uint32_t mutex_data; static struct k_thread tdata_2; static K_THREAD_STACK_DEFINE(tstack_2, STACK_SIZE); K_MUTEX_DEFINE(mutex); static void thread_entry_fn_mutex(void *p1, void *p2, void *p3) { uint32_t i; for (i = 0; i < NUMBER_OF_ITERATIONS; i++) { k_mutex_lock((struct k_mutex *)p1, K_FOREVER); mutex_data += 1; k_mutex_unlock((struct k_mutex *)p1); } } static void thread_entry_fn_mutex_2(void *p1, void *p2, void *p3) { uint32_t i; for (i = 0; i < NUMBER_OF_ITERATIONS*2; i++) { k_mutex_lock((struct k_mutex *)p1, K_FOREVER); mutex_data -= 1; k_mutex_unlock((struct k_mutex *)p1); } } ZTEST(kernel, test_mutex_usage) { /* Create the Thread A */ k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_fn_mutex, &mutex, &mutex_data, NULL, K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_FOREVER); /* Create the Thread B */ k_tid_t tid2 = k_thread_create(&tdata_2, tstack_2, STACK_SIZE, thread_entry_fn_mutex_2, &mutex, &mutex_data, NULL, K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_FOREVER); /* Start the Thread A */ k_thread_start(tid); /* Start the Thread B */ k_thread_start(tid2); /* Wait for end of Thread A */ k_thread_join(&tdata, K_FOREVER); /* Wait for end of Thread B */ k_thread_join(&tdata_2, K_FOREVER); /* Verify data after the end of the threads */ zassert_equal(mutex_data, -10000); /* Clear the spawn threads */ k_thread_abort(tid); k_thread_abort(tid2); } ZTEST_SUITE(kernel, NULL, NULL, ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);