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; }
static void helper_fiber(int arg1, int arg2) { nano_fiber_sem_take(&helper_fiber_sem, TICKS_UNLIMITED); /* Wake the test fiber */ fiber_fiber_wakeup(test_fiber_id); nano_fiber_sem_take(&helper_fiber_sem, TICKS_UNLIMITED); /* Wake the test fiber from an ISR */ irq_offload(irq_offload_isr, (void *)test_fiber_id); }
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 test_fiber_ticks_special_values(int packet, int special_value) { struct reply_packet *reply_packet = (void *)packet; reply_packet->reply = nano_fiber_sem_take(&sem_timeout[0], special_value); nano_fiber_fifo_put(&timeout_order_fifo, reply_packet); }
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(&multi_waiters, TICKS_UNLIMITED); TC_PRINT("multiple-waiter fiber %d acquired semaphore, sending reply\n", arg1); nano_fiber_sem_give(&reply_multi_waiters); }
int sys_event_logger_get_wait(struct event_logger *logger, uint16_t *event_id, uint8_t *dropped_event_count, uint32_t *buffer, uint8_t *buffer_size) { nano_fiber_sem_take(&(logger->sync_sema), TICKS_UNLIMITED); return event_logger_get(logger, event_id, dropped_event_count, buffer, buffer_size); }
int sys_event_logger_get(struct event_logger *logger, uint16_t *event_id, uint8_t *dropped_event_count, uint32_t *buffer, uint8_t *buffer_size) { if (nano_fiber_sem_take(&(logger->sync_sema), TICKS_NONE)) { return event_logger_get(logger, event_id, dropped_event_count, buffer, buffer_size); } return 0; }
/** * * @brief The test fiber entry function * * Fiber waits on the semaphore controlled by the test task * It signals the semaphore, the testing task waits for, * then it signals the semaphore for N_TASKS times, testing task * checks this number. * Then fiber signals each of the semaphores in the group. Test * task checks this. * * @return N/A */ static void testFiberEntry(void) { int i; /* release semaphore test task is waiting for */ nano_fiber_sem_take(&fiberSem, TICKS_UNLIMITED); fiber_sem_give(simpleSem); /* release the semaphore for N_TESTS times */ nano_fiber_sem_take(&fiberSem, TICKS_UNLIMITED); for (i = 0; i < N_TESTS; i++) { fiber_sem_give(simpleSem); } /* signal each semaphore in the group */ for (i = 0; semList[i] != ENDLIST; i++) { nano_fiber_sem_take(&fiberSem, TICKS_UNLIMITED); fiber_sem_give(semList[i]); } }
int sys_event_logger_get_wait_timeout(struct event_logger *logger, uint16_t *event_id, uint8_t *dropped_event_count, uint32_t *buffer, uint8_t *buffer_size, uint32_t timeout) { if (nano_fiber_sem_take(&(logger->sync_sema), timeout)) { return event_logger_get(logger, event_id, dropped_event_count, buffer, buffer_size); } return 0; }
static void tmp007_fiber(int dev_ptr, int unused) { struct device *dev = INT_TO_POINTER(dev_ptr); struct tmp007_data *drv_data = dev->driver_data; ARG_UNUSED(unused); while (1) { nano_fiber_sem_take(&drv_data->gpio_sem, TICKS_UNLIMITED); tmp007_fiber_cb(dev); } }
static void fiberEntry(int task_thread_id, int arg1) { int rv; ARG_UNUSED(arg1); fiberEvidence++; /* Prove to the task that the fiber has run */ nano_fiber_sem_take(&wakeFiber, TICKS_UNLIMITED); rv = nanoCtxFiberTest((nano_thread_id_t) task_thread_id); if (rv != TC_PASS) { return; } /* Allow the task to print any messages before the next test runs */ nano_fiber_sem_take(&wakeFiber, TICKS_UNLIMITED); rv = fiber_yieldTest(); if (rv != TC_PASS) { return; } }
void fiber3(void) { void *pData; /* Wait for fiber3 to be activated */ nano_fiber_sem_take(&nanoSemObj3, TICKS_UNLIMITED); /* Put two items onto <nanoFifoObj2> to unblock fibers #1 and #2. */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[0]); /* Wake fiber1 */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[1]); /* Wake fiber2 */ /* Wait for fiber3 to be re-activated */ nano_fiber_sem_take(&nanoSemObj3, TICKS_UNLIMITED); /* Immediately get the data from <nanoFifoObj2>. */ pData = nano_fiber_fifo_get(&nanoFifoObj2, TICKS_UNLIMITED); if (pData != pPutList2[0]) { retCode = TC_FAIL; TC_ERROR("fiber3 (1) - got 0x%x from <nanoFifoObj2>, expected 0x%x\n", pData, pPutList2[0]); } /* Put three items onto the FIFO for the task to get */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[0]); nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[1]); nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[2]); /* Sleep for 2 seconds */ nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); /* Put final item onto the FIFO for the task to get */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[3]); /* Wait for fiber3 to be re-activated (not expected to occur) */ nano_fiber_sem_take(&nanoSemObj3, TICKS_UNLIMITED); }
/* a fiber pends on a semaphore with a timeout and gets the semaphore in time */ static void test_fiber_pend_and_get_sem(int data, int unused) { struct timeout_order_data *the_data = (void *)data; int rv; ARG_UNUSED(unused); rv = nano_fiber_sem_take(the_data->sem, the_data->timeout); if (!rv) { TC_PRINT(" *** fiber (q order: %d, t/o: %d, sem: %p) timed out!\n", the_data->q_order, the_data->timeout, the_data->sem); return; } nano_fiber_fifo_put(&timeout_order_fifo, the_data); }
int taskLifoWaitTest(void) { void *data; /* ptr to data retrieved from LIFO */ /* Wait on <taskWaitSem> in case fiber's print message blocked */ nano_fiber_sem_take(&taskWaitSem, TICKS_UNLIMITED); /* The fiber is waiting on the LIFO. Wake it. */ nano_task_lifo_put(&test_lifo, &lifoItem[0]); /* * The fiber ran, but is now blocked on the semaphore. Add an item to the * LIFO before giving the semaphore that wakes the fiber so that we can * cover the path of nano_fiber_lifo_get(TICKS_UNLIMITED) not waiting on * the LIFO. */ nano_task_lifo_put(&test_lifo, &lifoItem[2]); nano_task_sem_give(&fiberWaitSem); /* Check that the fiber got the correct item (lifoItem[0]) */ if (fiberDetectedFailure) { TC_ERROR(" *** nano_task_lifo_put()/nano_fiber_lifo_get() failure\n"); return TC_FAIL; } /* The LIFO is empty. This time the task will wait for the item. */ TC_PRINT("Task waiting on an empty LIFO\n"); data = nano_task_lifo_get(&test_lifo, TICKS_UNLIMITED); if (data != (void *) &lifoItem[1]) { TC_ERROR(" *** nano_task_lifo_get()/nano_fiber_lifo_put() failure\n"); return TC_FAIL; } data = nano_task_lifo_get(&test_lifo, TICKS_UNLIMITED); if (data != (void *) &lifoItem[3]) { TC_ERROR(" *** nano_task_lifo_get()/nano_fiber_lifo_put() failure\n"); return TC_FAIL; } /* Waiting on an empty LIFO passed for both fiber and task. */ return TC_PASS; }
static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan, struct net_buf *buf) { uint16_t sdu_len; if (!nano_fiber_sem_take(&chan->rx.credits, TICKS_NONE)) { BT_ERR("No credits to receive packet"); bt_l2cap_chan_disconnect(&chan->chan); return; } /* Check if segments already exist */ if (chan->_sdu) { l2cap_chan_le_recv_sdu(chan, buf); return; } sdu_len = net_buf_pull_le16(buf); BT_DBG("chan %p len %u sdu_len %u", chan, buf->len, sdu_len); if (sdu_len > chan->rx.mtu) { BT_ERR("Invalid SDU length"); bt_l2cap_chan_disconnect(&chan->chan); return; } /* Always allocate buffer from the channel if supported. */ if (chan->chan.ops && chan->chan.ops->alloc_buf) { chan->_sdu = chan->chan.ops->alloc_buf(&chan->chan); if (!chan->_sdu) { BT_ERR("Unable to allocate buffer for SDU"); bt_l2cap_chan_disconnect(&chan->chan); return; } chan->_sdu_len = sdu_len; l2cap_chan_le_recv_sdu(chan, buf); return; } chan->chan.ops->recv(&chan->chan, buf); l2cap_chan_update_credits(chan); }
/* a fiber pends on a semaphore then times out */ static void test_fiber_pend_and_timeout(int data, int unused) { struct timeout_order_data *the_data = (void *)data; int32_t orig_ticks = sys_tick_get(); int rv; ARG_UNUSED(unused); rv = nano_fiber_sem_take(the_data->sem, the_data->timeout); if (rv) { TC_ERROR(" *** timeout of %d did not time out.\n", the_data->timeout); return; } if (!is_timeout_in_range(orig_ticks, the_data->timeout)) { return; } nano_fiber_fifo_put(&timeout_order_fifo, the_data); }
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; }
/** * * @brief Check the time when it gets executed after the semaphore * * Fiber starts, waits on semaphore. When the interrupt handler releases * the semaphore, fiber measures the time. * * @return N/A */ static void fiberWaiter(void) { nano_fiber_sem_take(&testSema, TICKS_UNLIMITED); timestamp = TIME_STAMP_DELTA_GET(timestamp); }
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(&testSem, TICKS_UNLIMITED); 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_test(&timer, TICKS_UNLIMITED); /* * 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_test(&timer, TICKS_UNLIMITED); /* * 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; } }
int fiber_yieldTest(void) { nano_thread_id_t self_thread_id; /* * Start a fiber of higher priority. Note that since the new fiber is * being started from a fiber, it will not automatically switch to the * fiber as it would if done from a task. */ self_thread_id = sys_thread_self_get(); fiberEvidence = 0; fiber_fiber_start(fiberStack2, FIBER_STACKSIZE, fiberHelper, 0, 0, FIBER_PRIORITY - 1, 0); if (fiberEvidence != 0) { /* ERROR! Helper spawned at higher */ fiberDetectedError = 10; /* priority ran prematurely. */ return TC_FAIL; } /* * Test that the fiber will yield to the higher priority helper. * <fiberEvidence> is still 0. */ fiber_yield(); if (fiberEvidence == 0) { /* ERROR! Did not yield to higher */ fiberDetectedError = 11; /* priority fiber. */ return TC_FAIL; } if (fiberEvidence > 1) { /* ERROR! Helper did not yield to */ fiberDetectedError = 12; /* equal priority fiber. */ return TC_FAIL; } /* * Raise the priority of fiberEntry(). Calling fiber_yield() should * not result in switching to the helper. */ self_thread_id->prio--; fiber_yield(); if (fiberEvidence != 1) { /* ERROR! Context switched to a lower */ fiberDetectedError = 13; /* priority fiber! */ return TC_FAIL; } /* * Block on <wakeFiber>. This will allow the helper fiber to complete. * The main task will wake this fiber. */ nano_fiber_sem_take(&wakeFiber, TICKS_UNLIMITED); return TC_PASS; }
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(&nanoSemObj1, TICKS_UNLIMITED); /* Wait for data to be added to <nanoFifoObj> by task */ pData = nano_fiber_fifo_get(&nanoFifoObj, TICKS_UNLIMITED); 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(&nanoFifoObj2, TICKS_UNLIMITED); if (pData != pPutList2[0]) { TC_ERROR("fiber1 (2) - expected 0x%x, got 0x%x\n", pPutList2[0], pData); retCode = TC_FAIL; return; } /* Wait for fiber1 to be reactivated */ nano_fiber_sem_take(&nanoSemObj1, TICKS_UNLIMITED); TC_PRINT("Test Fiber FIFO Get\n\n"); /* Get all FIFOs */ while ((pData = nano_fiber_fifo_get(&nanoFifoObj, TICKS_NONE)) != 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 */
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; }