Skip to content

Commit 73dd730

Browse files
[libc] implement sys/uio/writev (#122233)
implement sys/uio/writev according to POSIX standard. This vectorized IO API is needed by many logging libraries to achieve atomic logging multiple strings.
1 parent 4c8fdc2 commit 73dd730

File tree

15 files changed

+198
-0
lines changed

15 files changed

+198
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ set(TARGET_LIBC_ENTRYPOINTS
350350

351351
# wchar.h entrypoints
352352
libc.src.wchar.wctob
353+
354+
# sys/uio.h entrypoints
355+
libc.src.sys.uio.writev
353356
)
354357

355358
if(LLVM_LIBC_INCLUDE_SCUDO)

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ set(TARGET_LIBC_ENTRYPOINTS
350350
# wchar.h entrypoints
351351
libc.src.wchar.wctob
352352
libc.src.wchar.btowc
353+
354+
# sys/uio.h entrypoints
355+
libc.src.sys.uio.writev
353356
)
354357

355358
if(LLVM_LIBC_INCLUDE_SCUDO)

libc/hdr/types/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,12 @@ add_proxy_header_library(
333333
FULL_BUILD_DEPENDS
334334
libc.include.llvm-libc-types.uid_t
335335
)
336+
337+
add_proxy_header_library(
338+
struct_iovec
339+
HDRS
340+
struct_iovec.h
341+
FULL_BUILD_DEPENDS
342+
libc.include.llvm-libc-types.struct_iovec
343+
libc.include.sys_uio
344+
)

libc/hdr/types/struct_iovec.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Proxy for struct iovec -------------------------------------------===//
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+
#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_IOVEC_H
9+
#define LLVM_LIBC_HDR_TYPES_STRUCT_IOVEC_H
10+
11+
#ifdef LIBC_FULL_BUILD
12+
13+
#include "include/llvm-libc-types/struct_iovec.h"
14+
15+
#else
16+
17+
#include <sys/uio.h>
18+
19+
#endif // LIBC_FULL_BUILD
20+
21+
#endif // LLVM_LIBC_HDR_TYPES_STRUCT_IOVEC_H

libc/include/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,16 @@ add_header_macro(
632632
.llvm-libc-types.struct_utsname
633633
)
634634

635+
add_header_macro(
636+
sys_uio
637+
../libc/include/sys/uio.yaml
638+
sys/uio.h
639+
DEPENDS
640+
.llvm_libc_common_h
641+
.llvm-libc-types.struct_iovec
642+
.llvm-libc-types.ssize_t
643+
)
644+
635645
add_header_macro(
636646
sys_wait
637647
../libc/include/sys/wait.yaml

libc/include/sys/uio.h.def

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//===-- POSIX header uio.h ------------------------------------------------===//
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_SYS_UIO_H
10+
#define LLVM_LIBC_SYS_UIO_H
11+
12+
#include "__llvm-libc-common.h"
13+
14+
%%public_api()
15+
16+
#endif // LLVM_LIBC_SYS_UIO_H

libc/include/sys/uio.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
header: sys/uio.h
2+
header_template: uio.h.def
3+
macros: []
4+
types:
5+
- type_name: struct_iovec
6+
- type_name: ssize_t
7+
enums: []
8+
objects: []
9+
functions:
10+
- name: writev
11+
standards:
12+
- POSIX
13+
return_type: ssize_t
14+
arguments:
15+
- type: int
16+
- type: const struct iovec *
17+
- type: int

libc/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ add_subdirectory(statvfs)
1111
add_subdirectory(utsname)
1212
add_subdirectory(wait)
1313
add_subdirectory(prctl)
14+
add_subdirectory(uio)

libc/src/sys/uio/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
3+
endif()
4+
5+
add_entrypoint_object(
6+
writev
7+
ALIAS
8+
DEPENDS
9+
.${LIBC_TARGET_OS}.writev
10+
)

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_entrypoint_object(
2+
writev
3+
SRCS
4+
writev.cpp
5+
HDRS
6+
../writev.h
7+
DEPENDS
8+
libc.include.sys_syscall
9+
libc.src.__support.OSUtil.osutil
10+
libc.src.__support.common
11+
libc.src.errno.errno
12+
libc.hdr.types.ssize_t
13+
libc.hdr.types.struct_iovec
14+
)

libc/src/sys/uio/linux/writev.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Implementation file for writev ------------------------------------===//
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+
#include "src/sys/uio/writev.h"
9+
#include "src/__support/OSUtil/syscall.h"
10+
#include "src/__support/common.h"
11+
#include "src/errno/libc_errno.h"
12+
#include <sys/syscall.h>
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
LLVM_LIBC_FUNCTION(ssize_t, writev, (int fd, const iovec *iov, int iovcnt)) {
17+
long ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_writev, fd, iov, iovcnt);
18+
// On failure, return -1 and set errno.
19+
if (ret < 0) {
20+
libc_errno = static_cast<int>(-ret);
21+
return -1;
22+
}
23+
// On success, return number of bytes written.
24+
return static_cast<ssize_t>(ret);
25+
}
26+
27+
} // namespace LIBC_NAMESPACE_DECL

libc/src/sys/uio/writev.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Implementation header for writev ----------------------------------===//
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_UIO_WRITEV_H
10+
#define LLVM_LIBC_SRC_SYS_UIO_WRITEV_H
11+
12+
#include "hdr/types/ssize_t.h"
13+
#include "hdr/types/struct_iovec.h"
14+
#include "src/__support/macros/config.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
ssize_t writev(int fd, const iovec *iov, int iovcnt);
19+
20+
} // namespace LIBC_NAMESPACE_DECL
21+
22+
#endif // LLVM_LIBC_SRC_SYS_UIO_WRITEV_H

libc/test/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ add_subdirectory(wait)
1111
add_subdirectory(prctl)
1212
add_subdirectory(auxv)
1313
add_subdirectory(epoll)
14+
add_subdirectory(uio)

libc/test/src/sys/uio/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
add_custom_target(libc_sys_uio_unittests)
2+
add_libc_unittest(
3+
writev_test
4+
SUITE
5+
libc_sys_uio_unittests
6+
SRCS
7+
writev_test.cpp
8+
DEPENDS
9+
libc.src.errno.errno
10+
libc.src.__support.common
11+
libc.src.sys.uio.writev
12+
libc.src.unistd.close
13+
libc.src.fcntl.open
14+
libc.test.UnitTest.ErrnoSetterMatcher
15+
)

libc/test/src/sys/uio/writev_test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===-- Unittests for writev ----------------------------------------------===//
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/fcntl/open.h"
10+
#include "src/sys/uio/writev.h"
11+
#include "src/unistd/close.h"
12+
#include "test/UnitTest/ErrnoSetterMatcher.h"
13+
#include "test/UnitTest/Test.h"
14+
15+
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
16+
17+
TEST(LlvmLibcSysUioWritevTest, SmokeTest) {
18+
int fd = LIBC_NAMESPACE::open("/dev/null", O_WRONLY);
19+
ASSERT_THAT(fd, returns(GT(0)).with_errno(EQ(0)));
20+
const char *data = "Hello, World!\n";
21+
struct iovec iov[2];
22+
iov[0].iov_base = const_cast<char *>(data);
23+
iov[0].iov_len = 7;
24+
iov[1].iov_base = const_cast<char *>(data + 7);
25+
iov[1].iov_len = 8;
26+
ASSERT_THAT(LIBC_NAMESPACE::writev(fd, iov, 2),
27+
returns(EQ(15)).with_errno(EQ(0)));
28+
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
29+
}

0 commit comments

Comments
 (0)