int testSemFiberNoWait(void) { int i; TC_PRINT("Giving and taking a semaphore in a fiber (non-blocking)\n"); /* * Give the semaphore many times and then make sure that it can only be * taken that many times. */ for (i = 0; i < 32; i++) { nano_fiber_sem_give(&testSem); } for (i = 0; i < 32; i++) { if (nano_fiber_sem_take(&testSem) != 1) { TC_ERROR(" *** Expected nano_fiber_sem_take() to succeed, not fail\n"); goto errorReturn; } } if (nano_fiber_sem_take(&testSem) != 0) { TC_ERROR(" *** Expected nano_fiber_sem_take() to fail, not succeed\n"); goto errorReturn; } return TC_PASS; errorReturn: fiberDetectedFailure = 1; return TC_FAIL; }
void fiber1(void) { void *pData; /* pointer to FIFO object get from the queue */ int count = 0; /* counter */ /* Wait for fiber1 to be activated. */ nano_fiber_sem_take_wait(&nanoSemObj1); /* Wait for data to be added to <nanoFifoObj> by task */ pData = nano_fiber_fifo_get_wait(&nanoFifoObj); if (pData != pPutList1[0]) { TC_ERROR("fiber1 (1) - expected 0x%x, got 0x%x\n", pPutList1[0], pData); retCode = TC_FAIL; return; } /* Wait for data to be added to <nanoFifoObj2> by fiber3 */ pData = nano_fiber_fifo_get_wait(&nanoFifoObj2); if (pData != pPutList2[0]) { TC_ERROR("fiber1 (2) - expected 0x%x, got 0x%x\n", pPutList2[0], pData); retCode = TC_FAIL; return; } nano_fiber_sem_take_wait(&nanoSemObj1); /* Wait for fiber1 to be reactivated */ TC_PRINT("Test Fiber FIFO Get\n\n"); /* Get all FIFOs */ while ((pData = nano_fiber_fifo_get(&nanoFifoObj)) != NULL) { TC_PRINT("FIBER FIFO Get: count = %d, ptr is %p\n", count, pData); if ((count >= NUM_FIFO_ELEMENT) || (pData != pPutList1[count])) { TCERR1(count); retCode = TC_FAIL; return; } count++; } TC_END_RESULT(retCode); PRINT_LINE; /* * Entries in the FIFO queue have to be unique. * Put data. */ TC_PRINT("Test Fiber FIFO Put\n"); TC_PRINT("\nFIBER FIFO Put Order: "); for (int i=0; i<NUM_FIFO_ELEMENT; i++) { nano_fiber_fifo_put(&nanoFifoObj, pPutList2[i]); TC_PRINT(" %p,", pPutList2[i]); } TC_PRINT("\n"); PRINT_LINE; /* Give semaphore to allow the main task to run */ nano_fiber_sem_give(&nanoSemObjTask); } /* fiber1 */
/* a fiber busy waits, then reports through a fifo */ static void test_fiber_busy_wait(int ticks, int unused) { ARG_UNUSED(unused); uint32_t usecs = ticks * sys_clock_us_per_tick; TC_PRINT(" fiber busy waiting for %d usecs (%d ticks)\n", usecs, ticks); sys_thread_busy_wait(usecs); TC_PRINT(" fiber busy waiting completed\n"); /* * Ideally the test should verify that the correct number of ticks * have elapsed. However, when run under QEMU the tick interrupt * may be processed on a very irregular basis, meaning that far * fewer than the expected number of ticks may occur for a given * number of clock cycles vs. what would ordinarily be expected. * * Consequently, the best we can do for now to test busy waiting is * to invoke the API and verify that it returns. (If it takes way * too long, or never returns, the main test task may be able to * time out and report an error.) */ nano_fiber_sem_give(&reply_timeout); }
void fiber1(void) { uint32_t data; /* data used to put and get from the stack queue */ int count = 0; /* counter */ TC_PRINT("Test Fiber STACK Pop\n\n"); /* Get all data */ while (nano_fiber_stack_pop(&nanoStackObj, &data, TICKS_NONE) != 0) { TC_PRINT("FIBER STACK Pop: count = %d, data is %d\n", count, data); if ((count >= NUM_STACK_ELEMENT) || (data != myData[NUM_STACK_ELEMENT - 1 - count])) { TCERR1(count); retCode = TC_FAIL; return; } count++; } TC_END_RESULT(retCode); PRINT_LINE; /* Put data */ TC_PRINT("Test Fiber STACK Push\n"); TC_PRINT("\nFIBER STACK Put Order: "); for (int i=NUM_STACK_ELEMENT; i>0; i--) { nano_fiber_stack_push(&nanoStackObj, myData[i-1]); TC_PRINT(" %d,", myData[i-1]); } TC_PRINT("\n"); PRINT_LINE; /* Give semaphore to allow the main task to run */ nano_fiber_sem_give(&nanoSemObj); } /* fiber1 */
static void fiber_multi_waiters(int arg1, int arg2) { TC_PRINT("multiple-waiter fiber %d trying to get semaphore...\n", arg1); nano_fiber_sem_take_wait(&multi_waiters); TC_PRINT("multiple-waiter fiber %d acquired semaphore, sending reply\n", arg1); nano_fiber_sem_give(&reply_multi_waiters); }
/* a fiber sleeps and times out, then reports through a fifo */ static void test_fiber_sleep(int timeout, int arg2) { int64_t orig_ticks = sys_tick_get(); TC_PRINT(" fiber sleeping for %d ticks\n", timeout); fiber_sleep(timeout); TC_PRINT(" fiber back from sleep\n"); if (!is_timeout_in_range(orig_ticks, timeout)) { return; } nano_fiber_sem_give(&reply_timeout); }
void fiber2(void) { void *pData; /* pointer to FIFO object from the queue */ /* Wait for fiber2 to be activated */ nano_fiber_sem_take(&nanoSemObj2, TICKS_UNLIMITED); /* Wait for data to be added to <nanoFifoObj> */ pData = nano_fiber_fifo_get(&nanoFifoObj, TICKS_UNLIMITED); if (pData != pPutList1[1]) { TC_ERROR("fiber2 (1) - expected 0x%x, got 0x%x\n", pPutList1[1], pData); retCode = TC_FAIL; return; } /* Wait for data to be added to <nanoFifoObj2> by fiber3 */ pData = nano_fiber_fifo_get(&nanoFifoObj2, TICKS_UNLIMITED); if (pData != pPutList2[1]) { TC_ERROR("fiber2 (2) - expected 0x%x, got 0x%x\n", pPutList2[1], pData); retCode = TC_FAIL; return; } /* Wait for fiber2 to be reactivated */ nano_fiber_sem_take(&nanoSemObj2, TICKS_UNLIMITED); /* Fiber #2 has been reactivated by main task */ for (int i = 0; i < 4; i++) { pData = nano_fiber_fifo_get(&nanoFifoObj, TICKS_UNLIMITED); if (pData != pPutList1[i]) { TC_ERROR("fiber2 (3) - iteration %d expected 0x%x, got 0x%x\n", i, pPutList1[i], pData); retCode = TC_FAIL; return; } } nano_fiber_sem_give(&nanoSemObjTask); /* Wake main task */ /* Wait for fiber2 to be reactivated */ nano_fiber_sem_take(&nanoSemObj2, TICKS_UNLIMITED); testFiberFifoGetW(); PRINT_LINE; testIsrFifoFromFiber(); TC_END_RESULT(retCode); } /* fiber2 */
int fiberLifoWaitTest(void) { void *data; /* ptr to data retrieved from LIFO */ /* * The LIFO is empty; wait for an item to be added to the LIFO * from the task. */ TC_PRINT("Fiber waiting on an empty LIFO\n"); nano_fiber_sem_give(&taskWaitSem); data = nano_fiber_lifo_get(&test_lifo, TICKS_UNLIMITED); if (data != &lifoItem[0]) { fiberDetectedFailure = 1; return -1; } nano_fiber_sem_take(&fiberWaitSem, TICKS_UNLIMITED); data = nano_fiber_lifo_get(&test_lifo, TICKS_UNLIMITED); if (data != &lifoItem[2]) { fiberDetectedFailure = 1; return -1; } /* * Give the task some time to check the results. Ideally, this would * be waiting for a semaphore instead of a using a delay, but if the * main task wakes the fiber before it blocks on the LIFO, the fiber * will add the item to the LIFO too soon. Obviously, a semaphore could * not be given if the task is blocked on the LIFO; hence the delay. */ nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); /* The task is waiting on an empty LIFO. Wake it up. */ nano_fiber_lifo_put(&test_lifo, &lifoItem[3]); nano_fiber_lifo_put(&test_lifo, &lifoItem[1]); /* * Wait for the task to check the results. If the results pass, then the * the task will wake the fiber. If the results do not pass, then the * fiber will wait forever. */ nano_fiber_sem_take(&fiberWaitSem, TICKS_UNLIMITED); return 0; }
static void context_sem_give(struct nano_sem *chan) { switch (sys_execution_context_type_get()) { case NANO_CTX_FIBER: nano_fiber_sem_give(chan); break; case NANO_CTX_TASK: nano_task_sem_give(chan); break; case NANO_CTX_ISR: default: /* Invalid context type */ break; } }
static void fiber_multi_waiters(int arg1, int arg2) { void *item; TC_PRINT("multiple-waiter fiber %d receiving item...\n", arg1); item = nano_fiber_lifo_get(&multi_waiters, TICKS_UNLIMITED); if (item != &multi_waiters_items[arg1]) { TC_ERROR(" *** fiber %d did not receive correct item\n", arg1); TC_ERROR(" *** received %p instead of %p.\n", item, &multi_waiters_items[arg1]); /* do NOT give the semaphore, signifying an error */ return; } TC_PRINT("multiple-waiter fiber %d got correct item, giving semaphore\n", arg1); nano_fiber_sem_give(&reply_multi_waiters); }
void unlock_pool(void) { #ifdef ZEPHYR_MICRO_OS_ABSTRACTION_USE_SINGLE_POOL_LOCK #ifdef CONFIG_NANOKERNEL _PoolUnlock(); #else task_mutex_unlock(MTX_POOL_GENERIC); #endif #else #ifdef CONFIG_NANOKERNEL nano_fiber_sem_give (&QueuePoolLockSem) ; #else task_mutex_unlock(MTX_POOL_QUEUE); #endif #endif }
void fiberEntry(void) { struct nano_timer timer; uint32_t data[2] = {0, 0}; nano_sem_init(&nanoSemFiber); nano_timer_init(&timer, data); while (1) { /* wait for task to let us have a turn */ nano_fiber_sem_take_wait(&nanoSemFiber); /* say "hello" */ PRINT("%s: Hello World!\n", __FUNCTION__); /* wait a while, then let task have a turn */ nano_fiber_timer_start(&timer, SLEEPTICKS); nano_fiber_timer_wait(&timer); nano_fiber_sem_give(&nanoSemTask); } }
static bool send_frag(struct bt_conn *conn, struct net_buf *buf, uint8_t flags, bool always_consume) { struct bt_hci_acl_hdr *hdr; int err; BT_DBG("conn %p buf %p len %u flags 0x%02x", conn, buf, buf->len, flags); /* Wait until the controller can accept ACL packets */ nano_fiber_sem_take(bt_conn_get_pkts(conn), TICKS_UNLIMITED); /* Check for disconnection while waiting for pkts_sem */ if (conn->state != BT_CONN_CONNECTED) { goto fail; } hdr = net_buf_push(buf, sizeof(*hdr)); hdr->handle = sys_cpu_to_le16(bt_acl_handle_pack(conn->handle, flags)); hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr)); bt_buf_set_type(buf, BT_BUF_ACL_OUT); err = bt_send(buf); if (err) { BT_ERR("Unable to send to driver (err %d)", err); goto fail; } conn->pending_pkts++; return true; fail: nano_fiber_sem_give(bt_conn_get_pkts(conn)); if (always_consume) { net_buf_unref(buf); } return false; }
static void conn_tx_fiber(int arg1, int arg2) { struct bt_conn *conn = (struct bt_conn *)arg1; struct net_buf *buf; BT_DBG("Started for handle %u", conn->handle); while (conn->state == BT_CONN_CONNECTED) { /* Get next ACL packet for connection */ buf = nano_fifo_get(&conn->tx_queue, TICKS_UNLIMITED); if (conn->state != BT_CONN_CONNECTED) { net_buf_unref(buf); break; } if (!send_buf(conn, buf)) { net_buf_unref(buf); } } BT_DBG("handle %u disconnected - cleaning up", conn->handle); /* Give back any allocated buffers */ while ((buf = nano_fifo_get(&conn->tx_queue, TICKS_NONE))) { net_buf_unref(buf); } /* Return any unacknowledged packets */ if (conn->pending_pkts) { while (conn->pending_pkts--) { nano_fiber_sem_give(bt_conn_get_pkts(conn)); } } bt_conn_reset_rx_state(conn); BT_DBG("handle %u exiting", conn->handle); bt_conn_unref(conn); }
static int event_logger_get(struct event_logger *logger, uint16_t *event_id, uint8_t *dropped_event_count, uint32_t *buffer, uint8_t *buffer_size) { int ret; ret = sys_ring_buf_get(&logger->ring_buf, event_id, dropped_event_count, buffer, buffer_size); if (likely(!ret)) { return *buffer_size; } switch (ret) { case -EMSGSIZE: /* if the user can not retrieve the message, we increase the * semaphore to indicate that the message remains in the buffer */ nano_fiber_sem_give(&(logger->sync_sema)); return -EMSGSIZE; case -EAGAIN: return 0; default: return ret; } }
static void test_fiber(int arg1, int arg2) { uint32_t start_tick; uint32_t end_tick; nano_fiber_sem_take(&test_fiber_sem, TICKS_UNLIMITED); TC_PRINT("Testing normal expiration of fiber_sleep()\n"); align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick != start_tick + ONE_SECOND) { TC_ERROR(" *** fiber_sleep() slept for %d ticks not %d.", end_tick - start_tick, ONE_SECOND); return; } TC_PRINT("Testing fiber_sleep() + fiber_fiber_wakeup()\n"); nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** fiber_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } TC_PRINT("Testing fiber_sleep() + isr_fiber_wakeup()\n"); nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** isr_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } TC_PRINT("Testing fiber_sleep() + task_fiber_wakeup()\n"); nano_task_sem_give(&task_sem); /* Activate task */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); /* Task will execute */ end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** task_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } test_failure = false; }
int fiberLifoNonWaitTest(void) { void *data; /* pointer to data retrieved from LIFO */ /* The LIFO has two items in it; retrieve them both */ data = nano_fiber_lifo_get(&test_lifo, TICKS_NONE); if (data != (void *) &lifoItem[3]) { goto errorReturn; } data = nano_fiber_lifo_get(&test_lifo, TICKS_NONE); if (data != (void *) &lifoItem[2]) { goto errorReturn; } /* LIFO should be empty--verify. */ data = nano_fiber_lifo_get(&test_lifo, TICKS_NONE); if (data != NULL) { goto errorReturn; } /* * The LIFO is now empty. Add two items to the LIFO and then wait * for the semaphore so that the task can retrieve them. */ TC_PRINT("Task to get LIFO items without waiting\n"); nano_fiber_lifo_put(&test_lifo, &lifoItem[0]); nano_fiber_lifo_put(&test_lifo, &lifoItem[1]); nano_fiber_sem_give(&taskWaitSem); /* Wake the task (if blocked) */ /* * Wait for the task to get the items and then trigger an ISR to populate * the LIFO. */ nano_fiber_sem_take(&fiberWaitSem, TICKS_UNLIMITED); /* * The task retrieved the two items from the LIFO and then triggered * two interrupts to add two other items to the LIFO. The fiber will * now trigger two interrupts to read the two items. */ _trigger_nano_isr_lifo_get(); if (isrLifoInfo.data != &lifoItem[1]) { goto errorReturn; } _trigger_nano_isr_lifo_get(); if (isrLifoInfo.data != &lifoItem[3]) { goto errorReturn; } /* The LIFO should now be empty--verify */ _trigger_nano_isr_lifo_get(); if (isrLifoInfo.data != NULL) { goto errorReturn; } return 0; errorReturn: fiberDetectedFailure = 1; return -1; }
static void fiberEntry(int arg1, int arg2) { int rv; /* return value from a test */ ARG_UNUSED(arg1); ARG_UNUSED(arg2); rv = testSemFiberNoWait(); if (rv != TC_PASS) { return; } /* * At this point <testSem> is not available. Wait for <testSem> to become * available (the main task will give it). */ nano_fiber_sem_take_wait(&testSem); semTestState = STS_TASK_WOKE_FIBER; /* * Delay for two seconds. This gives the main task time to print * any messages (very important if I/O link is slow!), and wait * on <testSem>. Once the delay is done, this fiber will give <testSem> * thus waking the main task. */ nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_wait(&timer); /* * The main task is now waiting on <testSem>. Give the semaphore <testSem> * to wake it. */ nano_fiber_sem_give(&testSem); /* * Some small delay must be done so that the main task can process the * semaphore signal. */ semTestState = STS_FIBER_WOKE_TASK; nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_wait(&timer); /* * The main task should be waiting on <testSem> again. This time, instead * of giving the semaphore from the semaphore, give it from an ISR to wake * the main task. */ isrSemInfo.data = 0; isrSemInfo.sem = &testSem; _trigger_nano_isr_sem_give(); if (isrSemInfo.data == 1) { semTestState = STS_ISR_WOKE_TASK; } }
/* a fiber sleeps then gives a semaphore */ static void test_fiber_give_timeout(int sem, int timeout) { fiber_sleep((int32_t)timeout); nano_fiber_sem_give((struct nano_sem *)sem); }