Beispiel #1
0
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;
}
Beispiel #2
0
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 */
Beispiel #3
0
/* 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);
}
Beispiel #4
0
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 */
Beispiel #5
0
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);
}
Beispiel #6
0
/* 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);
}
Beispiel #7
0
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 */
Beispiel #8
0
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;
}
Beispiel #9
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;
	}
}
Beispiel #10
0
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);
}
Beispiel #11
0
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
}
Beispiel #12
0
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);
	}
}
Beispiel #13
0
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;
}
Beispiel #14
0
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);
}
Beispiel #15
0
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;
	}
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
	}
}
Beispiel #19
0
/* 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);
}