Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 43 additions & 27 deletions subsys/net/lib/sockets/socketpair.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,13 +369,13 @@ int z_vrfy_zsock_socketpair(int family, int type, int proto,
static ssize_t spair_write(void *obj, const void *buffer, size_t count)
{
int res;
bool is_connected;
int key;
size_t avail;
bool is_nonblock;
bool will_block;
size_t bytes_written;
bool have_local_sem = false;
bool have_remote_sem = false;
bool will_block = false;
struct spair *const spair = (struct spair *)obj;
struct spair *remote = NULL;

Expand All @@ -385,9 +385,10 @@ static ssize_t spair_write(void *obj, const void *buffer, size_t count)
goto out;
}

key = irq_lock();
is_nonblock = sock_is_nonblock(spair);

res = k_sem_take(&spair->sem, K_NO_WAIT);
irq_unlock(key);
if (res < 0) {
if (is_nonblock) {
errno = EAGAIN;
Expand All @@ -401,17 +402,15 @@ static ssize_t spair_write(void *obj, const void *buffer, size_t count)
res = -1;
goto out;
}
is_nonblock = sock_is_nonblock(spair);
}

have_local_sem = true;

remote = z_get_fd_obj(spair->remote,
(const struct fd_op_vtable *)&spair_fd_op_vtable, 0);

is_connected = sock_is_connected(spair);
is_nonblock = sock_is_nonblock(spair);

if (!is_connected) {
if (remote == NULL) {
errno = EPIPE;
res = -1;
goto out;
Expand All @@ -434,14 +433,17 @@ static ssize_t spair_write(void *obj, const void *buffer, size_t count)

have_remote_sem = true;

avail = is_connected ? spair_write_avail(spair) : 0;
if (avail == 0 && is_nonblock) {
errno = EAGAIN;
res = -1;
goto out;
avail = spair_write_avail(spair);

if (avail == 0) {
if (is_nonblock) {
errno = EAGAIN;
res = -1;
goto out;
}
will_block = true;
}

will_block = (count > avail) && !is_nonblock;
if (will_block) {

for (int signaled = false, result = -1; !signaled;
Expand All @@ -464,6 +466,16 @@ static ssize_t spair_write(void *obj, const void *buffer, size_t count)
goto out;
}

remote = z_get_fd_obj(spair->remote,
(const struct fd_op_vtable *)
&spair_fd_op_vtable, 0);

if (remote == NULL) {
errno = EPIPE;
res = -1;
goto out;
}

res = k_sem_take(&remote->sem, K_NO_WAIT);
if (res < 0) {
if (is_nonblock) {
Expand Down Expand Up @@ -569,14 +581,13 @@ static ssize_t spair_write(void *obj, const void *buffer, size_t count)
static ssize_t spair_read(void *obj, void *buffer, size_t count)
{
int res;

int key;
bool is_connected;
size_t avail;
bool is_nonblock;
bool will_block;
size_t bytes_read;

bool have_local_sem = false;
bool will_block = false;
struct spair *const spair = (struct spair *)obj;

if (obj == NULL || buffer == NULL || count == 0) {
Expand All @@ -585,9 +596,10 @@ static ssize_t spair_read(void *obj, void *buffer, size_t count)
goto out;
}

key = irq_lock();
is_nonblock = sock_is_nonblock(spair);

res = k_sem_take(&spair->sem, K_NO_WAIT);
irq_unlock(key);
if (res < 0) {
if (is_nonblock) {
errno = EAGAIN;
Expand All @@ -601,24 +613,28 @@ static ssize_t spair_read(void *obj, void *buffer, size_t count)
res = -1;
goto out;
}
is_nonblock = sock_is_nonblock(spair);
}

have_local_sem = true;

is_connected = sock_is_connected(spair);
avail = spair_read_avail(spair);
will_block = (avail == 0) && !is_nonblock;

if (avail == 0 && !is_connected) {
/* signal EOF */
res = 0;
goto out;
}
if (avail == 0) {
if (!is_connected) {
/* signal EOF */
res = 0;
goto out;
}

if (avail == 0 && is_nonblock) {
errno = EAGAIN;
res = -1;
goto out;
if (is_nonblock) {
errno = EAGAIN;
res = -1;
goto out;
}

will_block = true;
}

if (will_block) {
Expand Down
2 changes: 0 additions & 2 deletions tests/net/socket/socketpair/prj.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
CONFIG_MP_NUM_CPUS=1

# General config
CONFIG_NEWLIB_LIBC=y

Expand Down
83 changes: 42 additions & 41 deletions tests/net/socket/socketpair/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,12 @@

#include <ztest.h>

#include "test_socketpair_thread.h"

/* in happy_path.c */
extern void test_socketpair_AF_LOCAL__SOCK_STREAM__0(void);
extern void test_socketpair_AF_UNIX__SOCK_STREAM__0(void);

/* in nonblock.c */
extern void test_socketpair_write_nonblock(void);
extern void test_socketpair_read_nonblock(void);

/* in block.c */
extern void test_socketpair_write_block(void);
extern void test_socketpair_read_block(void);

/* in closed_ends.c */
extern void test_socketpair_close_one_end_and_write_to_the_other(void);
extern void test_socketpair_close_one_end_and_read_from_the_other(void);

/* in expected_failures.c */
extern void test_socketpair_expected_failures(void);

Expand All @@ -31,63 +21,74 @@ extern void test_socketpair_unsupported_calls(void);
/* in fcntl.c */
extern void test_socketpair_fcntl(void);

/* in nonblock.c */
extern void test_socketpair_read_nonblock(void);
extern void test_socketpair_write_nonblock(void);

/* in block.c */
extern void test_socketpair_read_block(void);
extern void test_socketpair_write_block(void);

/* in closed_ends.c */
extern void test_socketpair_close_one_end_and_read_from_the_other(void);
extern void test_socketpair_close_one_end_and_write_to_the_other(void);

/* in poll.c */
extern void test_socketpair_poll_timeout(void);
extern void test_socketpair_poll_timeout_nonblocking(void);
extern void test_socketpair_poll_close_remote_end_POLLIN(void);
extern void test_socketpair_poll_close_remote_end_POLLOUT(void);
extern void test_socketpair_poll_immediate_data(void);
extern void test_socketpair_poll_delayed_data(void);
extern void test_socketpair_poll_close_remote_end_POLLIN(void);
extern void test_socketpair_poll_close_remote_end_POLLOUT(void);

/* work queue for tests that need an async event */
static K_THREAD_STACK_DEFINE(test_socketpair_work_q_stack, 512);
struct k_work_q test_socketpair_work_q;

void test_main(void)
{
k_thread_system_pool_assign(k_current_get());

k_thread_access_grant(k_current_get(),
&test_socketpair_work_q.queue);

k_work_q_start(&test_socketpair_work_q, test_socketpair_work_q_stack,
K_THREAD_STACK_SIZEOF(test_socketpair_work_q_stack),
CONFIG_MAIN_THREAD_PRIORITY);

ztest_test_suite(
socketpair,

ztest_user_unit_test(test_socketpair_AF_LOCAL__SOCK_STREAM__0),
ztest_user_unit_test(test_socketpair_AF_UNIX__SOCK_STREAM__0),

ztest_user_unit_test(test_socketpair_write_nonblock),
ztest_user_unit_test(test_socketpair_read_nonblock),

ztest_user_unit_test(
test_socketpair_close_one_end_and_write_to_the_other),
ztest_user_unit_test(
test_socketpair_close_one_end_and_read_from_the_other),

ztest_user_unit_test(test_socketpair_expected_failures),

ztest_user_unit_test(test_socketpair_unsupported_calls),

ztest_user_unit_test(test_socketpair_fcntl),

ztest_user_unit_test(test_socketpair_read_nonblock),
ztest_user_unit_test(test_socketpair_write_nonblock),

ztest_user_unit_test(test_socketpair_read_block),
ztest_user_unit_test(test_socketpair_write_block),

ztest_user_unit_test(
test_socketpair_close_one_end_and_read_from_the_other),
ztest_user_unit_test(
test_socketpair_close_one_end_and_write_to_the_other),

ztest_user_unit_test(test_socketpair_poll_timeout),
ztest_user_unit_test(
test_socketpair_poll_timeout_nonblocking),
ztest_user_unit_test(test_socketpair_poll_immediate_data)
);

ztest_run_test_suite(socketpair);

/* 20200509: @cfriedt: experiencing some issues with userspace thread
* / memory permissions that will require some sorting out. Currently
* these tests succeeed for native_posix_64.
*
* This feature is experimental at present.
*/
#if 0
ztest_test_suite(
socketpair_only_kernel,
ztest_user_unit_test(test_socketpair_write_block),
ztest_user_unit_test(test_socketpair_read_block),
ztest_user_unit_test(test_socketpair_poll_immediate_data),
ztest_user_unit_test(test_socketpair_poll_delayed_data),

ztest_user_unit_test(
test_socketpair_poll_close_remote_end_POLLIN),
ztest_user_unit_test(
test_socketpair_poll_close_remote_end_POLLOUT)
);

ztest_run_test_suite(socketpair_only_kernel);
#endif
ztest_run_test_suite(socketpair);
}
Loading