[libc-commits] [libc] [libc][sys/sem] Add sys v sem headers and syscall wrapper implementation (PR #185914)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Thu Mar 12 07:47:28 PDT 2026
================
@@ -0,0 +1,72 @@
+//===-- 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 "hdr/sys_ipc_macros.h"
+#include "hdr/sys_sem_macros.h"
+#include "hdr/types/struct_sembuf.h"
+#include "hdr/types/struct_semid_ds.h"
+#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"
+
+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 a semaphore
+ int semid =
+ LIBC_NAMESPACE::semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_GT(semid, -1);
+
+ union semun set_val;
+ set_val.val = 1;
+
+ // set the semaphore value to 1
+ ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, SETVAL, set_val), Succeeds(0));
+
+ // get the value of semaphore should be 1
+ ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, GETVAL), Succeeds(1));
+
+ // decrement the semaphore value with IPC_NOWAIT flag
+ struct sembuf decrement_op = {0, -1, IPC_NOWAIT};
+ ASSERT_THAT(LIBC_NAMESPACE::semop(semid, &decrement_op, 1), Succeeds(0));
+
+ // get the value of semaphore should be 0
+ ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, GETVAL), Succeeds(0));
+
+ // increment the semaphore with IPC_NOWAIT flag
+ struct sembuf increment_op = {0, 1, IPC_NOWAIT};
+ ASSERT_THAT(LIBC_NAMESPACE::semop(semid, &increment_op, 1), Succeeds(0));
+
+ // get the semaphore value should be 1
+ ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, GETVAL), Succeeds(1));
+
+ // get the IPC stats
+ struct semid_ds sem_ds;
+ union semun stat_arg;
+ stat_arg.buf = &sem_ds;
+ ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, IPC_STAT, stat_arg),
+ Succeeds(0));
+
+ // the number of sem is 1
+ ASSERT_EQ(sem_ds.sem_nsems, 1UL);
+
+ // destroy the semaphore
+ ASSERT_THAT(LIBC_NAMESPACE::semctl(semid, 0, IPC_RMID), Succeeds(0));
+}
----------------
SchrodingerZhu wrote:
The following example is from POSIX.1 Issue 8, I wonder if we can include it in some ways:
```
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <sys/stat.h>
...
struct sembuf sbuf;
int semid;
key_t semkey;
...
// Get a key for the semaphore set.
if ((semkey = ftok("/tmp", 'a')) == (key_t) -1) {
perror("IPC error: ftok");
exit(1);
}
// Create the semaphore set associated with this key
if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1) {
// Initialize the semaphore.
sbuf.sem_num = 0;
sbuf.sem_op = 2; // Set the number of runs without queuing.
sbuf.sem_flg = 0;
if (semop(semid, &sbuf, 1) == -1) {
perror("IPC error: semop");
exit(1);
}
} else if (errno == EEXIST) {
// The semaphore set already exists; get its semaphore ID.
if ((semid = semget(semkey, 0, 0)) == -1) {
perror("IPC error 1: semget");
exit(1);
}
} else {
perror("IPC error 2: semget");
exit(1);
}
// Since the semget() initialized the semaphore to 0, the
// following semop() will block until the creating process
// completes the initialization above. Processes will also
// block in the following semop() call if two other processes
// have already passed this point and are still running.
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
if (semop(semid, &sbuf, 1) == -1) {
perror("IPC Error: semop");
exit(1);
}
```
https://github.com/llvm/llvm-project/pull/185914
More information about the libc-commits
mailing list