Skip to content

Commit 0cbaaec

Browse files
move to socketpair to simplify parallelism
1 parent fbb557c commit 0cbaaec

File tree

9 files changed

+283
-228
lines changed

9 files changed

+283
-228
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ if(LLVM_LIBC_FULL_BUILD)
10421042

10431043
# sys/socket.h entrypoints
10441044
libc.src.sys.socket.socket
1045+
libc.src.sys.socket.socketpair
10451046
libc.src.sys.socket.bind
10461047
libc.src.sys.socket.send
10471048
libc.src.sys.socket.sendto

libc/src/sys/socket/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ add_entrypoint_object(
99
.${LIBC_TARGET_OS}.socket
1010
)
1111

12+
add_entrypoint_object(
13+
socketpair
14+
ALIAS
15+
DEPENDS
16+
.${LIBC_TARGET_OS}.socketpair
17+
)
18+
1219
add_entrypoint_object(
1320
bind
1421
ALIAS

libc/src/sys/socket/linux/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ add_entrypoint_object(
1111
libc.src.errno.errno
1212
)
1313

14+
add_entrypoint_object(
15+
socketpair
16+
SRCS
17+
socketpair.cpp
18+
HDRS
19+
../socketpair.h
20+
DEPENDS
21+
libc.include.sys_syscall
22+
libc.include.sys_socket
23+
libc.src.__support.OSUtil.osutil
24+
libc.src.errno.errno
25+
)
26+
1427
add_entrypoint_object(
1528
bind
1629
SRCS
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===-- Linux implementation of socketpair --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/sys/socket/socketpair.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
#include "src/__support/common.h"
13+
14+
#include "src/__support/macros/config.h"
15+
#include "src/errno/libc_errno.h"
16+
17+
#include <linux/net.h> // For SYS_SOCKET socketcall number.
18+
#include <sys/syscall.h> // For syscall numbers.
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
22+
LLVM_LIBC_FUNCTION(int, socketpair,
23+
(int domain, int type, int protocol, int sv[2])) {
24+
#ifdef SYS_socketpair
25+
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketpair, domain, type,
26+
protocol, sv);
27+
#elif defined(SYS_socketcall)
28+
unsigned long sockcall_args[3] = {
29+
static_cast<unsigned long>(domain), static_cast<unsigned long>(type),
30+
static_cast<unsigned long>(protocol), static_cast<unsigned long>(sv)};
31+
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SOCKETPAIR,
32+
sockcall_args);
33+
#else
34+
#error "socket and socketcall syscalls unavailable for this platform."
35+
#endif
36+
if (ret < 0) {
37+
libc_errno = -ret;
38+
return -1;
39+
}
40+
return ret;
41+
}
42+
43+
} // namespace LIBC_NAMESPACE_DECL

libc/src/sys/socket/socketpair.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for socketpair --------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
10+
#define LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
11+
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
int socketpair(int domain, int type, int protocol, int sv[2]);
17+
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H

libc/test/integration/src/sys/socket/linux/CMakeLists.txt

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,30 @@ add_integration_test(
1313
libc.src.errno.errno
1414
libc.src.sys.socket.send
1515
libc.src.sys.socket.recv
16-
libc.src.sys.socket.socket
17-
libc.src.sys.socket.bind
18-
libc.src.sys.socket.connect
19-
libc.src.sys.socket.listen
20-
libc.src.sys.socket.accept
16+
libc.src.sys.socket.socketpair
2117
libc.src.stdio.remove
2218
libc.src.stdio.puts
2319
libc.src.unistd.close
2420
libc.src.unistd.fork
2521
)
2622

23+
add_integration_test(
24+
socket_sendto_recvfrom_test
25+
SUITE
26+
sys-socket-integration-tests
27+
SRCS
28+
socket_sendto_recvfrom_test.cpp
29+
DEPENDS
30+
libc.include.sys_socket
31+
libc.src.errno.errno
32+
libc.src.sys.socket.sendto
33+
libc.src.sys.socket.recvfrom
34+
libc.src.sys.socket.socketpair
35+
libc.src.stdio.remove
36+
libc.src.stdio.puts
37+
libc.src.unistd.close
38+
libc.src.unistd.fork
39+
)
2740

