[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