[libc] Add implementation of POSIX setrlimit and getrlimit functions.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D134016
This commit is contained in:
Siva Chandra Reddy 2022-09-15 22:22:59 +00:00
parent c2cf93c1a9
commit f5cbbb9988
23 changed files with 391 additions and 0 deletions

View File

@ -271,6 +271,10 @@ def UniStdAPI : PublicAPI<"unistd.h"> {
let Types = ["off_t", "size_t", "ssize_t"];
}
def SysResourceAPI : PublicAPI<"sys/resource.h"> {
let Types = ["rlim_t", "struct rlimit_t"];
}
def SysStatAPI : PublicAPI<"sys/stat.h"> {
let Types = ["mode_t"];
}

View File

@ -101,6 +101,10 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
# sys/resource.h entrypoints
libc.src.sys.resource.getrlimit
libc.src.sys.resource.setrlimit
# sys/sendfile entrypoints
libc.src.sys.sendfile.sendfile

View File

@ -203,6 +203,17 @@ add_gen_header(
.llvm-libc-types.ssize_t
)
add_gen_header(
sys_resource
DEF_FILE sys/resource.h.def
GEN_HDR sys/resource.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_resource_macros
.llvm-libc-types.rlim_t
.llvm-libc-types.struct_rlimit_t
)
add_gen_header(
sys_stat
DEF_FILE sys/stat.h.def

View File

@ -22,6 +22,14 @@ add_header(
.linux.sys_stat_macros
)
add_header(
sys_resource_macros
HDR
sys-resource-macros.h
DEPENDS
.linux.sys_resource_macros
)
add_header(
unistd_macros
HDR

View File

@ -10,6 +10,12 @@ add_header(
sys-stat-macros.h
)
add_header(
sys_resource_macros
HDR
sys-resource-macros.h
)
add_header(
unistd_macros
HDR

View File

@ -0,0 +1,26 @@
//===-- Macros defined in sys/resource.h header file ----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#define RLIMIT_CPU 0
#define RLIMIT_FSIZE 1
#define RLIMIT_DATA 2
#define RLIMIT_STACK 3
#define RLIMIT_CORE 4
#define RLIMIT_RSS 5
#define RLIMIT_NPROC 6
#define RLIMIT_NOFILE 7
#define RLIMIT_MEMLOCK 8
#define RLIMIT_AS 9
#define RLIMIT_LOCKS 10
#define RLIMIT_SIGPENDING 11
#define RLIMIT_MSGQUEUE 12
#define RLIMIT_NICE 13
#define RLIMIT_RTPRIO 14
#define RLIMIT_RTTIME 15
#define RLIM_INFINITY (~0UL)

View File

@ -0,0 +1,16 @@
//===-- Macros defined in sys/resource.h header file ----------------------===//
//
// 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_MACROS_SYS_RESOURCE_MACROS_H
#define __LLVM_LIBC_MACROS_SYS_RESOURCE_MACROS_H
#ifdef __unix__
#include "linux/sys-resource-macros.h"
#endif
#endif // __LLVM_LIBC_MACROS_SYS_RESOURCE_MACROS_H

View File

@ -31,6 +31,8 @@ add_header(pthread_key_t HDR pthread_key_t.h)
add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type)
add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h)
add_header(rlim_t HDR rlim_t.h)
add_header(struct_rlimit_t HDR struct_rlimit_t.h DEPENDS .rlim_t)
add_header(ssize_t HDR ssize_t.h)
add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t)
add_header(struct_sigaction HDR struct_sigaction.h)

View File

@ -0,0 +1,14 @@
//===-- Definition of type rlim_t -----------------------------------------===//
//
// 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_TYPES_RLIM_T_H__
#define __LLVM_LIBC_TYPES_RLIM_T_H__
typedef unsigned long rlim_t;
#endif // __LLVM_LIBC_TYPES_RLIM_T_H__

View File