2841
add_integration_test(
2942
socket_sendmsg_recvmsg_test
@@ -36,11 +49,7 @@ add_integration_test(
3649
libc.src.errno.errno
3750
libc.src.sys.socket.sendmsg
3851
libc.src.sys.socket.recvmsg
39-
libc.src.sys.socket.socket
40-
libc.src.sys.socket.bind
41-
libc.src.sys.socket.connect
42-
libc.src.sys.socket.listen
43-
libc.src.sys.socket.accept
52+
libc.src.sys.socket.socketpair
4453
libc.src.stdio.remove
4554
libc.src.stdio.puts
4655
libc.src.unistd.close

libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp

Lines changed: 35 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@
1010

1111
#include "src/stdio/puts.h"
1212
#include "src/stdio/remove.h"
13-
#include "src/sys/socket/accept.h"
14-
#include "src/sys/socket/bind.h"
15-
#include "src/sys/socket/connect.h"
16-
#include "src/sys/socket/listen.h"
1713
#include "src/sys/socket/recv.h"
1814
#include "src/sys/socket/send.h"
19-
#include "src/sys/socket/socket.h"
15+
#include "src/sys/socket/socketpair.h"
2016
#include "src/unistd/close.h"
2117
#include "src/unistd/fork.h"
2218

@@ -28,90 +24,7 @@
2824
const char TEST_MESSAGE[] = "connection successful";
2925
const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
3026

31-
void run_client(const char *SOCK_PATH) {
32-
constexpr size_t SPIN_TRIES = 1000;
33-
int result;
34-
35-
int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
36-
ASSERT_NE(sock, -1);
37-
ASSERT_ERRNO_SUCCESS();
38-
39-
struct sockaddr_un my_addr;
40-
41-
my_addr.sun_family = AF_UNIX;
42-
size_t i = 0;
43-
for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
44-
my_addr.sun_path[i] = SOCK_PATH[i];
45-
my_addr.sun_path[i] = '\0';
46-
47-
// If the connection fails with "EAGAIN" then sleep breifly and try again, but
48-
// only up to SPIN_TRIES times.
49-
LIBC_NAMESPACE::libc_errno = EAGAIN;
50-
for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
51-
++j, LIBC_NAMESPACE::sleep_briefly()) {
52-
LIBC_NAMESPACE::libc_errno = 0;
53-
result = LIBC_NAMESPACE::connect(
54-
sock, reinterpret_cast<struct sockaddr *>(&my_addr),
55-
sizeof(my_addr.sun_path));
56-
}
57-
ASSERT_EQ(result, 0);
58-
ASSERT_ERRNO_SUCCESS();
59-
60-
ssize_t send_result =
61-
LIBC_NAMESPACE::send(sock, TEST_MESSAGE, MESSAGE_LEN, 0);
62-
63-
EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
64-
ASSERT_ERRNO_SUCCESS();
65-
66-
LIBC_NAMESPACE::close(sock);
67-
}
68-
69-
void run_server(const char *SOCK_PATH) {
70-
int result;
71-
72-
int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
73-
ASSERT_NE(sock, -1);
74-
ASSERT_ERRNO_SUCCESS();
75-
76-
struct sockaddr_un my_addr;
77-
78-
my_addr.sun_family = AF_UNIX;
79-
size_t i = 0;
80-
for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
81-
my_addr.sun_path[i] = SOCK_PATH[i];
82-
my_addr.sun_path[i] = '\0';
83-
84-
result =
85-
LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
86-
sizeof(my_addr.sun_path));
87-
ASSERT_EQ(result, 0);
88-
ASSERT_ERRNO_SUCCESS();
89-
90-
result = LIBC_NAMESPACE::listen(sock, 1);
91-
ASSERT_EQ(result, 0);
92-
ASSERT_ERRNO_SUCCESS();
93-
94-
struct sockaddr connected_sock;
95-
socklen_t sockaddr_len = sizeof(struct sockaddr);
96-
97-
int accepted_sock =
98-
LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
99-
ASSERT_NE(accepted_sock, -1);
100-
ASSERT_ERRNO_SUCCESS();
101-
102-
char buffer[256];
103-
104-
ssize_t recv_result =
105-
LIBC_NAMESPACE::recv(accepted_sock, buffer, sizeof(buffer), 0);
106-
ASSERT_EQ(recv_result, MESSAGE_LEN);
107-
ASSERT_ERRNO_SUCCESS();
108-
109-
for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
110-
ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
111-
}
112-
113-
LIBC_NAMESPACE::close(sock);
114-
}
27+
#define SEND_TEST_NAME "Send/Recv"
11528

11629
TEST_MAIN(int argc, char **argv, char **envp) {
11730

@@ -124,21 +37,47 @@ TEST_MAIN(int argc, char **argv, char **envp) {
12437
LIBC_NAMESPACE::remove(SOCK_PATH);
12538
LIBC_NAMESPACE::libc_errno = 0;
12639

127-
LIBC_NAMESPACE::puts("Send/Recv Test Start");
40+
int sockpair[2] = {0, 0};
41+
42+
int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
43+
ASSERT_EQ(result, 0);
44+
ASSERT_ERRNO_SUCCESS();
45+
46+
LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
12847

12948
// split into client and server processes.
13049
pid_t pid = LIBC_NAMESPACE::fork();
13150
ASSERT_NE(pid, -1);
13251
ASSERT_ERRNO_SUCCESS();
13352

13453
if (pid == 0) { // child
135-
LIBC_NAMESPACE::puts("Send/Recv Child Start");
136-
run_client(SOCK_PATH);
137-
LIBC_NAMESPACE::puts("Send/Recv Child End");
54+
LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
55+
LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
56+
57+
ssize_t send_result =
58+
LIBC_NAMESPACE::send(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0);
59+
EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
60+
ASSERT_ERRNO_SUCCESS();
61+
62+
LIBC_NAMESPACE::close(sockpair[0]); // close child sock
63+
LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
13864
} else { // parent
139-
LIBC_NAMESPACE::puts("Send/Recv Parent Start");
140-
run_server(SOCK_PATH);
141-
LIBC_NAMESPACE::puts("Send/Recv Parent End");
65+
LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
66+
LIBC_NAMESPACE::close(sockpair[0]); // close child sock
67+
68+
char buffer[256];
69+
70+
ssize_t recv_result =
71+
LIBC_NAMESPACE::recv(sockpair[1], buffer, sizeof(buffer), 0);
72+
ASSERT_EQ(recv_result, MESSAGE_LEN);
73+
ASSERT_ERRNO_SUCCESS();
74+
75+
for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
76+
ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
77+
}
78+
79+
LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
80+
LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
14281
}
14382
return 0;
14483
}

0 commit comments

Comments
 (0)