[libc-commits] [libc] [libc][sys/sem][sys/ipc] Adding syscall wrapper implementation for sys/sem and sys/ipc on linux x86_64 (PR #182683)

Pengxiang Huang via libc-commits libc-commits at lists.llvm.org
Sat Feb 21 07:49:46 PST 2026


https://github.com/Pengxiang-Huang created https://github.com/llvm/llvm-project/pull/182683

This pull request implements for the corresponding issue: https://github.com/llvm/llvm-project/issues/182161, @SchrodingerZhu 

The implementation includes a system call wrapper for sys V semaphore, since <sys/sem.h> includes on the <sys/ipc.h>, thus the <sys/ipc.h> is also implemented as a wrapper in this pull request. 

The implementation follows the POSIX standard for ipc and sem: 
https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_ipc.h.html and 
https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_sem.h.html

since it is a system call wrapper implementation, this implementation only target on the linux platform and follows the linux ABI requirements for the data structure that syscall required. More specifically, the data structure `ipc_perm` and `semid_ds` are not compliant across platforms thus we only implement it for linux. 

Two unit tests are added for sys/ipc and sys/sem; one for each. This implementation also only declare the headers and entrypoints for x86_64 platform as it is only tested on such platform. 

>From 65dcdf94b5479e4bd9b10fece6e6cd2b9072f64a Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Fri, 20 Feb 2026 15:22:09 -0500
Subject: [PATCH 1/4] add headers, types, macros for sys/sem, since sem
 requires sys/ipc, ipc is added as well

---
 libc/include/CMakeLists.txt                   | 29 ++++++++++++++
 libc/include/llvm-libc-macros/CMakeLists.txt  | 12 ++++++
 .../llvm-libc-macros/linux/CMakeLists.txt     | 12 ++++++
 .../llvm-libc-macros/linux/sys-ipc-macros.h   | 24 ++++++++++++
 .../llvm-libc-macros/linux/sys-sem-macros.h   | 24 ++++++++++++
 .../include/llvm-libc-macros/sys-ipc-macros.h | 16 ++++++++
 .../include/llvm-libc-macros/sys-sem-macros.h | 16 ++++++++
 libc/include/llvm-libc-types/CMakeLists.txt   | 17 +++++++++
 libc/include/llvm-libc-types/key_t.h          | 14 +++++++
 .../include/llvm-libc-types/struct_ipc_perm.h | 24 ++++++++++++
 libc/include/llvm-libc-types/struct_sembuf.h  | 18 +++++++++
 .../include/llvm-libc-types/struct_semid_ds.h | 22 +++++++++++
 libc/include/sys/ipc.h.def                    | 18 +++++++++
 libc/include/sys/ipc.yaml                     | 20 ++++++++++
 libc/include/sys/sem.h.def                    | 19 ++++++++++
 libc/include/sys/sem.yaml                     | 38 +++++++++++++++++++
 libc/include/sys/types.yaml                   |  1 +
 17 files changed, 324 insertions(+)
 create mode 100644 libc/include/llvm-libc-macros/linux/sys-ipc-macros.h
 create mode 100644 libc/include/llvm-libc-macros/linux/sys-sem-macros.h
 create mode 100644 libc/include/llvm-libc-macros/sys-ipc-macros.h
 create mode 100644 libc/include/llvm-libc-macros/sys-sem-macros.h
 create mode 100644 libc/include/llvm-libc-types/key_t.h
 create mode 100644 libc/include/llvm-libc-types/struct_ipc_perm.h
 create mode 100644 libc/include/llvm-libc-types/struct_sembuf.h
 create mode 100644 libc/include/llvm-libc-types/struct_semid_ds.h
 create mode 100644 libc/include/sys/ipc.h.def
 create mode 100644 libc/include/sys/ipc.yaml
 create mode 100644 libc/include/sys/sem.h.def
 create mode 100644 libc/include/sys/sem.yaml

diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index c6254aafe3849..5c1f3b030e10d 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -557,6 +557,20 @@ add_header_macro(
     .llvm-libc-macros.sys_ioctl_macros
 )
 
+add_header_macro(
+  sys_ipc
+  ../libc/include/sys/ipc.yaml
+  sys/ipc.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.sys_ipc_macros
+    .llvm-libc-types.key_t
+    .llvm-libc-types.uid_t
+    .llvm-libc-types.gid_t
+    .llvm-libc-types.mode_t
+    .llvm-libc-types.struct_ipc_perm
+)
+
 add_header_macro(
   sys_mman
   ../libc/include/sys/mman.yaml
@@ -643,6 +657,20 @@ add_header_macro(
     .llvm-libc-types.struct_timeval
 )
 
+add_header_macro(
+  sys_sem
+  ../libc/include/sys/sem.yaml
+  sys/sem.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.sys_sem_macros
+    .llvm-libc-types.key_t
+    .llvm-libc-types.size_t
+    .llvm-libc-types.struct_ipc_perm
+    .llvm-libc-types.struct_semid_ds
+    .llvm-libc-types.struct_sembuf
+)
+
 add_header_macro(
   sys_sendfile
   ../libc/include/sys/sendfile.yaml
@@ -708,6 +736,7 @@ add_header_macro(
     .llvm-libc-types.dev_t
     .llvm-libc-types.gid_t
     .llvm-libc-types.ino_t
+    .llvm-libc-types.key_t
     .llvm-libc-types.mode_t
     .llvm-libc-types.nlink_t
     .llvm-libc-types.off_t
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index b16337cccd58b..6285283cc763c 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -226,6 +226,12 @@ add_macro_header(
     sys-ioctl-macros.h
 )
 
+add_macro_header(
+  sys_ipc_macros
+  HDR
+    sys-ipc-macros.h
+)
+
 add_macro_header(
   sys_stat_macros
   HDR
@@ -265,6 +271,12 @@ add_macro_header(
     sys-select-macros.h
 )
 
+add_macro_header(
+  sys_sem_macros
+  HDR
+    sys-sem-macros.h
+)
+
 add_macro_header(
   sys_socket_macros
   HDR
diff --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt
index 61da55eabd40b..e6a95457a5b91 100644
--- a/libc/include/llvm-libc-macros/linux/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt
@@ -34,12 +34,24 @@ add_header(
     sys-ioctl-macros.h
 )
 
+add_header(
+  sys_ipc_macros
+  HDR
+    sys-ipc-macros.h
+)
+
 add_header(
   sys_random_macros
   HDR
     sys-random-macros.h
 )
 
+add_header(
+  sys_sem_macros
+  HDR
+    sys-sem-macros.h
+)
+
 add_header(
   sys_socket_macros
   HDR
diff --git a/libc/include/llvm-libc-macros/linux/sys-ipc-macros.h b/libc/include/llvm-libc-macros/linux/sys-ipc-macros.h
new file mode 100644
index 0000000000000..111f48542c518
--- /dev/null
+++ b/libc/include/llvm-libc-macros/linux/sys-ipc-macros.h
@@ -0,0 +1,24 @@
+//===-- Definition of macros from sys/ipc.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_MACROS_LINUX_SYS_IPC_MACROS_H
+#define LLVM_LIBC_MACROS_LINUX_SYS_IPC_MACROS_H
+
+#define IPC_PRIVATE 0
+
+// Resource get request flags.
+#define IPC_CREAT 00001000
+#define IPC_EXCL 00002000
+#define IPC_NOWAIT 00004000
+
+// Control commands used with semctl, msgctl, and shmctl.
+#define IPC_RMID 0
+#define IPC_SET 1
+#define IPC_STAT 2
+
+#endif // LLVM_LIBC_MACROS_LINUX_SYS_IPC_MACROS_H
diff --git a/libc/include/llvm-libc-macros/linux/sys-sem-macros.h b/libc/include/llvm-libc-macros/linux/sys-sem-macros.h
new file mode 100644
index 0000000000000..f6a7a2ed83d45
--- /dev/null
+++ b/libc/include/llvm-libc-macros/linux/sys-sem-macros.h
@@ -0,0 +1,24 @@
+//===-- Definition of macros from sys/sem.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_MACROS_LINUX_SYS_SEM_MACROS_H
+#define LLVM_LIBC_MACROS_LINUX_SYS_SEM_MACROS_H
+
+// semop flags
+#define SEM_UNDO 0x1000
+
+// semctl command definitions
+#define GETPID 11
+#define GETVAL 12
+#define GETALL 13
+#define GETNCNT 14
+#define GETZCNT 15
+#define SETVAL 16
+#define SETALL 17
+
+#endif // LLVM_LIBC_MACROS_LINUX_SYS_SEM_MACROS_H
diff --git a/libc/include/llvm-libc-macros/sys-ipc-macros.h b/libc/include/llvm-libc-macros/sys-ipc-macros.h
new file mode 100644
index 0000000000000..37e7e45456d2a
--- /dev/null
+++ b/libc/include/llvm-libc-macros/sys-ipc-macros.h
@@ -0,0 +1,16 @@
+//===-- Macros defined in sys/ipc.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_IPC_MACROS_H
+#define LLVM_LIBC_MACROS_SYS_IPC_MACROS_H
+
+#ifdef __linux__
+#include "linux/sys-ipc-macros.h"
+#endif
+
+#endif // LLVM_LIBC_MACROS_SYS_IPC_MACROS_H
diff --git a/libc/include/llvm-libc-macros/sys-sem-macros.h b/libc/include/llvm-libc-macros/sys-sem-macros.h
new file mode 100644
index 0000000000000..801f82e79f5d4
--- /dev/null
+++ b/libc/include/llvm-libc-macros/sys-sem-macros.h
@@ -0,0 +1,16 @@
+//===-- Macros defined in sys/sem.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_SEM_MACROS_H
+#define LLVM_LIBC_MACROS_SYS_SEM_MACROS_H
+
+#ifdef __linux__
+#include "linux/sys-sem-macros.h"
+#endif
+
+#endif // LLVM_LIBC_MACROS_SYS_SEM_MACROS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index dc36dfeadba57..70e4d7fd5d923 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -44,6 +44,7 @@ add_header(in_addr HDR in_addr.h DEPENDS .in_addr_t)
 add_header(ino_t HDR ino_t.h)
 add_header(mbstate_t HDR mbstate_t.h)
 add_header(mode_t HDR mode_t.h)
+add_header(key_t HDR key_t.h)
 add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type)
 add_header(nfds_t HDR nfds_t.h)
 add_header(nl_catd HDR nl_catd.h)
@@ -79,9 +80,25 @@ add_header(dl_info HDR Dl_info.h)
 add_header(struct_f_owner_ex HDR struct_f_owner_ex.h DEPENDS .pid_t)
 add_header(struct_flock HDR struct_flock.h DEPENDS .off_t .pid_t)
 add_header(struct_flock64 HDR struct_flock64.h DEPENDS .off64_t .pid_t)
+add_header(
+  struct_ipc_perm
+  HDR struct_ipc_perm.h
+  DEPENDS
+    .uid_t
+    .gid_t
+    .mode_t
+)
 add_header(struct_pollfd HDR struct_pollfd.h)
 add_header(struct_rlimit HDR struct_rlimit.h DEPENDS .rlim_t)
 add_header(struct_sched_param HDR struct_sched_param.h)
+add_header(struct_sembuf HDR struct_sembuf.h)
+add_header(
+  struct_semid_ds
+  HDR struct_semid_ds.h
+  DEPENDS
+    .struct_ipc_perm
+    .time_t
+)
 add_header(struct_timeval HDR struct_timeval.h DEPENDS .suseconds_t .time_t)
 add_header(struct_itimerval HDR struct_itimerval.h DEPENDS .struct_timeval)
 add_header(struct_rusage HDR struct_rusage.h DEPENDS .struct_timeval)
diff --git a/libc/include/llvm-libc-types/key_t.h b/libc/include/llvm-libc-types/key_t.h
new file mode 100644
index 0000000000000..1515469880862
--- /dev/null
+++ b/libc/include/llvm-libc-types/key_t.h
@@ -0,0 +1,14 @@
+//===-- Definition of key_t type ------------------------------------------===//
+//
+// 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_KEY_T_H
+#define LLVM_LIBC_TYPES_KEY_T_H
+
+typedef __INT32_TYPE__ key_t;
+
+#endif // LLVM_LIBC_TYPES_KEY_T_H
diff --git a/libc/include/llvm-libc-types/struct_ipc_perm.h b/libc/include/llvm-libc-types/struct_ipc_perm.h
new file mode 100644
index 0000000000000..064865fba7240
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_ipc_perm.h
@@ -0,0 +1,24 @@
+//===-- Definition of struct ipc_perm -------------------------------------===//
+//
+// 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_STRUCT_IPC_PERM_H
+#define LLVM_LIBC_TYPES_STRUCT_IPC_PERM_H
+
+#include "gid_t.h"
+#include "mode_t.h"
+#include "uid_t.h"
+
+struct ipc_perm {
+  uid_t uid;
+  gid_t gid;
+  uid_t cuid;
+  gid_t cgid;
+  mode_t mode;
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_IPC_PERM_H
diff --git a/libc/include/llvm-libc-types/struct_sembuf.h b/libc/include/llvm-libc-types/struct_sembuf.h
new file mode 100644
index 0000000000000..4f1171698acc6
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_sembuf.h
@@ -0,0 +1,18 @@
+//===-- Definition of struct sembuf ---------------------------------------===//
+//
+// 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_STRUCT_SEMBUF_H
+#define LLVM_LIBC_TYPES_STRUCT_SEMBUF_H
+
+struct sembuf {
+  unsigned short sem_num;
+  short sem_op;
+  short sem_flg;
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_SEMBUF_H
diff --git a/libc/include/llvm-libc-types/struct_semid_ds.h b/libc/include/llvm-libc-types/struct_semid_ds.h
new file mode 100644
index 0000000000000..4fadabcf7b730
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_semid_ds.h
@@ -0,0 +1,22 @@
+//===-- Definition of struct semid_ds -------------------------------------===//
+//
+// 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_STRUCT_SEMID_DS_H
+#define LLVM_LIBC_TYPES_STRUCT_SEMID_DS_H
+
+#include "struct_ipc_perm.h"
+#include "time_t.h"
+
+struct semid_ds {
+  struct ipc_perm sem_perm;
+  unsigned short sem_nsems;
+  time_t sem_otime;
+  time_t sem_ctime;
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_SEMID_DS_H
diff --git a/libc/include/sys/ipc.h.def b/libc/include/sys/ipc.h.def
new file mode 100644
index 0000000000000..cf06e1d2565b4
--- /dev/null
+++ b/libc/include/sys/ipc.h.def
@@ -0,0 +1,18 @@
+//===-- POSIX header sys/ipc.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_IPC_H
+#define LLVM_LIBC_SYS_IPC_H
+
+#include "__llvm-libc-common.h"
+
+#include "../llvm-libc-macros/sys-ipc-macros.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_IPC_H
diff --git a/libc/include/sys/ipc.yaml b/libc/include/sys/ipc.yaml
new file mode 100644
index 0000000000000..3c608243c7fc5
--- /dev/null
+++ b/libc/include/sys/ipc.yaml
@@ -0,0 +1,20 @@
+header: sys/ipc.h
+header_template: ipc.h.def
+standards:
+  - POSIX
+types:
+  - type_name: key_t
+  - type_name: uid_t
+  - type_name: gid_t
+  - type_name: mode_t
+  - type_name: struct_ipc_perm
+functions:
+  - name: ftok
+    standards:
+      - POSIX
+    return_type: key_t
+    arguments:
+      - type: const char *
+      - type: int
+enums: []
+objects: []
diff --git a/libc/include/sys/sem.h.def b/libc/include/sys/sem.h.def
new file mode 100644
index 0000000000000..dd98f77535459
--- /dev/null
+++ b/libc/include/sys/sem.h.def
@@ -0,0 +1,19 @@
+//===-- POSIX header sys/sem.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_SEM_H
+#define LLVM_LIBC_SYS_SEM_H
+
+#include "__llvm-libc-common.h"
+
+#include "ipc.h"
+#include "../llvm-libc-macros/sys-sem-macros.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_SEM_H
diff --git a/libc/include/sys/sem.yaml b/libc/include/sys/sem.yaml
new file mode 100644
index 0000000000000..552b83acb9fb4
--- /dev/null
+++ b/libc/include/sys/sem.yaml
@@ -0,0 +1,38 @@
+header: sys/sem.h
+header_template: sem.h.def
+standards:
+  - POSIX
+types:
+  - type_name: key_t
+  - type_name: size_t
+  - type_name: struct_ipc_perm
+  - type_name: struct_semid_ds
+  - type_name: struct_sembuf
+functions:
+  - name: semctl
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: int
+      - type: int
+      - type: int
+      - type: '...'
+  - name: semget
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: key_t
+      - type: int
+      - type: int
+  - name: semop
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: int
+      - type: struct sembuf *
+      - type: size_t
+enums: []
+objects: []
diff --git a/libc/include/sys/types.yaml b/libc/include/sys/types.yaml
index a00429d3817e1..126c597b30353 100644
--- a/libc/include/sys/types.yaml
+++ b/libc/include/sys/types.yaml
@@ -8,6 +8,7 @@ types:
   - type_name: dev_t
   - type_name: gid_t
   - type_name: ino_t
+  - type_name: key_t
   - type_name: mode_t
   - type_name: nlink_t
   - type_name: off_t

>From 5d16b8c974644c15d54c44ed0d78512892956f7e Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Fri, 20 Feb 2026 16:13:16 -0500
Subject: [PATCH 2/4] add src for sys/ipc and sys/sem, implemented by system
 call wrapper

---
 libc/src/sys/CMakeLists.txt           |  2 +
 libc/src/sys/ipc/CMakeLists.txt       | 10 +++
 libc/src/sys/ipc/ftok.h               | 22 ++++++
 libc/src/sys/ipc/linux/CMakeLists.txt | 10 +++
 libc/src/sys/ipc/linux/ftok.cpp       | 28 ++++++++
 libc/src/sys/sem/CMakeLists.txt       | 24 +++++++
 libc/src/sys/sem/linux/CMakeLists.txt | 38 +++++++++++
 libc/src/sys/sem/linux/semctl.cpp     | 98 +++++++++++++++++++++++++++
 libc/src/sys/sem/linux/semget.cpp     | 32 +++++++++
 libc/src/sys/sem/linux/semop.cpp      | 32 +++++++++
 libc/src/sys/sem/semctl.h             | 21 ++++++
 libc/src/sys/sem/semget.h             | 22 ++++++
 libc/src/sys/sem/semop.h              | 22 ++++++
 13 files changed, 361 insertions(+)
 create mode 100644 libc/src/sys/ipc/CMakeLists.txt
 create mode 100644 libc/src/sys/ipc/ftok.h
 create mode 100644 libc/src/sys/ipc/linux/CMakeLists.txt
 create mode 100644 libc/src/sys/ipc/linux/ftok.cpp
 create mode 100644 libc/src/sys/sem/CMakeLists.txt
 create mode 100644 libc/src/sys/sem/linux/CMakeLists.txt
 create mode 100644 libc/src/sys/sem/linux/semctl.cpp
 create mode 100644 libc/src/sys/sem/linux/semget.cpp
 create mode 100644 libc/src/sys/sem/linux/semop.cpp
 create mode 100644 libc/src/sys/sem/semctl.h
 create mode 100644 libc/src/sys/sem/semget.h
 create mode 100644 libc/src/sys/sem/semop.h

diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index 0fa11e9eee696..41becce798ddd 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -1,10 +1,12 @@
 add_subdirectory(auxv)
 add_subdirectory(epoll)
+add_subdirectory(ipc)
 add_subdirectory(mman)
 add_subdirectory(random)
 add_subdirectory(resource)
 add_subdirectory(select)
 add_subdirectory(socket)
+add_subdirectory(sem)
 add_subdirectory(sendfile)
 add_subdirectory(stat)
 add_subdirectory(statvfs)
diff --git a/libc/src/sys/ipc/CMakeLists.txt b/libc/src/sys/ipc/CMakeLists.txt
new file mode 100644
index 0000000000000..e20ac7e3f964e
--- /dev/null
+++ b/libc/src/sys/ipc/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  ftok
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.ftok
+)
diff --git a/libc/src/sys/ipc/ftok.h b/libc/src/sys/ipc/ftok.h
new file mode 100644
index 0000000000000..6b9d0fa40b028
--- /dev/null
+++ b/libc/src/sys/ipc/ftok.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for ftok ---------------------------*- 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_IPC_FTOK_H
+#define LLVM_LIBC_SRC_SYS_IPC_FTOK_H
+
+#include "src/__support/macros/config.h"
+#include <sys/ipc.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+key_t ftok(const char *path, int id);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_IPC_FTOK_H
diff --git a/libc/src/sys/ipc/linux/CMakeLists.txt b/libc/src/sys/ipc/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..c2fdebcf989dc
--- /dev/null
+++ b/libc/src/sys/ipc/linux/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_entrypoint_object(
+  ftok
+  SRCS
+    ftok.cpp
+  HDRS
+    ../ftok.h
+  DEPENDS
+    libc.include.sys_ipc
+    libc.src.sys.stat.stat
+)
diff --git a/libc/src/sys/ipc/linux/ftok.cpp b/libc/src/sys/ipc/linux/ftok.cpp
new file mode 100644
index 0000000000000..6d0920c77ced3
--- /dev/null
+++ b/libc/src/sys/ipc/linux/ftok.cpp
@@ -0,0 +1,28 @@
+//===-- Linux implementation of ftok -------------------------------------===//
+//
+// 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/ipc/ftok.h"
+
+#include "src/__support/common.h"
+#include "src/sys/stat/stat.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(key_t, ftok, (const char *path, int id)) {
+
+  // ftok implements based on stat
+  struct stat st;
+  if (LIBC_NAMESPACE::stat(path, &st) < 0)
+    return -1;
+
+  return static_cast<key_t>(((id & 0xff) << 24) |
+                            ((static_cast<int>(st.st_dev) & 0xff) << 16) |
+                            (static_cast<int>(st.st_ino) & 0xffff));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/sem/CMakeLists.txt b/libc/src/sys/sem/CMakeLists.txt
new file mode 100644
index 0000000000000..4b9bd851b9d2d
--- /dev/null
+++ b/libc/src/sys/sem/CMakeLists.txt
@@ -0,0 +1,24 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  semget
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.semget
+)
+
+add_entrypoint_object(
+  semctl
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.semctl
+)
+
+add_entrypoint_object(
+  semop
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.semop
+)
diff --git a/libc/src/sys/sem/linux/CMakeLists.txt b/libc/src/sys/sem/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..11b4ee6e98c6f
--- /dev/null
+++ b/libc/src/sys/sem/linux/CMakeLists.txt
@@ -0,0 +1,38 @@
+add_entrypoint_object(
+  semget
+  SRCS
+    semget.cpp
+  HDRS
+    ../semget.h
+  DEPENDS
+    libc.include.sys_sem
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  semctl
+  SRCS
+    semctl.cpp
+  HDRS
+    ../semctl.h
+  DEPENDS
+    libc.include.sys_sem
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  semop
+  SRCS
+    semop.cpp
+  HDRS
+    ../semop.h
+  DEPENDS
+    libc.include.sys_sem
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
diff --git a/libc/src/sys/sem/linux/semctl.cpp b/libc/src/sys/sem/linux/semctl.cpp
new file mode 100644
index 0000000000000..926d9c69e0fb1
--- /dev/null
+++ b/libc/src/sys/sem/linux/semctl.cpp
@@ -0,0 +1,98 @@
+//===-- Linux implementation of semctl ------------------------------------===//
+//
+// 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/sem/semctl.h"
+
+#include "hdr/errno_macros.h"             // For EINVAL
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include <stdarg.h>
+#include <sys/sem.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, semctl, (int semid, int semnum, int cmd, ...)) {
+  // mask cmd before start matching
+  int masked_cmd = cmd & 0xff;
+
+  unsigned long cmd_arg = 0;
+
+  // if user specified the fourth argument vararg,
+  // it expects type union semun:
+  // union semun {
+  //  int val;
+  //  struct semid_ds *buf;
+  //  unsigned short  *array;
+  // } arg;
+
+  // handle the control operation and vararg based on cmd
+  switch (masked_cmd) {
+    // does not take vararg argument
+  case IPC_RMID:
+  case GETVAL:
+  case GETPID:
+  case GETNCNT:
+  case GETZCNT:
+    break;
+
+    // take one argument
+    // union semun is int val
+  case SETVAL: {
+    va_list vargs;
+    va_start(vargs, cmd);
+    cmd_arg = static_cast<unsigned long>(va_arg(vargs, int));
+    va_end(vargs);
+    break;
+  }
+
+    // take one argument
+    // union semun is struct semid_ds *buf
+  case IPC_SET:
+  case IPC_STAT: {
+    va_list vargs;
+    va_start(vargs, cmd);
+    cmd_arg = reinterpret_cast<unsigned long>(va_arg(vargs, struct semid_ds *));
+    va_end(vargs);
+    break;
+  }
+
+    // take one argument
+    // union semun is unsigned short *array
+  case GETALL:
+  case SETALL: {
+    va_list vargs;
+    va_start(vargs, cmd);
+    cmd_arg = reinterpret_cast<unsigned long>(va_arg(vargs, unsigned short *));
+    va_end(vargs);
+    break;
+  }
+
+    // no such case
+    // wrong cmd
+  default:
+    libc_errno = EINVAL;
+    return -1;
+  }
+
+#ifdef SYS_semctl
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_semctl, semid, semnum,
+                                              masked_cmd, cmd_arg);
+#else
+#error "semctl syscall not available."
+#endif
+
+  if (ret < 0) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/sem/linux/semget.cpp b/libc/src/sys/sem/linux/semget.cpp
new file mode 100644
index 0000000000000..42eb068e9cbbb
--- /dev/null
+++ b/libc/src/sys/sem/linux/semget.cpp
@@ -0,0 +1,32 @@
+//===-- Linux implementation of semget ------------------------------------===//
+//
+// 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/sem/semget.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, semget, (key_t key, int nsems, int semflg)) {
+#ifdef SYS_semget
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_semget, key, nsems, semflg);
+#else
+#error "semget syscall not available."
+#endif
+
+  if (ret < 0) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/sem/linux/semop.cpp b/libc/src/sys/sem/linux/semop.cpp
new file mode 100644
index 0000000000000..54b1a41dacf00
--- /dev/null
+++ b/libc/src/sys/sem/linux/semop.cpp
@@ -0,0 +1,32 @@
+//===-- Linux implementation of semop -------------------------------------===//
+//
+// 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/sem/semop.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, semop, (int semid, struct sembuf *sops, size_t nsops)) {
+#ifdef SYS_semop
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_semop, semid, sops, nsops);
+#else
+#error "semop syscall not available."
+#endif
+
+  if (ret < 0) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/sem/semctl.h b/libc/src/sys/sem/semctl.h
new file mode 100644
index 0000000000000..78d689d62f3a5
--- /dev/null
+++ b/libc/src/sys/sem/semctl.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for semctl -------------------------*- 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_SEM_SEMCTL_H
+#define LLVM_LIBC_SRC_SYS_SEM_SEMCTL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int semctl(int semid, int semnum, int cmd, ...);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SEM_SEMCTL_H
diff --git a/libc/src/sys/sem/semget.h b/libc/src/sys/sem/semget.h
new file mode 100644
index 0000000000000..b6e97e55ffbd5
--- /dev/null
+++ b/libc/src/sys/sem/semget.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for semget -------------------------*- 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_SEM_SEMGET_H
+#define LLVM_LIBC_SRC_SYS_SEM_SEMGET_H
+
+#include "src/__support/macros/config.h"
+#include <sys/sem.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int semget(key_t key, int nsems, int semflg);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SEM_SEMGET_H
diff --git a/libc/src/sys/sem/semop.h b/libc/src/sys/sem/semop.h
new file mode 100644
index 0000000000000..62e87c547fad7
--- /dev/null
+++ b/libc/src/sys/sem/semop.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for semop --------------------------*- 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_SEM_SEMOP_H
+#define LLVM_LIBC_SRC_SYS_SEM_SEMOP_H
+
+#include "src/__support/macros/config.h"
+#include <sys/sem.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int semop(int semid, struct sembuf *sops, size_t nsops);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SEM_SEMOP_H

>From 142ab574dbbde8ab14a8c679e06d4ded2fa16c6e Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Fri, 20 Feb 2026 17:13:15 -0500
Subject: [PATCH 3/4] add config for entrypoints and declare the headers; now
 ONLY on x86_64

---
 libc/config/linux/x86_64/entrypoints.txt | 8 ++++++++
 libc/config/linux/x86_64/headers.txt     | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 6f0ecf0c6885d..14338dad5903b 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -251,6 +251,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     # sys/ioctl.h entrypoints
     libc.src.sys.ioctl.ioctl
 
+    # sys/ipc.h entrypoints
+    libc.src.sys.ipc.ftok
+
+    # sys/sem.h entrypoints
+    libc.src.sys.sem.semget
+    libc.src.sys.sem.semctl
+    libc.src.sys.sem.semop
+
     # sys/mman.h entrypoints
     libc.src.sys.mman.madvise
     libc.src.sys.mman.mincore
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index d0f62eb104dcc..19e12b528b8a1 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -38,11 +38,13 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.sys_auxv
     libc.include.sys_epoll
     libc.include.sys_ioctl
+    libc.include.sys_ipc
     libc.include.sys_mman
     libc.include.sys_prctl
     libc.include.sys_queue
     libc.include.sys_random
     libc.include.sys_resource
+    libc.include.sys_sem
     libc.include.sys_select
     libc.include.sys_socket
     libc.include.sys_stat

>From 3167fb28434cb4e1d897841fb5743fc7f483ea36 Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Sat, 21 Feb 2026 10:23:53 -0500
Subject: [PATCH 4/4] change the ipc and sem data structure to align linux
 standard to match the syscall interface; reason is that the struct layouts
 are not compliant across all Unix systems. add tests for ipc and sem, one
 test for each

---
 .../include/llvm-libc-types/struct_ipc_perm.h | 13 +++-
 .../include/llvm-libc-types/struct_semid_ds.h | 14 +++-
 libc/include/sys/ipc.h.def                    |  2 +-
 libc/include/sys/ipc.yaml                     |  5 +-
 libc/include/sys/sem.h.def                    |  2 +-
 libc/include/sys/sem.yaml                     |  8 +--
 libc/test/src/sys/CMakeLists.txt              |  2 +
 libc/test/src/sys/ipc/CMakeLists.txt          |  3 +
 libc/test/src/sys/ipc/linux/CMakeLists.txt    | 19 +++++
 libc/test/src/sys/ipc/linux/ftok_test.cpp     | 59 ++++++++++++++++
 libc/test/src/sys/sem/CMakeLists.txt          |  3 +
 libc/test/src/sys/sem/linux/CMakeLists.txt    | 18 +++++
 libc/test/src/sys/sem/linux/sem_test.cpp      | 69 +++++++++++++++++++
 13 files changed, 203 insertions(+), 14 deletions(-)
 create mode 100644 libc/test/src/sys/ipc/CMakeLists.txt
 create mode 100644 libc/test/src/sys/ipc/linux/CMakeLists.txt
 create mode 100644 libc/test/src/sys/ipc/linux/ftok_test.cpp
 create mode 100644 libc/test/src/sys/sem/CMakeLists.txt
 create mode 100644 libc/test/src/sys/sem/linux/CMakeLists.txt
 create mode 100644 libc/test/src/sys/sem/linux/sem_test.cpp

diff --git a/libc/include/llvm-libc-types/struct_ipc_perm.h b/libc/include/llvm-libc-types/struct_ipc_perm.h
index 064865fba7240..60c021cd5a1cf 100644
--- a/libc/include/llvm-libc-types/struct_ipc_perm.h
+++ b/libc/include/llvm-libc-types/struct_ipc_perm.h
@@ -10,15 +10,24 @@
 #define LLVM_LIBC_TYPES_STRUCT_IPC_PERM_H
 
 #include "gid_t.h"
-#include "mode_t.h"
+#include "key_t.h"
 #include "uid_t.h"
 
+#ifdef __linux__
 struct ipc_perm {
+  key_t __key;
   uid_t uid;
   gid_t gid;
   uid_t cuid;
   gid_t cgid;
-  mode_t mode;
+  unsigned short mode;
+  unsigned short seq;
+  unsigned short padding;
+  unsigned long unused_0;
+  unsigned long unused_1;
 };
+#else
+#error "ipc_perm not defined for the target platform"
+#endif
 
 #endif // LLVM_LIBC_TYPES_STRUCT_IPC_PERM_H
diff --git a/libc/include/llvm-libc-types/struct_semid_ds.h b/libc/include/llvm-libc-types/struct_semid_ds.h
index 4fadabcf7b730..48e4b173bb462 100644
--- a/libc/include/llvm-libc-types/struct_semid_ds.h
+++ b/libc/include/llvm-libc-types/struct_semid_ds.h
@@ -12,11 +12,19 @@
 #include "struct_ipc_perm.h"
 #include "time_t.h"
 
+#ifdef __linux__
 struct semid_ds {
   struct ipc_perm sem_perm;
-  unsigned short sem_nsems;
-  time_t sem_otime;
-  time_t sem_ctime;
+  time_t sem_otime; // last semop time
+  unsigned long otime_high;
+  time_t sem_ctime; // last time changed by semctl
+  unsigned long ctime_high;
+  unsigned long sem_nsems;
+  unsigned long unused0;
+  unsigned long unused1;
 };
+#else
+#error "semid_ds not defined for the target platform"
+#endif
 
 #endif // LLVM_LIBC_TYPES_STRUCT_SEMID_DS_H
diff --git a/libc/include/sys/ipc.h.def b/libc/include/sys/ipc.h.def
index cf06e1d2565b4..8688bad8a1159 100644
--- a/libc/include/sys/ipc.h.def
+++ b/libc/include/sys/ipc.h.def
@@ -1,4 +1,4 @@
-//===-- POSIX header sys/ipc.h --------------------------------------------===//
+//===-- Linux header sys/ipc.h --------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/include/sys/ipc.yaml b/libc/include/sys/ipc.yaml
index 3c608243c7fc5..172f5f64a3398 100644
--- a/libc/include/sys/ipc.yaml
+++ b/libc/include/sys/ipc.yaml
@@ -1,17 +1,16 @@
 header: sys/ipc.h
 header_template: ipc.h.def
 standards:
-  - POSIX
+  - Linux
 types:
   - type_name: key_t
   - type_name: uid_t
   - type_name: gid_t
-  - type_name: mode_t
   - type_name: struct_ipc_perm
 functions:
   - name: ftok
     standards:
-      - POSIX
+      - Linux
     return_type: key_t
     arguments:
       - type: const char *
diff --git a/libc/include/sys/sem.h.def b/libc/include/sys/sem.h.def
index dd98f77535459..3014c986e25ad 100644
--- a/libc/include/sys/sem.h.def
+++ b/libc/include/sys/sem.h.def
@@ -1,4 +1,4 @@
-//===-- POSIX header sys/sem.h --------------------------------------------===//
+//===-- Linux header sys/sem.h --------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/include/sys/sem.yaml b/libc/include/sys/sem.yaml
index 552b83acb9fb4..769db5c4df6c0 100644
--- a/libc/include/sys/sem.yaml
+++ b/libc/include/sys/sem.yaml
@@ -1,7 +1,7 @@
 header: sys/sem.h
 header_template: sem.h.def
 standards:
-  - POSIX
+  - Linux
 types:
   - type_name: key_t
   - type_name: size_t
@@ -11,7 +11,7 @@ types:
 functions:
   - name: semctl
     standards:
-      - POSIX
+      - Linux
     return_type: int
     arguments:
       - type: int
@@ -20,7 +20,7 @@ functions:
       - type: '...'
   - name: semget
     standards:
-      - POSIX
+      - Linux
     return_type: int
     arguments:
       - type: key_t
@@ -28,7 +28,7 @@ functions:
       - type: int
   - name: semop
     standards:
-      - POSIX
+      - Linux
     return_type: int
     arguments:
       - type: int
diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index 13bf91eef04be..937a5ca196a70 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -2,6 +2,7 @@ add_subdirectory(mman)
 add_subdirectory(random)
 add_subdirectory(resource)
 add_subdirectory(select)
+add_subdirectory(sem)
 add_subdirectory(sendfile)
 add_subdirectory(socket)
 add_subdirectory(stat)
@@ -11,6 +12,7 @@ add_subdirectory(wait)
 add_subdirectory(prctl)
 add_subdirectory(auxv)
 add_subdirectory(epoll)
+add_subdirectory(ipc)
 add_subdirectory(uio)
 add_subdirectory(time)
 add_subdirectory(ioctl)
diff --git a/libc/test/src/sys/ipc/CMakeLists.txt b/libc/test/src/sys/ipc/CMakeLists.txt
new file mode 100644
index 0000000000000..b4bbe81c92ff2
--- /dev/null
+++ b/libc/test/src/sys/ipc/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/src/sys/ipc/linux/CMakeLists.txt b/libc/test/src/sys/ipc/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..21d501a3029ef
--- /dev/null
+++ b/libc/test/src/sys/ipc/linux/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_custom_target(libc_sys_ipc_unittests)
+
+add_libc_unittest(
+  ftok_test
+  SUITE
+    libc_sys_ipc_unittests
+  SRCS
+    ftok_test.cpp
+  DEPENDS
+    libc.hdr.fcntl_macros
+    libc.include.sys_ipc
+    libc.src.errno.errno
+    libc.src.fcntl.open
+    libc.src.sys.ipc.ftok
+    libc.src.unistd.close
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/ipc/linux/ftok_test.cpp b/libc/test/src/sys/ipc/linux/ftok_test.cpp
new file mode 100644
index 0000000000000..dd9a4702d439b
--- /dev/null
+++ b/libc/test/src/sys/ipc/linux/ftok_test.cpp
@@ -0,0 +1,59 @@
+//===-- Unittests for ftok ------------------------------------------------===//
+//
+// 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/fcntl/open.h"
+#include "src/sys/ipc/ftok.h"
+#include "src/unistd/close.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include "hdr/fcntl_macros.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcFtokTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcFtokTest, InvalidPath) {
+  ASSERT_THAT(LIBC_NAMESPACE::ftok("no/such/path", 1), Fails(ENOENT));
+}
+
+TEST_F(LlvmLibcFtokTest, DeterministicForPathAndId) {
+  // create a file
+  constexpr const char *TEST_FILE_NAME = "ftok.test";
+  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
+
+  // we first ensure such file exist and set to readable, writable
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY, 0600);
+  ASSERT_GT(fd, -1);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+  // create keys based on file path and user specified int
+  key_t key1 = LIBC_NAMESPACE::ftok(TEST_FILE, 'A');
+  ASSERT_NE(key1, key_t(-1));
+  ASSERT_ERRNO_SUCCESS();
+
+  key_t key2 = LIBC_NAMESPACE::ftok(TEST_FILE, 'A');
+  ASSERT_NE(key2, key_t(-1));
+  ASSERT_ERRNO_SUCCESS();
+
+  // key should be identical if both inputs are the same
+  ASSERT_EQ(key1, key2);
+
+  // create another key
+  key_t key3 = LIBC_NAMESPACE::ftok(TEST_FILE, 'B');
+  ASSERT_NE(key3, key_t(-1));
+  ASSERT_ERRNO_SUCCESS();
+
+  // key should be different if any input is different
+  ASSERT_NE(key1, key3);
+
+  // delete the file
+  ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+}
diff --git a/libc/test/src/sys/sem/CMakeLists.txt b/libc/test/src/sys/sem/CMakeLists.txt
new file mode 100644
index 0000000000000..b4bbe81c92ff2
--- /dev/null
+++ b/libc/test/src/sys/sem/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/src/sys/sem/linux/CMakeLists.txt b/libc/test/src/sys/sem/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..0de92270d8c2b
--- /dev/null
+++ b/libc/test/src/sys/sem/linux/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_custom_target(libc_sys_sem_unittests)
+
+add_libc_unittest(
+  sem_test
+  SUITE
+    libc_sys_sem_unittests
+  SRCS
+    sem_test.cpp
+  DEPENDS
+    libc.include.sys_ipc
+    libc.include.sys_sem
+    libc.src.errno.errno
+    libc.src.sys.sem.semget
+    libc.src.sys.sem.semctl
+    libc.src.sys.sem.semop
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/sem/linux/sem_test.cpp b/libc/test/src/sys/sem/linux/sem_test.cpp
new file mode 100644
index 0000000000000..fbf80a3a73e02
--- /dev/null
+++ b/libc/test/src/sys/sem/linux/sem_test.cpp
@@ -0,0 +1,69 @@
+//===-- Unittests for sys/sem.h entrypoints ------------------------------===//
+//
+// 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/sem/semctl.h"
+#include "src/sys/sem/semget.h"
+#include "src/sys/sem/semop.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+using LlvmLibcSysSemTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+union semun {
+  int val;
+  struct semid_ds *buf;
+  unsigned short *array;
+};
+
+TEST_F(LlvmLibcSysSemTest, SemgetSemctlSemopFlow) {
+  // create 1 semaphore
+  // fail if such key exists
+  // grant the read and write permission for its metadata
+  int semid =
+      LIBC_NAMESPACE::semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(semid, -1);
+
+  // create the semun
+  union semun set_val;
+
+  // set the val
+  set_val.val = 1;
+
+  // set the value to user value for the first semaphore
+  ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, SETVAL, set_val), Succeeds(0));
+
+  // get the value for the semaphore, expect 1
+  ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, GETVAL), Succeeds(1));
+
+  // try to decrement and non block
+  struct sembuf decrement_op = {0, -1, IPC_NOWAIT};
+
+  // decrement the semaphore
+  ASSERT_THAT(LIBC_NAMESPACE::semop(semid, &decrement_op, 1), Succeeds(0));
+
+  // access the value again now the value should be 0
+  ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, GETVAL), Succeeds(0));
+
+  // increment the semaphore and non block
+  struct sembuf increment_op = {0, 1, IPC_NOWAIT};
+
+  // increment the value in semaphore
+  ASSERT_THAT(LIBC_NAMESPACE::semop(semid, &increment_op, 1), Succeeds(0));
+
+  // get the value again and we expect the semaphore value to be 1
+  ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, GETVAL), Succeeds(1));
+
+  // destroy the semaphore as it is persistent unless delete
+  ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, IPC_RMID), Succeeds(0));
+}



More information about the libc-commits mailing list