@ -0,0 +1,19 @@
//===-- Definition of type rlimit_t ---------------------------------------===//
//
// 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_TYPES_RLIMIT_T_H__
#define __LLVM_LIBC_TYPES_RLIMIT_T_H__
#include <llvm-libc-types/rlim_t.h>
struct rlimit_t {
rlim_t rlim_cur;
rlim_t rlim_max;
};
#endif // __LLVM_LIBC_TYPES_RLIMIT_T_H__

View File

@ -0,0 +1,18 @@
//===-- POSIX header resource.h -------------------------------------------===//
//
// 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_SYS_RESOURCE_H
#define LLVM_LIBC_SYS_RESOURCE_H
#include <__llvm-libc-common.h>
#include <llvm-libc-macros/sys-resource-macros.h>
%%public_api()
#endif // LLVM_LIBC_SYS_RESOURCE_H

View File

@ -465,6 +465,29 @@ def POSIX : StandardSpec<"POSIX"> {
]
>;
NamedType RLimTType = NamedType<"rlim_t">;
NamedType StructRLimitTType = NamedType<"struct rlimit_t">;
PtrType StructRLimitPtr = PtrType<StructRLimitTType>;
ConstType ConstStructRLimitPtr = ConstType<StructRLimitTType>;
HeaderSpec SysResource = HeaderSpec<
"sys/resource.h",
[], // Macros
[RLimTType, StructRLimitTType], // Types
[], // Enumerations
[
FunctionSpec<
"getrlimit",
RetValSpec<IntType>,
[ArgSpec<StructRLimitPtr>]
>,
FunctionSpec<
"setrlimit",
RetValSpec<IntType>,
[ArgSpec<ConstStructRLimitPtr>]
>,
]
>;
HeaderSpec SysStat = HeaderSpec<
"sys/stat.h",
[], // Macros
@ -764,6 +787,7 @@ def POSIX : StandardSpec<"POSIX"> {
StdIO,
StdLib,
SysMMan,
SysResource,
SysStat,
UniStd,
String

View File

@ -1,3 +1,4 @@
add_subdirectory(mman)
add_subdirectory(resource)
add_subdirectory(sendfile)
add_subdirectory(stat)

View File

@ -0,0 +1,17 @@
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
endif()
add_entrypoint_object(
getrlimit
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.getrlimit
)
add_entrypoint_object(
setrlimit
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.setrlimit
)

View File

@ -0,0 +1,20 @@
//===-- Implementation header for getrlimit ---------------------*- 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_SYS_STAT_GETRLIMIT_H
#define LLVM_LIBC_SRC_SYS_STAT_GETRLIMIT_H
#include <sys/resource.h>
namespace __llvm_libc {
int getrlimit(int resource, struct rlimit_t *lim);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_SYS_STAT_GETRLIMIT_H

View File

@ -0,0 +1,25 @@
add_entrypoint_object(
getrlimit
SRCS
getrlimit.cpp
HDRS
../getrlimit.h
DEPENDS
libc.include.sys_resource
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
add_entrypoint_object(
setrlimit
SRCS
setrlimit.cpp
HDRS
../setrlimit.h
DEPENDS
libc.include.sys_resource
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)

View File

@ -0,0 +1,29 @@
//===-- Linux implementation of getrlimit ---------------------------------===//
//
// 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/sys/resource/getrlimit.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include <errno.h>
#include <sys/resource.h> // For struct rlimit_t
#include <sys/syscall.h> // For syscall numbers.
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, getrlimit, (int res, struct rlimit_t *limits)) {
long ret = __llvm_libc::syscall(SYS_prlimit64, 0, res, nullptr, limits);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
}
} // namespace __llvm_libc

View File

@ -0,0 +1,29 @@
//===-- Linux implementation of setrlimit ---------------------------------===//
//
// 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/sys/resource/setrlimit.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include <errno.h>
#include <sys/resource.h> // For struct rlimit_t
#include <sys/syscall.h> // For syscall numbers.
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, setrlimit, (int res, const struct rlimit_t *limits)) {
long ret = __llvm_libc::syscall(SYS_prlimit64, 0, res, limits, nullptr);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
}
} // namespace __llvm_libc

View File

