[libc][sys/sem] Add sys v sem headers and syscall wrapper implementation (#185914)
Fix #182161 Based on the last PR #182700 implementing sys/ipc.
This commit is contained in:
@@ -288,6 +288,11 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
libc.src.sys.resource.getrlimit
|
||||
libc.src.sys.resource.setrlimit
|
||||
|
||||
# sys/sem.h entrypoints
|
||||
libc.src.sys.sem.semget
|
||||
libc.src.sys.sem.semctl
|
||||
libc.src.sys.sem.semop
|
||||
|
||||
# sys/sendfile entrypoints
|
||||
libc.src.sys.sendfile.sendfile
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ set(TARGET_PUBLIC_HEADERS
|
||||
libc.include.sys_random
|
||||
libc.include.sys_resource
|
||||
libc.include.sys_select
|
||||
libc.include.sys_sem
|
||||
libc.include.sys_socket
|
||||
libc.include.sys_stat
|
||||
libc.include.sys_statvfs
|
||||
|
||||
@@ -149,6 +149,24 @@ add_proxy_header_library(
|
||||
libc.include.llvm-libc-macros.sys_ioctl_macros
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
sys_ipc_macros
|
||||
HDRS
|
||||
sys_ipc_macros.h
|
||||
FULL_BUILD_DEPENDS
|
||||
libc.include.sys_ipc
|
||||
libc.include.llvm-libc-macros.sys_ipc_macros
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
sys_sem_macros
|
||||
HDRS
|
||||
sys_sem_macros.h
|
||||
FULL_BUILD_DEPENDS
|
||||
libc.include.sys_sem
|
||||
libc.include.llvm-libc-macros.sys_sem_macros
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
sys_socket_macros
|
||||
HDRS
|
||||
|
||||
22
libc/hdr/sys_ipc_macros.h
Normal file
22
libc/hdr/sys_ipc_macros.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- 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_HDR_SYS_IPC_MACROS_H
|
||||
#define LLVM_LIBC_HDR_SYS_IPC_MACROS_H
|
||||
|
||||
#ifdef LIBC_FULL_BUILD
|
||||
|
||||
#include "include/llvm-libc-macros/sys-ipc-macros.h"
|
||||
|
||||
#else // Overlay mode
|
||||
|
||||
#include <sys/ipc.h>
|
||||
|
||||
#endif // LLVM_LIBC_FULL_BUILD
|
||||
|
||||
#endif // LLVM_LIBC_HDR_SYS_IPC_MACROS_H
|
||||
22
libc/hdr/sys_sem_macros.h
Normal file
22
libc/hdr/sys_sem_macros.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- 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_HDR_SYS_SEM_MACROS_H
|
||||
#define LLVM_LIBC_HDR_SYS_SEM_MACROS_H
|
||||
|
||||
#ifdef LIBC_FULL_BUILD
|
||||
|
||||
#include "include/llvm-libc-macros/sys-sem-macros.h"
|
||||
|
||||
#else // Overlay mode
|
||||
|
||||
#include <sys/sem.h>
|
||||
|
||||
#endif // LLVM_LIBC_FULL_BUILD
|
||||
|
||||
#endif // LLVM_LIBC_HDR_SYS_SEM_MACROS_H
|
||||
@@ -514,6 +514,33 @@ add_proxy_header_library(
|
||||
libc.include.sys_resource
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
struct_semid_ds
|
||||
HDRS
|
||||
struct_semid_ds.h
|
||||
FULL_BUILD_DEPENDS
|
||||
libc.include.llvm-libc-types.struct_semid_ds
|
||||
libc.include.sys_sem
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
struct_sembuf
|
||||
HDRS
|
||||
struct_sembuf.h
|
||||
FULL_BUILD_DEPENDS
|
||||
libc.include.llvm-libc-types.struct_sembuf
|
||||
libc.include.sys_sem
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
struct_seminfo
|
||||
HDRS
|
||||
struct_seminfo.h
|
||||
FULL_BUILD_DEPENDS
|
||||
libc.include.llvm-libc-types.struct_seminfo
|
||||
libc.include.sys_sem
|
||||
)
|
||||
|
||||
add_proxy_header_library(
|
||||
gid_t
|
||||
HDRS
|
||||
|
||||
22
libc/hdr/types/struct_sembuf.h
Normal file
22
libc/hdr/types/struct_sembuf.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- Proxy for 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_HDR_TYPES_STRUCT_SEMBUF_H
|
||||
#define LLVM_LIBC_HDR_TYPES_STRUCT_SEMBUF_H
|
||||
|
||||
#ifdef LIBC_FULL_BUILD
|
||||
|
||||
#include "include/llvm-libc-types/struct_sembuf.h"
|
||||
|
||||
#else // Overlay mode
|
||||
|
||||
#include <sys/sem.h>
|
||||
|
||||
#endif // LLVM_LIBC_FULL_BUILD
|
||||
|
||||
#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SEMBUF_H
|
||||
22
libc/hdr/types/struct_semid_ds.h
Normal file
22
libc/hdr/types/struct_semid_ds.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- Proxy for 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_HDR_TYPES_STRUCT_SEMID_DS_H
|
||||
#define LLVM_LIBC_HDR_TYPES_STRUCT_SEMID_DS_H
|
||||
|
||||
#ifdef LIBC_FULL_BUILD
|
||||
|
||||
#include "include/llvm-libc-types/struct_semid_ds.h"
|
||||
|
||||
#else // Overlay mode
|
||||
|
||||
#include <sys/sem.h>
|
||||
|
||||
#endif // LLVM_LIBC_FULL_BUILD
|
||||
|
||||
#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SEMID_DS_H
|
||||
22
libc/hdr/types/struct_seminfo.h
Normal file
22
libc/hdr/types/struct_seminfo.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- Proxy for struct seminfo ------------------------------------------===//
|
||||
//
|
||||
// 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_HDR_TYPES_STRUCT_SEMINFO_H
|
||||
#define LLVM_LIBC_HDR_TYPES_STRUCT_SEMINFO_H
|
||||
|
||||
#ifdef LIBC_FULL_BUILD
|
||||
|
||||
#include "include/llvm-libc-types/struct_seminfo.h"
|
||||
|
||||
#else // Overlay mode
|
||||
|
||||
#include <sys/sem.h>
|
||||
|
||||
#endif // LLVM_LIBC_FULL_BUILD
|
||||
|
||||
#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SEMINFO_H
|
||||
@@ -660,6 +660,21 @@ 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
|
||||
.llvm-libc-types.struct_seminfo
|
||||
)
|
||||
|
||||
add_header_macro(
|
||||
sys_sendfile
|
||||
../libc/include/sys/sendfile.yaml
|
||||
|
||||
@@ -232,6 +232,12 @@ add_macro_header(
|
||||
sys-ipc-macros.h
|
||||
)
|
||||
|
||||
add_macro_header(
|
||||
sys_sem_macros
|
||||
HDR
|
||||
sys-sem-macros.h
|
||||
)
|
||||
|
||||
add_macro_header(
|
||||
sys_stat_macros
|
||||
HDR
|
||||
|
||||
@@ -46,6 +46,12 @@ add_header(
|
||||
sys-random-macros.h
|
||||
)
|
||||
|
||||
add_header(
|
||||
sys_sem_macros
|
||||
HDR
|
||||
sys-sem-macros.h
|
||||
)
|
||||
|
||||
add_header(
|
||||
sys_socket_macros
|
||||
HDR
|
||||
|
||||
@@ -20,5 +20,6 @@
|
||||
#define IPC_RMID 0
|
||||
#define IPC_SET 1
|
||||
#define IPC_STAT 2
|
||||
#define IPC_INFO 3
|
||||
|
||||
#endif // LLVM_LIBC_MACROS_LINUX_SYS_IPC_MACROS_H
|
||||
|
||||
29
libc/include/llvm-libc-macros/linux/sys-sem-macros.h
Normal file
29
libc/include/llvm-libc-macros/linux/sys-sem-macros.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//===-- 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
|
||||
|
||||
// linux specific extensions
|
||||
#define SEM_STAT 18
|
||||
#define SEM_INFO 19
|
||||
#define SEM_STAT_ANY 20
|
||||
|
||||
#endif // LLVM_LIBC_MACROS_LINUX_SYS_SEM_MACROS_H
|
||||
16
libc/include/llvm-libc-macros/sys-sem-macros.h
Normal file
16
libc/include/llvm-libc-macros/sys-sem-macros.h
Normal file
@@ -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
|
||||
@@ -101,6 +101,15 @@ add_header(
|
||||
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_seminfo HDR struct_seminfo.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)
|
||||
|
||||
19
libc/include/llvm-libc-types/struct_sembuf.h
Normal file
19
libc/include/llvm-libc-types/struct_sembuf.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//===-- 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 {
|
||||
// changed to unsigned short from short since POSIX issue 7
|
||||
unsigned short sem_num;
|
||||
short sem_op;
|
||||
short sem_flg;
|
||||
};
|
||||
|
||||
#endif // LLVM_LIBC_TYPES_STRUCT_SEMBUF_H
|
||||
33
libc/include/llvm-libc-types/struct_semid_ds.h
Normal file
33
libc/include/llvm-libc-types/struct_semid_ds.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//===-- 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;
|
||||
#ifdef __linux__
|
||||
time_t sem_otime;
|
||||
unsigned long __unused1;
|
||||
time_t sem_ctime;
|
||||
unsigned long __unused2;
|
||||
#else
|
||||
time_t sem_otime;
|
||||
time_t sem_ctime;
|
||||
#endif
|
||||
unsigned long sem_nsems;
|
||||
#ifdef __linux__
|
||||
unsigned long __unused3;
|
||||
unsigned long __unused4;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // LLVM_LIBC_TYPES_STRUCT_SEMID_DS_H
|
||||
27
libc/include/llvm-libc-types/struct_seminfo.h
Normal file
27
libc/include/llvm-libc-types/struct_seminfo.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- Definition of struct seminfo --------------------------------------===//
|
||||
//
|
||||
// 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_SEMINFO_H
|
||||
#define LLVM_LIBC_TYPES_STRUCT_SEMINFO_H
|
||||
|
||||
#ifdef __linux__
|
||||
struct seminfo {
|
||||
int semmap;
|
||||
int semmni;
|
||||
int semmns;
|
||||
int semmnu;
|
||||
int semmsl;
|
||||
int semopm;
|
||||
int semume;
|
||||
int semusz;
|
||||
int semvmx;
|
||||
int semaem;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // LLVM_LIBC_TYPES_STRUCT_SEMINFO_H
|
||||
84
libc/include/sys/sem.yaml
Normal file
84
libc/include/sys/sem.yaml
Normal file
@@ -0,0 +1,84 @@
|
||||
header: sys/sem.h
|
||||
standards:
|
||||
- posix
|
||||
- linux
|
||||
macros:
|
||||
- macro_name: SEM_UNDO
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: GETNCNT
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: GETPID
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: GETVAL
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: GETALL
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: GETZCNT
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: SETVAL
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: SETALL
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- posix
|
||||
- macro_name: SEM_STAT
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- linux
|
||||
- macro_name: SEM_INFO
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- linux
|
||||
- macro_name: SEM_STAT_ANY
|
||||
macro_header: sys-sem-macros.h
|
||||
standards:
|
||||
- linux
|
||||
types:
|
||||
- type_name: key_t
|
||||
- type_name: size_t
|
||||
- type_name: struct_ipc_perm
|
||||
- type_name: struct_semid_ds
|
||||
- type_name: struct_sembuf
|
||||
- type_name: struct_seminfo
|
||||
standards:
|
||||
- linux
|
||||
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
|
||||
@@ -6,6 +6,7 @@ add_subdirectory(random)
|
||||
add_subdirectory(resource)
|
||||
add_subdirectory(select)
|
||||
add_subdirectory(socket)
|
||||
add_subdirectory(sem)
|
||||
add_subdirectory(sendfile)
|
||||
add_subdirectory(stat)
|
||||
add_subdirectory(statvfs)
|
||||
|
||||
24
libc/src/sys/sem/CMakeLists.txt
Normal file
24
libc/src/sys/sem/CMakeLists.txt
Normal file
@@ -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
|
||||
)
|
||||
46
libc/src/sys/sem/linux/CMakeLists.txt
Normal file
46
libc/src/sys/sem/linux/CMakeLists.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
add_entrypoint_object(
|
||||
semget
|
||||
SRCS
|
||||
semget.cpp
|
||||
HDRS
|
||||
../semget.h
|
||||
DEPENDS
|
||||
libc.hdr.types.key_t
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.__support.common
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
semctl
|
||||
SRCS
|
||||
semctl.cpp
|
||||
HDRS
|
||||
../semctl.h
|
||||
DEPENDS
|
||||
libc.hdr.errno_macros
|
||||
libc.hdr.sys_ipc_macros
|
||||
libc.hdr.sys_sem_macros
|
||||
libc.hdr.types.struct_semid_ds
|
||||
libc.hdr.types.struct_seminfo
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.__support.common
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
semop
|
||||
SRCS
|
||||
semop.cpp
|
||||
HDRS
|
||||
../semop.h
|
||||
DEPENDS
|
||||
libc.hdr.types.size_t
|
||||
libc.hdr.types.struct_sembuf
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.__support.common
|
||||
libc.src.errno.errno
|
||||
)
|
||||
101
libc/src/sys/sem/linux/semctl.cpp
Normal file
101
libc/src/sys/sem/linux/semctl.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//===-- 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"
|
||||
#include "hdr/sys_ipc_macros.h"
|
||||
#include "hdr/sys_sem_macros.h"
|
||||
#include "hdr/types/struct_semid_ds.h"
|
||||
#include "hdr/types/struct_seminfo.h"
|
||||
#include "src/__support/OSUtil/syscall.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/libc_errno.h"
|
||||
#include <stdarg.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, semctl, (int semid, int semnum, int cmd, ...)) {
|
||||
// used to parse the fourth varargs argument
|
||||
// its expected to be explicitly declared by application as an union type:
|
||||
// union semun {
|
||||
// int val;
|
||||
// struct semid_ds *buf;
|
||||
// unsigned short *array;
|
||||
// struct seminfo *__buf; (* linux specific *)
|
||||
// } arg;
|
||||
unsigned long cmd_arg = 0;
|
||||
|
||||
// parse cmd_arg based on the flags
|
||||
switch (cmd) {
|
||||
// does not use the vargs
|
||||
case IPC_RMID:
|
||||
case GETVAL:
|
||||
case GETPID:
|
||||
case GETNCNT:
|
||||
case GETZCNT:
|
||||
break;
|
||||
|
||||
// use vargs as int, semun->val
|
||||
case SETVAL: {
|
||||
va_list vargs;
|
||||
va_start(vargs, cmd);
|
||||
cmd_arg = static_cast<unsigned long>(va_arg(vargs, int));
|
||||
va_end(vargs);
|
||||
break;
|
||||
}
|
||||
|
||||
// use vargs as semid_ds*, semun->buf
|
||||
case IPC_SET:
|
||||
case IPC_STAT:
|
||||
case SEM_STAT:
|
||||
case SEM_STAT_ANY: {
|
||||
va_list vargs;
|
||||
va_start(vargs, cmd);
|
||||
cmd_arg = reinterpret_cast<unsigned long>(va_arg(vargs, struct semid_ds *));
|
||||
va_end(vargs);
|
||||
break;
|
||||
}
|
||||
|
||||
// use vargs as short*, semun->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;
|
||||
}
|
||||
|
||||
// linux specific, use vargs as seminfo*, semun->__buf
|
||||
case IPC_INFO:
|
||||
case SEM_INFO: {
|
||||
va_list vargs;
|
||||
va_start(vargs, cmd);
|
||||
cmd_arg = reinterpret_cast<unsigned long>(va_arg(vargs, struct seminfo *));
|
||||
va_end(vargs);
|
||||
break;
|
||||
}
|
||||
|
||||
// unrecognized flags
|
||||
default:
|
||||
libc_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_semctl, semid, semnum, cmd,
|
||||
cmd_arg);
|
||||
if (ret < 0) {
|
||||
libc_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
27
libc/src/sys/sem/linux/semget.cpp
Normal file
27
libc/src/sys/sem/linux/semget.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- 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"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/libc_errno.h"
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, semget, (key_t key, int nsems, int semflg)) {
|
||||
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_semget, key, nsems, semflg);
|
||||
if (ret < 0) {
|
||||
libc_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
27
libc/src/sys/sem/linux/semop.cpp
Normal file
27
libc/src/sys/sem/linux/semop.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- 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"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/libc_errno.h"
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, semop, (int semid, struct sembuf *sops, size_t nsops)) {
|
||||
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_semop, semid, sops, nsops);
|
||||
if (ret < 0) {
|
||||
libc_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
20
libc/src/sys/sem/semctl.h
Normal file
20
libc/src/sys/sem/semctl.h
Normal file
@@ -0,0 +1,20 @@
|
||||
//===-- 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
|
||||
21
libc/src/sys/sem/semget.h
Normal file
21
libc/src/sys/sem/semget.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//===-- 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 "hdr/types/key_t.h"
|
||||
#include "src/__support/macros/config.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
|
||||
22
libc/src/sys/sem/semop.h
Normal file
22
libc/src/sys/sem/semop.h
Normal file
@@ -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 "hdr/types/size_t.h"
|
||||
#include "hdr/types/struct_sembuf.h"
|
||||
#include "src/__support/macros/config.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
|
||||
@@ -4,4 +4,5 @@ add_subdirectory(spawn)
|
||||
add_subdirectory(stdio)
|
||||
add_subdirectory(stdlib)
|
||||
add_subdirectory(threads)
|
||||
add_subdirectory(sys)
|
||||
add_subdirectory(unistd)
|
||||
|
||||
1
libc/test/integration/src/sys/CMakeLists.txt
Normal file
1
libc/test/integration/src/sys/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_subdirectory(sem)
|
||||
29
libc/test/integration/src/sys/sem/CMakeLists.txt
Normal file
29
libc/test/integration/src/sys/sem/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
add_custom_target(sys-sem-integration-tests)
|
||||
add_dependencies(libc-integration-tests sys-sem-integration-tests)
|
||||
|
||||
add_integration_test(
|
||||
sem_test
|
||||
SUITE
|
||||
sys-sem-integration-tests
|
||||
SRCS
|
||||
sem_test.cpp
|
||||
DEPENDS
|
||||
libc.hdr.fcntl_macros
|
||||
libc.hdr.sys_ipc_macros
|
||||
libc.hdr.sys_sem_macros
|
||||
libc.hdr.types.struct_sembuf
|
||||
libc.src.__support.threads.sleep
|
||||
libc.src.fcntl.open
|
||||
libc.src.signal.kill
|
||||
libc.src.stdlib.exit
|
||||
libc.src.sys.ipc.ftok
|
||||
libc.src.sys.sem.semctl
|
||||
libc.src.sys.sem.semget
|
||||
libc.src.sys.sem.semop
|
||||
libc.src.sys.wait.waitpid
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.fork
|
||||
libc.src.unistd.unlink
|
||||
libc.include.signal
|
||||
libc.include.sys_wait
|
||||
)
|
||||
171
libc/test/integration/src/sys/sem/sem_test.cpp
Normal file
171
libc/test/integration/src/sys/sem/sem_test.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
//===-- Integration test for sys/sem --------------------------------------===//
|
||||
//
|
||||
// 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/threads/sleep.h"
|
||||
#include "src/fcntl/open.h"
|
||||
#include "src/signal/kill.h"
|
||||
#include "src/stdlib/exit.h"
|
||||
#include "src/sys/ipc/ftok.h"
|
||||
#include "src/sys/sem/semctl.h"
|
||||
#include "src/sys/sem/semget.h"
|
||||
#include "src/sys/sem/semop.h"
|
||||
#include "src/sys/wait/waitpid.h"
|
||||
#include "src/unistd/close.h"
|
||||
#include "src/unistd/fork.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
|
||||
#include "test/IntegrationTest/test.h"
|
||||
|
||||
#include "hdr/fcntl_macros.h"
|
||||
#include "hdr/sys_ipc_macros.h"
|
||||
#include "hdr/sys_sem_macros.h"
|
||||
#include "hdr/types/struct_sembuf.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
// child try IPC_CREAT|IPC_EXCL,
|
||||
// but expect EEXIST then fall back to get the existing semaphore.
|
||||
static int sem_joiner_get(key_t semkey) {
|
||||
// this expect to fail and return -1 because we used the same key
|
||||
// and this semaphore has been initialized.
|
||||
int sid = LIBC_NAMESPACE::semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0666);
|
||||
if (sid == -1 && errno == EEXIST)
|
||||
// get the initialized semaphore id
|
||||
sid = LIBC_NAMESPACE::semget(semkey, 0, 0);
|
||||
return sid;
|
||||
}
|
||||
|
||||
// fork a child that acquires the semaphore and hold untill killed.
|
||||
// returns child pid.
|
||||
static pid_t fork_sem_holder(key_t semkey) {
|
||||
pid_t pid = LIBC_NAMESPACE::fork();
|
||||
if (pid == 0) {
|
||||
int sid = sem_joiner_get(semkey);
|
||||
if (sid < 0)
|
||||
LIBC_NAMESPACE::exit(1);
|
||||
// try acquire and hold
|
||||
// set flag to UNDO if process terminate unexpectedly
|
||||
struct sembuf acq = {0, -1, SEM_UNDO};
|
||||
if (LIBC_NAMESPACE::semop(sid, &acq, 1) != 0)
|
||||
LIBC_NAMESPACE::exit(2);
|
||||
|
||||
// hold the semaphore until killed by parent.
|
||||
while (1)
|
||||
LIBC_NAMESPACE::sleep_briefly();
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
// fork a child that tries to acquire (IPC_NOWAIT).
|
||||
// exit code: 0 = acquired, 1 = EAGAIN (full, try later again), 2+ = error.
|
||||
static pid_t fork_sem_try_acquire(key_t semkey) {
|
||||
pid_t pid = LIBC_NAMESPACE::fork();
|
||||
if (pid == 0) {
|
||||
int sid = sem_joiner_get(semkey);
|
||||
if (sid < 0)
|
||||
LIBC_NAMESPACE::exit(3);
|
||||
// try acquire
|
||||
struct sembuf acq = {0, -1, SEM_UNDO | IPC_NOWAIT};
|
||||
|
||||
if (LIBC_NAMESPACE::semop(sid, &acq, 1) == 0)
|
||||
LIBC_NAMESPACE::exit(0); // acquired
|
||||
|
||||
// exit with code 1 if EAGAIN
|
||||
LIBC_NAMESPACE::exit(errno == EAGAIN ? 1 : 2);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
// wait for child to terminate.
|
||||
static int wait_for_child(pid_t pid) {
|
||||
int status;
|
||||
LIBC_NAMESPACE::waitpid(pid, &status, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
// semaphore gate that allows at most two processes to enter
|
||||
void sem_gate_test() {
|
||||
constexpr const char *TEST_FILE = "/tmp/sem_gate_test";
|
||||
int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY, 0666);
|
||||
ASSERT_TRUE(fd >= 0);
|
||||
ASSERT_ERRNO_SUCCESS();
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::close(fd) == 0);
|
||||
|
||||
key_t semkey = LIBC_NAMESPACE::ftok(TEST_FILE, 'a');
|
||||
ASSERT_TRUE(semkey != key_t(-1));
|
||||
ASSERT_ERRNO_SUCCESS();
|
||||
|
||||
// clean up stale semaphore from previous run because semaphore
|
||||
// are kernel persistent, they can remain on the system if previous
|
||||
// test fail and exit.
|
||||
int old_semid = LIBC_NAMESPACE::semget(semkey, 1, 0);
|
||||
if (old_semid != -1)
|
||||
LIBC_NAMESPACE::semctl(old_semid, 0, IPC_RMID);
|
||||
errno = 0;
|
||||
|
||||
// create a semaphore
|
||||
int semid = LIBC_NAMESPACE::semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0666);
|
||||
ASSERT_TRUE(semid >= 0);
|
||||
ASSERT_ERRNO_SUCCESS();
|
||||
|
||||
// increment the first semaphore by 2 that allows two processes to access
|
||||
struct sembuf sbuf = {0, 2, 0};
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::semop(semid, &sbuf, 1) == 0);
|
||||
|
||||
// verify the first semaphore value
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::semctl(semid, 0, GETVAL) == 2);
|
||||
|
||||
// fork two children to hold the semaphore
|
||||
pid_t holder1 = fork_sem_holder(semkey);
|
||||
ASSERT_TRUE(holder1 > 0);
|
||||
pid_t holder2 = fork_sem_holder(semkey);
|
||||
ASSERT_TRUE(holder2 > 0);
|
||||
|
||||
// wait until both children have acquired so semaphore value reaches 0.
|
||||
while (LIBC_NAMESPACE::semctl(semid, 0, GETVAL) > 0)
|
||||
LIBC_NAMESPACE::sleep_briefly();
|
||||
|
||||
// check my current semaphore value is 0
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::semctl(semid, 0, GETVAL) == 0);
|
||||
|
||||
// now the semaphore gate is full
|
||||
// fork another process to try to acquire it
|
||||
pid_t blocked = fork_sem_try_acquire(semkey);
|
||||
ASSERT_TRUE(blocked > 0);
|
||||
int blocked_status = wait_for_child(blocked);
|
||||
// check the exit status
|
||||
ASSERT_TRUE(WIFEXITED(blocked_status));
|
||||
ASSERT_EQ(WEXITSTATUS(blocked_status), 1); // EAGAIN (blocked)
|
||||
|
||||
// kill the first holder to make one slot avalaible in semaphore
|
||||
LIBC_NAMESPACE::kill(holder1, SIGKILL);
|
||||
wait_for_child(holder1);
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::semctl(semid, 0, GETVAL) == 1);
|
||||
|
||||
// then fork child again to try acquire
|
||||
pid_t unblocked = fork_sem_try_acquire(semkey);
|
||||
ASSERT_TRUE(unblocked > 0);
|
||||
int unblocked_status = wait_for_child(unblocked);
|
||||
// this child should get it since the slot is avalaible now
|
||||
ASSERT_TRUE(WIFEXITED(unblocked_status));
|
||||
ASSERT_EQ(WEXITSTATUS(unblocked_status), 0); // acquired
|
||||
|
||||
// cleanup
|
||||
LIBC_NAMESPACE::kill(holder2, SIGKILL);
|
||||
wait_for_child(holder2);
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::semctl(semid, 0, IPC_RMID) == 0);
|
||||
ASSERT_TRUE(LIBC_NAMESPACE::unlink(TEST_FILE) == 0);
|
||||
}
|
||||
|
||||
TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
|
||||
[[maybe_unused]] char **envp) {
|
||||
sem_gate_test();
|
||||
return 0;
|
||||
}
|
||||
@@ -15,3 +15,4 @@ add_subdirectory(ipc)
|
||||
add_subdirectory(uio)
|
||||
add_subdirectory(time)
|
||||
add_subdirectory(ioctl)
|
||||
add_subdirectory(sem)
|
||||
|
||||
3
libc/test/src/sys/sem/CMakeLists.txt
Normal file
3
libc/test/src/sys/sem/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
|
||||
add_subdirectory(${LIBC_TARGET_OS})
|
||||
endif()
|
||||
20
libc/test/src/sys/sem/linux/CMakeLists.txt
Normal file
20
libc/test/src/sys/sem/linux/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
add_custom_target(libc_sys_sem_unittests)
|
||||
|
||||
add_libc_unittest(
|
||||
sem_test
|
||||
SUITE
|
||||
libc_sys_sem_unittests
|
||||
SRCS
|
||||
sem_test.cpp
|
||||
DEPENDS
|
||||
libc.hdr.sys_ipc_macros
|
||||
libc.hdr.sys_sem_macros
|
||||
libc.hdr.types.struct_sembuf
|
||||
libc.hdr.types.struct_semid_ds
|
||||
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
|
||||
)
|
||||
72
libc/test/src/sys/sem/linux/sem_test.cpp
Normal file
72
libc/test/src/sys/sem/linux/sem_test.cpp
Normal file
@@ -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));
|
||||
}
|
||||
Reference in New Issue
Block a user