# 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
]
>;
+ 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,
];
}
]
>;
+ 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,
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">;
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>;
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;
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;
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);
)
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
fread.cpp
)
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
fwrite.cpp
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
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)
--- /dev/null
+//===-- 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);
+}