@ -0,0 +1,20 @@
//===-- Implementation header for setrlimit ---------------------*- 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_SYS_STAT_SETRLIMIT_H
#define LLVM_LIBC_SRC_SYS_STAT_SETRLIMIT_H
#include <sys/resource.h>
namespace __llvm_libc {
int setrlimit(int resource, const struct rlimit_t *lim);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_SYS_STAT_SETRLIMIT_H

View File

@ -1,3 +1,4 @@
add_subdirectory(mman)
add_subdirectory(resource)
add_subdirectory(sendfile)
add_subdirectory(stat)

View File

@ -0,0 +1,20 @@
add_libc_testsuite(libc_sys_resource_unittests)
add_subdirectory(testdata)
add_libc_unittest(
getrlimit_setrlimit_test
SUITE
libc_sys_resource_unittests
SRCS
getrlimit_setrlimit_test.cpp
DEPENDS
libc.include.errno
libc.include.fcntl
libc.include.sys_resource
libc.src.fcntl.open
libc.src.sys.resource.getrlimit
libc.src.sys.resource.setrlimit
libc.src.unistd.close
libc.src.unistd.unlink
)

View File

@ -0,0 +1,77 @@
//===-- Unittests for getrlimit and setrlimit -----------------------------===//
//
// 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/__support/CPP/string_view.h"
#include "src/fcntl/open.h"
#include "src/sys/resource/getrlimit.h"
#include "src/sys/resource/setrlimit.h"
#include "src/unistd/close.h"
#include "src/unistd/unlink.h"
#include "test/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"
#include <errno.h>
#include <sys/resource.h>
TEST(LlvmLibcResourceLimitsTest, SetNoFileLimit) {
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
// The test strategy is to first create initialize two file descriptors
// successfully. Next, close the files and set the file descriptor limit
// to 4. This will allow us to open one of those file but not the other.
constexpr const char *TEST_FILE1 = "testdata/resource_limits1.test";
constexpr const char *TEST_FILE2 = "testdata/resource_limits2.test";
errno = 0;
int fd1 = __llvm_libc::open(TEST_FILE1, O_CREAT | O_WRONLY, S_IRWXU);
ASSERT_GT(fd1, 0);
ASSERT_EQ(errno, 0);
int fd2 = __llvm_libc::open(TEST_FILE2, O_CREAT | O_WRONLY, S_IRWXU);
ASSERT_GT(fd2, 0);
ASSERT_EQ(errno, 0);
ASSERT_THAT(__llvm_libc::close(fd1), Succeeds(0));
ASSERT_THAT(__llvm_libc::close(fd2), Succeeds(0));
struct rlimit_t limits {
4, 4
};
ASSERT_THAT(__llvm_libc::setrlimit(RLIMIT_NOFILE, &limits), Succeeds(0));
// One can now only open one of the files successfully.
fd1 = __llvm_libc::open(TEST_FILE1, O_RDONLY);
ASSERT_GT(fd1, 0);
ASSERT_EQ(errno, 0);
fd2 = __llvm_libc::open(TEST_FILE2, O_RDONLY);
ASSERT_LT(fd2, 0);
ASSERT_NE(errno, 0);
errno = 0;
ASSERT_THAT(__llvm_libc::close(fd1), Succeeds(0));
fd2 = __llvm_libc::open(TEST_FILE2, O_RDONLY);
ASSERT_GT(fd2, 0);
ASSERT_EQ(errno, 0);
fd1 = __llvm_libc::open(TEST_FILE1, O_RDONLY);
ASSERT_LT(fd1, 0);
ASSERT_NE(errno, 0);
errno = 0;
ASSERT_THAT(__llvm_libc::close(fd2), Succeeds(0));
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE1), Succeeds(0));
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE2), Succeeds(0));
struct rlimit_t current_limits;
ASSERT_THAT(__llvm_libc::getrlimit(RLIMIT_NOFILE, &current_limits),
Succeeds(0));
ASSERT_EQ(current_limits.rlim_cur, rlim_t(4));
ASSERT_EQ(current_limits.rlim_max, rlim_t(4));
}

View File