[libc-commits] [libc] 945e022 - [libc] Add GNU extention functions fread_unlocked and fwrite_unlocked.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Wed Apr 20 08:39:58 PDT 2022
Author: Siva Chandra Reddy
Date: 2022-04-20T15:39:27Z
New Revision: 945e0220fd6f744f200ab93829b52c0c3c4031af
URL: https://github.com/llvm/llvm-project/commit/945e0220fd6f744f200ab93829b52c0c3c4031af
DIFF: https://github.com/llvm/llvm-project/commit/945e0220fd6f744f200ab93829b52c0c3c4031af.diff
LOG: [libc] Add GNU extention functions fread_unlocked and fwrite_unlocked.
POSIX locking and unlocking functions flockfile and funlockfile have
also been added. The locking is not recursive yet. A future patch will
make the underlying lock a recursive lock.
Reviewed By: lntue
Differential Revision: https://reviews.llvm.org/D123986
Added:
libc/src/stdio/flockfile.cpp
libc/src/stdio/flockfile.h
libc/src/stdio/fread_unlocked.cpp
libc/src/stdio/fread_unlocked.h
libc/src/stdio/funlockfile.cpp
libc/src/stdio/funlockfile.h
libc/src/stdio/fwrite_unlocked.cpp
libc/src/stdio/fwrite_unlocked.h
libc/test/src/stdio/unlocked_fileop_test.cpp
Modified:
libc/config/linux/x86_64/entrypoints.txt
libc/spec/gnu_ext.td
libc/spec/posix.td
libc/spec/spec.td
libc/spec/stdc.td
libc/src/__support/File/file.cpp
libc/src/__support/File/file.h
libc/src/stdio/CMakeLists.txt
libc/test/src/stdio/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 5fc5d19f75208..c7af459c36381 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -252,10 +252,14 @@ if(LLVM_LIBC_FULL_BUILD)
# stdio.h entrypoints
libc.src.stdio.fclose
+ libc.src.stdio.flockfile
libc.src.stdio.fopen
libc.src.stdio.fread
+ libc.src.stdio.fread_unlocked
libc.src.stdio.fseek
+ libc.src.stdio.funlockfile
libc.src.stdio.fwrite
+ libc.src.stdio.fwrite_unlocked
# signal.h entrypoints
# TODO: Enable signal.h entrypoints after fixing signal.h
diff --git a/libc/spec/gnu_ext.td b/libc/spec/gnu_ext.td
index 99b78deed28b4..14ede61beffd9 100644
--- a/libc/spec/gnu_ext.td
+++ b/libc/spec/gnu_ext.td
@@ -65,10 +65,36 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
]
>;
+ HeaderSpec StdIO = HeaderSpec<
+ "stdio.h",
+ [], // Macros
+ [], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "fread_unlocked",
+ RetValSpec<SizeTType>,
+ [ArgSpec<VoidRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<SizeTType>,
+ ArgSpec<FILERestrictedPtr>]
+ >,
+ FunctionSpec<
+ "fwrite_unlocked",
+ RetValSpec<SizeTType>,
+ [ArgSpec<ConstVoidRestrictedPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<SizeTType>,
+ ArgSpec<FILERestrictedPtr>]
+ >,
+ ]
+ >;
+
let Headers = [
CType,
FEnv,
- Math,
+ Math,
+ StdIO,
String,
];
}
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 13b4ed4ce49d3..fbb6a78225dd8 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -502,12 +502,32 @@ def POSIX : StandardSpec<"POSIX"> {
]
>;
+ HeaderSpec StdIO = HeaderSpec<
+ "stdio.h",
+ [], // Macros
+ [], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "flockfile",
+ RetValSpec<VoidType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
+ "funlockfile",
+ RetValSpec<VoidType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ ]
+ >;
+
let Headers = [
CType,
Errno,
FCntl,
PThread,
Signal,
+ StdIO,
StdLib,
SysMMan,
SysStat,
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 5c947e4a17cad..198900788c50e 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -103,6 +103,10 @@ def QSortCompareT : NamedType<"__qsortcompare_t">;
def AtexitHandlerT : NamedType<"__atexithandler_t">;
+def FILE : NamedType<"FILE">;
+def FILEPtr : PtrType<FILE>;
+def FILERestrictedPtr : RestrictedPtrType<FILE>;
+
//added because __assert_fail needs it.
def UnsignedType : NamedType<"unsigned">;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 7f57a2ddfab02..10a980bf98df3 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1,8 +1,5 @@
def StdC : StandardSpec<"stdc"> {
- NamedType FILE = NamedType<"FILE">;
- PtrType FILEPtr = PtrType<FILE>;
- RestrictedPtrType FILERestrictedPtr = RestrictedPtrType<FILE>;
NamedType StructTmType = NamedType<"struct tm">;
PtrType StructTmPtr = PtrType<StructTmType>;
PtrType TimeTTypePtr = PtrType<TimeTType>;
diff --git a/libc/src/__support/File/file.cpp b/libc/src/__support/File/file.cpp
index 3f2928c5c32e3..95f464d1df8df 100644
--- a/libc/src/__support/File/file.cpp
+++ b/libc/src/__support/File/file.cpp
@@ -16,9 +16,7 @@
namespace __llvm_libc {
-size_t File::write(const void *data, size_t len) {
- FileLock lock(this);
-
+size_t File::write_unlocked(const void *data, size_t len) {
if (!write_allowed()) {
errno = EBADF;
err = true;
@@ -76,9 +74,7 @@ size_t File::write(const void *data, size_t len) {
return len;
}
-size_t File::read(void *data, size_t len) {
- FileLock lock(this);
-
+size_t File::read_unlocked(void *data, size_t len) {
if (!read_allowed()) {
errno = EBADF;
err = true;
diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index 26849ad96b23e..fdc0d45e4c857 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -145,11 +145,27 @@ class File {
f->eof = f->err = false;
}
- // Buffered write of |len| bytes from |data|.
- size_t write(const void *data, size_t len);
+ // Buffered write of |len| bytes from |data| without the file lock.
+ size_t write_unlocked(const void *data, size_t len);
+
+ // Buffered write of |len| bytes from |data| under the file lock.
+ size_t write(const void *data, size_t len) {
+ lock();
+ size_t ret = write_unlocked(data, len);
+ unlock();
+ return ret;
+ }
+
+ // Buffered read of |len| bytes into |data| without the file lock.
+ size_t read_unlocked(void *data, size_t len);
- // Buffered read of |len| bytes into |data|.
- size_t read(void *data, size_t len);
+ // Buffered read of |len| bytes into |data| under the file lock.
+ size_t read(void *data, size_t len) {
+ lock();
+ size_t ret = read_unlocked(data, len);
+ unlock();
+ return ret;
+ }
int seek(long offset, int whence);
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index 19a3cd1c7f776..493244257850d 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -24,6 +24,42 @@ add_entrypoint_object(
libc.src.__support.File.platform_file
)
+add_entrypoint_object(
+ flockfile
+ SRCS
+ flockfile.cpp
+ HDRS
+ flockfile.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ funlockfile
+ SRCS
+ funlockfile.cpp
+ HDRS
+ funlockfile.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ fread_unlocked
+ SRCS
+ fread_unlocked.cpp
+ HDRS
+ fread_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
add_entrypoint_object(
fread
SRCS
@@ -36,6 +72,18 @@ add_entrypoint_object(
libc.src.__support.File.platform_file
)
+add_entrypoint_object(
+ fwrite_unlocked
+ SRCS
+ fwrite_unlocked.cpp
+ HDRS
+ fwrite_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
add_entrypoint_object(
fwrite
SRCS
diff --git a/libc/src/stdio/flockfile.cpp b/libc/src/stdio/flockfile.cpp
new file mode 100644
index 0000000000000..3b13a6f4d813d
--- /dev/null
+++ b/libc/src/stdio/flockfile.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of flockfile ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/flockfile.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(void, flockfile, (::FILE * stream)) {
+ reinterpret_cast<__llvm_libc::File *>(stream)->lock();
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/flockfile.h b/libc/src/stdio/flockfile.h
new file mode 100644
index 0000000000000..961ad8f941cdf
--- /dev/null
+++ b/libc/src/stdio/flockfile.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of flockfile ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FLOCKFILE_H
+#define LLVM_LIBC_SRC_STDIO_FLOCKFILE_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+void flockfile(::FILE *stream);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FLOCKFILE_H
diff --git a/libc/src/stdio/fread_unlocked.cpp b/libc/src/stdio/fread_unlocked.cpp
new file mode 100644
index 0000000000000..162cc4e9a4122
--- /dev/null
+++ b/libc/src/stdio/fread_unlocked.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of fread_unlocked ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fread_unlocked.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(size_t, fread_unlocked,
+ (void *__restrict buffer, size_t size, size_t nmemb,
+ ::FILE *stream)) {
+ return reinterpret_cast<__llvm_libc::File *>(stream)->read_unlocked(
+ buffer, size * nmemb);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/fread_unlocked.h b/libc/src/stdio/fread_unlocked.h
new file mode 100644
index 0000000000000..5c965b0f168cd
--- /dev/null
+++ b/libc/src/stdio/fread_unlocked.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of fread_unlocked -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FREAD_UNLOCKED_H
+#define LLVM_LIBC_SRC_STDIO_FREAD_UNLOCKED_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+size_t fread_unlocked(void *__restrict buffer, size_t size, size_t nmemb,
+ ::FILE *stream);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FREAD_UNLOCKED_H
diff --git a/libc/src/stdio/funlockfile.cpp b/libc/src/stdio/funlockfile.cpp
new file mode 100644
index 0000000000000..6c7dbee303cbb
--- /dev/null
+++ b/libc/src/stdio/funlockfile.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of funlockfile -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/funlockfile.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(void, funlockfile, (::FILE * stream)) {
+ reinterpret_cast<__llvm_libc::File *>(stream)->unlock();
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/funlockfile.h b/libc/src/stdio/funlockfile.h
new file mode 100644
index 0000000000000..cb04b7e9550ec
--- /dev/null
+++ b/libc/src/stdio/funlockfile.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of funlockfile --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FUNLOCKFILE_H
+#define LLVM_LIBC_SRC_STDIO_FUNLOCKFILE_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+void funlockfile(::FILE *stream);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FUNLOCKFILE_H
diff --git a/libc/src/stdio/fwrite_unlocked.cpp b/libc/src/stdio/fwrite_unlocked.cpp
new file mode 100644
index 0000000000000..085b77516d9eb
--- /dev/null
+++ b/libc/src/stdio/fwrite_unlocked.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of fwrite_unlocked ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fwrite_unlocked.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(size_t, fwrite_unlocked,
+ (const void *__restrict buffer, size_t size, size_t nmemb,
+ ::FILE *stream)) {
+ return reinterpret_cast<__llvm_libc::File *>(stream)->write_unlocked(
+ buffer, size * nmemb);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/fwrite_unlocked.h b/libc/src/stdio/fwrite_unlocked.h
new file mode 100644
index 0000000000000..33bcc219d2efa
--- /dev/null
+++ b/libc/src/stdio/fwrite_unlocked.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of fwrite_unlocked ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FWRITE_UNLOCKED_H
+#define LLVM_LIBC_SRC_STDIO_FWRITE_UNLOCKED_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+size_t fwrite_unlocked(const void *__restrict ptr, size_t size, size_t nmemb,
+ ::FILE *__restrict stream);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FWRITE_UNLOCKED_H
diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 45717593007b3..6a955ba742c70 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -14,6 +14,21 @@ add_libc_unittest(
libc.src.stdio.fwrite
)
+add_libc_unittest(
+ unlocked_fileop_test
+ SUITE
+ libc_stdio_unittests
+ SRCS
+ unlocked_fileop_test.cpp
+ DEPENDS
+ libc.src.stdio.fclose
+ libc.src.stdio.flockfile
+ libc.src.stdio.fopen
+ libc.src.stdio.fread_unlocked
+ libc.src.stdio.funlockfile
+ libc.src.stdio.fwrite_unlocked
+)
+
add_subdirectory(printf_core)
add_subdirectory(testdata)
diff --git a/libc/test/src/stdio/unlocked_fileop_test.cpp b/libc/test/src/stdio/unlocked_fileop_test.cpp
new file mode 100644
index 0000000000000..6e936efd7b8bd
--- /dev/null
+++ b/libc/test/src/stdio/unlocked_fileop_test.cpp
@@ -0,0 +1,44 @@
+//===-- Unittests for file operations like fopen, flcose etc --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fclose.h"
+#include "src/stdio/flockfile.h"
+#include "src/stdio/fopen.h"
+#include "src/stdio/fread_unlocked.h"
+#include "src/stdio/funlockfile.h"
+#include "src/stdio/fwrite_unlocked.h"
+#include "utils/UnitTest/Test.h"
+
+#include <stdio.h>
+
+TEST(LlvmLibcFILETest, UnlockedReadAndWrite) {
+ constexpr char FILENAME[] = "testdata/unlocked_read_and_write.test";
+ ::FILE *file = __llvm_libc::fopen(FILENAME, "w");
+ ASSERT_FALSE(file == nullptr);
+ constexpr char CONTENT[] = "1234567890987654321";
+ __llvm_libc::flockfile(file);
+ ASSERT_EQ(sizeof(CONTENT) - 1, __llvm_libc::fwrite_unlocked(
+ CONTENT, 1, sizeof(CONTENT) - 1, file));
+ __llvm_libc::funlockfile(file);
+ ASSERT_EQ(0, __llvm_libc::fclose(file));
+
+ file = __llvm_libc::fopen(FILENAME, "r");
+ ASSERT_FALSE(file == nullptr);
+
+ constexpr size_t READ_SIZE = 5;
+ char data[READ_SIZE * 2 + 1];
+ data[READ_SIZE * 2] = '\0';
+ __llvm_libc::flockfile(file);
+ ASSERT_EQ(__llvm_libc::fread_unlocked(data, 1, READ_SIZE, file), READ_SIZE);
+ ASSERT_EQ(__llvm_libc::fread_unlocked(data + READ_SIZE, 1, READ_SIZE, file),
+ READ_SIZE);
+ __llvm_libc::funlockfile(file);
+ ASSERT_STREQ(data, "1234567890");
+
+ ASSERT_EQ(__llvm_libc::fclose(file), 0);
+}
More information about the libc-commits
mailing list