Skip to content

Commit f6f42af

Browse files
[libc] Add shm_open/shm_unlink (#84974)
1 parent 0c423af commit f6f42af

File tree

17 files changed

+435
-3
lines changed

17 files changed

+435
-3
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ set(TARGET_LIBC_ENTRYPOINTS
216216
libc.src.sys.mman.mlockall
217217
libc.src.sys.mman.munlockall
218218
libc.src.sys.mman.msync
219+
libc.src.sys.mman.shm_open
220+
libc.src.sys.mman.shm_unlink
219221

220222
# sys/random.h entrypoints
221223
libc.src.sys.random.getrandom

libc/config/linux/api.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def SchedAPI : PublicAPI<"sched.h"> {
117117
}
118118

119119
def SysMManAPI : PublicAPI<"sys/mman.h"> {
120-
let Types = ["off_t", "size_t"];
120+
let Types = ["off_t", "size_t", "mode_t"];
121121
}
122122

123123
def SignalAPI : PublicAPI<"signal.h"> {

libc/config/linux/riscv/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ set(TARGET_LIBC_ENTRYPOINTS
221221
libc.src.sys.mman.mlockall
222222
libc.src.sys.mman.munlockall
223223
libc.src.sys.mman.msync
224+
libc.src.sys.mman.shm_open
225+
libc.src.sys.mman.shm_unlink
224226

225227
# sys/random.h entrypoints
226228
libc.src.sys.random.getrandom

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ set(TARGET_LIBC_ENTRYPOINTS
229229
libc.src.sys.mman.mlockall
230230
libc.src.sys.mman.munlockall
231231
libc.src.sys.mman.msync
232+
libc.src.sys.mman.shm_open
233+
libc.src.sys.mman.shm_unlink
232234

233235
# sys/random.h entrypoints
234236
libc.src.sys.random.getrandom

libc/docs/dev/undefined_behavior.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,7 @@ Design Decisions
7070
Resizable Tables for hsearch
7171
----------------------------
7272
The POSIX.1 standard does not delineate the behavior consequent to invoking hsearch or hdestroy without prior initialization of the hash table via hcreate. Furthermore, the standard does not specify the outcomes of successive invocations of hsearch absent intervening hdestroy calls. Libraries such as MUSL and Glibc do not apply checks to these scenarios, potentially leading to memory corruption or leakage. Conversely, FreeBSD's libc and Bionic automatically initialize the hash table to a minimal size if it is found uninitialized, and proceeding to destroy the table only if initialization has occurred. This approach also avoids redundant table allocation if an initialized hash table is already present. Given that the hash table starts with a minimal size, resizing becomes necessary to accommodate additional user insertions. LLVM's libc mirrors the approach of FreeBSD's libc and Bionic, owing to its enhanced robustness and user-friendliness. Notably, such resizing behavior itself aligns with POSIX.1 standards, which explicitly permit implementations to modify the capacity of the hash table.
73+
74+
Path without Leading Slashs in shm_open
75+
----------------------------------------
76+
POSIX.1 leaves that when the name of a shared memory object does not begin with a slash, the behavior is implementation defined. In such cases, the shm_open in LLVM libc is implemented to behave as if the name began with a slash.

libc/spec/posix.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def POSIX : StandardSpec<"POSIX"> {
246246
[
247247
SizeTType,
248248
OffTType,
249+
ModeTType,
249250
],
250251
[], // Enumerations
251252
[
@@ -310,6 +311,16 @@ def POSIX : StandardSpec<"POSIX"> {
310311
RetValSpec<IntType>,
311312
[ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
312313
>,
314+
FunctionSpec<
315+
"shm_open",
316+
RetValSpec<IntType>,
317+
[ArgSpec<ConstCharPtr>, ArgSpec<IntType>, ArgSpec<ModeTType>]
318+
>,
319+
FunctionSpec<
320+
"shm_unlink",
321+
RetValSpec<IntType>,
322+
[ArgSpec<ConstCharPtr>]
323+
>,
313324
]
314325
>;
315326

libc/src/__support/CPP/string_view.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,38 @@ class string_view {
179179
LIBC_INLINE char back() const { return Data[Len - 1]; }
180180

181181
// Finds the first occurence of c in this view, starting at position From.
182-
LIBC_INLINE size_t find_first_of(const char c, size_t From = 0) const {
182+
LIBC_INLINE constexpr size_t find_first_of(const char c,
183+
size_t From = 0) const {
183184
for (size_t Pos = From; Pos < size(); ++Pos)
184185
if ((*this)[Pos] == c)
185186
return Pos;
186187
return npos;
187188
}
188189

189190
// Finds the last occurence of c in this view, ending at position End.
190-
LIBC_INLINE size_t find_last_of(const char c, size_t End = npos) const {
191+
LIBC_INLINE constexpr size_t find_last_of(const char c,
192+
size_t End = npos) const {
191193
End = End >= size() ? size() : End + 1;
192194
for (; End > 0; --End)
193195
if ((*this)[End - 1] == c)
194196
return End - 1;
195197
return npos;
196198
}
199+
200+
// Finds the first character not equal to c in this view, starting at position
201+
// From.
202+
LIBC_INLINE constexpr size_t find_first_not_of(const char c,
203+
size_t From = 0) const {
204+
for (size_t Pos = From; Pos < size(); ++Pos)
205+
if ((*this)[Pos] != c)
206+
return Pos;
207+
return npos;
208+
}
209+
210+
// Check if this view contains the given character.
211+
LIBC_INLINE constexpr bool contains(char c) const {
212+
return find_first_of(c) != npos;
213+
}
197214
};
198215

199216
} // namespace cpp

libc/src/sys/mman/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,17 @@ add_entrypoint_object(
8585
DEPENDS
8686
.${LIBC_TARGET_OS}.msync
8787
)
88+
89+
add_entrypoint_object(
90+
shm_open
91+
ALIAS
92+
DEPENDS
93+
.${LIBC_TARGET_OS}.shm_open
94+
)
95+
96+
add_entrypoint_object(
97+
shm_unlink
98+
ALIAS
99+
DEPENDS
100+
.${LIBC_TARGET_OS}.shm_unlink
101+
)

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,40 @@ add_entrypoint_object(
152152
libc.src.__support.OSUtil.osutil
153153
libc.src.errno.errno
154154
)
155+
156+
add_header_library(
157+
shm_common
158+
HDRS
159+
shm_common.h
160+
DEPENDS
161+
libc.src.__support.CPP.array
162+
libc.src.__support.CPP.string_view
163+
libc.src.__support.CPP.optional
164+
libc.src.__support.common
165+
libc.src.errno.errno
166+
libc.src.string.memory_utils.inline_memcpy
167+
)
168+
169+
add_entrypoint_object(
170+
shm_open
171+
SRCS
172+
shm_open.cpp
173+
HDRS
174+
../shm_open.h
175+
DEPENDS
176+
libc.src.fcntl.open
177+
libc.include.llvm-libc-macros.fcntl_macros
178+
libc.include.llvm-libc-types.mode_t
179+
.shm_common
180+
)
181+
182+
add_entrypoint_object(
183+
shm_unlink
184+
SRCS
185+
shm_unlink.cpp
186+
HDRS
187+
../shm_unlink.h
188+
DEPENDS
189+
libc.src.unistd.unlink
190+
.shm_common
191+
)

libc/src/sys/mman/linux/shm_common.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//===---------- Shared implementations for shm_open/shm_unlink ------------===//
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/__support/CPP/array.h"
10+
#include "src/__support/CPP/optional.h"
11+
#include "src/__support/CPP/string_view.h"
12+
#include "src/errno/libc_errno.h"
13+
#include "src/string/memory_utils/inline_memcpy.h"
14+
15+
// TODO: Get PATH_MAX via https://github.com/llvm/llvm-project/issues/85121
16+
#include <linux/limits.h>
17+
18+
namespace LIBC_NAMESPACE {
19+
20+
namespace shm_common {
21+
22+
LIBC_INLINE_VAR constexpr cpp::string_view SHM_PREFIX = "/dev/shm/";
23+
using SHMPath = cpp::array<char, NAME_MAX + SHM_PREFIX.size() + 1>;
24+
25+
LIBC_INLINE cpp::optional<SHMPath> translate_name(cpp::string_view name) {
26+
// trim leading slashes
27+
size_t offset = name.find_first_not_of('/');
28+
if (offset == cpp::string_view::npos) {
29+
libc_errno = EINVAL;
30+
return cpp::nullopt;
31+
}
32+
name = name.substr(offset);
33+
34+
// check the name
35+
if (name.size() > NAME_MAX) {
36+
libc_errno = ENAMETOOLONG;
37+
return cpp::nullopt;
38+
}
39+
if (name == "." || name == ".." || name.contains('/')) {
40+
libc_errno = EINVAL;
41+
return cpp::nullopt;
42+
}
43+
44+
// prepend the prefix
45+
SHMPath buffer;
46+
inline_memcpy(buffer.data(), SHM_PREFIX.data(), SHM_PREFIX.size());
47+
inline_memcpy(buffer.data() + SHM_PREFIX.size(), name.data(), name.size());
48+
buffer[SHM_PREFIX.size() + name.size()] = '\0';
49+
return buffer;
50+
}
51+
} // namespace shm_common
52+
53+
} // namespace LIBC_NAMESPACE

libc/src/sys/mman/linux/shm_open.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===---------- Linux implementation of the shm_open function -------------===//
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/mman/shm_open.h"
10+
#include "llvm-libc-macros/fcntl-macros.h"
11+
#include "src/fcntl/open.h"
12+
#include "src/sys/mman/linux/shm_common.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK;
17+
18+
LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
19+
using namespace shm_common;
20+
if (cpp::optional<SHMPath> buffer = translate_name(name))
21+
return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
22+
return -1;
23+
}
24+
25+
} // namespace LIBC_NAMESPACE
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===---------- Linux implementation of the shm_unlink function -----------===//
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/mman/shm_unlink.h"
10+
#include "src/sys/mman/linux/shm_common.h"
11+
#include "src/unistd/unlink.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
16+
using namespace shm_common;
17+
if (cpp::optional<SHMPath> buffer = translate_name(name))
18+
return unlink(buffer->data());
19+
return -1;
20+
}
21+
22+
} // namespace LIBC_NAMESPACE

libc/src/sys/mman/shm_open.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for shm_open function -------------*- 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_MMAN_SHM_OPEN_H
10+
#define LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
11+
12+
#include <llvm-libc-types/mode_t.h>
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int shm_open(const char *name, int oflag, mode_t mode);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H

libc/src/sys/mman/shm_unlink.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===-- Implementation header for shm_unlink function ------------*- 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_MMAN_SHM_UNLINK_H
10+
#define LLVM_LIBC_SRC_SYS_MMAN_SHM_UNLINK_H
11+
12+
namespace LIBC_NAMESPACE {
13+
14+
int shm_unlink(const char *name);
15+
16+
} // namespace LIBC_NAMESPACE
17+
18+
#endif // LLVM_LIBC_SRC_SYS_MMAN_SHM_UNLINK_H

0 commit comments

Comments
 (0)