[ports] Add an API to dynamically add/remove ports from a port group.

This commit is contained in:
Gurjant Kalsi
2016-02-17 17:33:57 -08:00
parent ff12cba747
commit 42e76b1fc7
3 changed files with 236 additions and 3 deletions

View File

@@ -27,6 +27,7 @@
#include <string.h>
#include <trace.h>
#include <kernel/event.h>
#include <kernel/port.h>
#include <kernel/thread.h>
@@ -583,6 +584,151 @@ int group_basic(void)
return 0;
}
int group_dynamic(void)
{
status_t st;
port_t w_test_port1, r_test_port1;
st = make_port_pair("tst_port1", TS1_PORT_CTX, &w_test_port1, &r_test_port1);
if (st < 0)
return __LINE__;
port_t w_test_port2, r_test_port2;
st = make_port_pair("tst_port2", TS2_PORT_CTX, &w_test_port2, &r_test_port2);
if (st < 0)
return __LINE__;
port_t pg;
st = port_group(&r_test_port1, 1, &pg);
if (st < 0)
return __LINE__;
port_packet_t pkt = { { 0 } };
st = port_write(w_test_port2, &pkt, 1);
if (st < 0)
return __LINE__;
port_result_t rslt;
st = port_read(pg, 0, &rslt);
if (st != ERR_TIMED_OUT)
return __LINE__;
// Attach the port that has been written to to the port group and ensure
// that we can read from it.
st = port_group_add(pg, r_test_port2);
if (st < 0)
return __LINE__;
st = port_read(pg, 0, &rslt);
if (st < 0)
return __LINE__;
// Write some data to a port then remove it from the port group and ensure
// that we can't read from it.
st = port_write(w_test_port1, &pkt, 1);
if (st < 0)
return __LINE__;
st = port_group_remove(pg, r_test_port1);
if (st < 0)
return __LINE__;
st = port_read(pg, 0, &rslt);
if (st != ERR_TIMED_OUT)
return __LINE__;
st = port_close(w_test_port1);
if (st < 0)
return __LINE__;
st = port_close(w_test_port2);
if (st < 0)
return __LINE__;
st = port_destroy(w_test_port1);
if (st < 0)
return __LINE__;
st = port_destroy(w_test_port2);
if (st < 0)
return __LINE__;
return 0;
}
event_t group_waiting_sync_evt;
static int receive_thread(void *arg)
{
port_t pg = (port_t)arg;
// Try to read from an empty port group. When the other thread adds a port
// to this port group, we should wake up and
port_result_t rslt;
status_t st = port_read(pg, 500, &rslt);
if (st == ERR_TIMED_OUT)
return __LINE__;
event_signal(&group_waiting_sync_evt, true);
return 0;
}
/* Test the edge case where a read port with data available is added to a port
* group that has a read-blocked receiver.
*/
int group_waiting(void)
{
status_t st;
event_init(&group_waiting_sync_evt, false, EVENT_FLAG_AUTOUNSIGNAL);
port_t w_test_port1, r_test_port1;
st = make_port_pair("tst_port1", TS1_PORT_CTX, &w_test_port1, &r_test_port1);
if (st < 0)
return __LINE__;
// Write something to this port group that currently has no receivers.
port_packet_t pkt = { { 0 } };
st = port_write(w_test_port1, &pkt, 1);
if (st < 0)
return __LINE__;
// Create an empty port group.
port_t pg;
st = port_group(NULL, 0, &pg);
if (st < 0)
return __LINE__;
thread_t *t1 = thread_create(
"receiver",
&receive_thread,
(void *)pg,
DEFAULT_PRIORITY,
DEFAULT_STACK_SIZE
);
thread_resume(t1);
// Wait for the other thread to block on the read.
thread_sleep(20);
// Adding a port that has data available to the port group should wake any
// threads waiting on that port group.
port_group_add(pg, r_test_port1);
if (event_wait_timeout(&group_waiting_sync_evt, 500) != NO_ERROR)
return __LINE__;
st = port_close(w_test_port1);
if (st < 0)
return __LINE__;
st = port_destroy(w_test_port1);
if (st < 0)
return __LINE__;
return 0;
}
#define RUN_TEST(t) result = t(); if (result) goto fail
int port_tests(void)
@@ -593,6 +739,7 @@ int port_tests(void)
RUN_TEST(single_thread_basic);
RUN_TEST(two_threads_basic);
RUN_TEST(group_basic);
RUN_TEST(group_dynamic);
}
printf("all tests passed\n");