Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,11 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_spin_lock
libc.src.pthread.pthread_spin_trylock
libc.src.pthread.pthread_spin_unlock

# semaphore.h entrypoints
libc.src.semaphore.sem_destroy
libc.src.semaphore.sem_getvalue
libc.src.semaphore.sem_init
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setname_np
libc.src.pthread.pthread_setspecific
Expand Down
8 changes: 8 additions & 0 deletions libc/hdr/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,14 @@ add_proxy_header_library(
libc.include.llvm-libc-types.pid_t
)

add_proxy_header_library(
sem_t
HDRS
sem_t.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.sem_t
)

add_proxy_header_library(
pthread_barrier_t
HDRS
Expand Down
22 changes: 22 additions & 0 deletions libc/hdr/types/sem_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Definition of sem_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_HDR_TYPES_SEM_T_H
#define LLVM_LIBC_HDR_TYPES_SEM_T_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-types/sem_t.h"

#else // Overlay mode

#error "Cannot overlay sem_t"

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_TYPES_SEM_T_H
9 changes: 9 additions & 0 deletions libc/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,15 @@ add_header_macro(
.llvm-libc-types.struct_timespec
)

add_header_macro(
semaphore
../libc/include/semaphore.yaml
semaphore.h
DEPENDS
.llvm-libc-types.sem_t
.llvm_libc_common_h
)

add_header_macro(
spawn
../libc/include/spawn.yaml
Expand Down
2 changes: 2 additions & 0 deletions libc/include/limits.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ macros:
macro_header: limits-macros.h
- macro_name: ULLONG_MAX
macro_header: limits-macros.h
- macro_name: SEM_VALUE_MAX
macro_header: limits-macros.h
- macro_name: SCHAR_MIN
macro_header: limits-macros.h
- macro_name: UCHAR_MIN
Expand Down
4 changes: 4 additions & 0 deletions libc/include/llvm-libc-macros/limits-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif // ULLONG_MAX

#ifndef SEM_VALUE_MAX
#define SEM_VALUE_MAX INT_MAX
#endif // SEM_VALUE_MAX

// *_MIN macros

#ifndef SCHAR_MIN
Expand Down
1 change: 1 addition & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ add_header(pthread_rwlockattr_t HDR pthread_rwlockattr_t.h)
add_header(pthread_spinlock_t HDR pthread_spinlock_t.h DEPENDS .pid_t)
add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
add_header(rlim_t HDR rlim_t.h)
add_header(sem_t HDR sem_t.h DEPENDS .__futex_word)
if(LIBC_TYPES_TIME_T_IS_32_BIT)
add_header(time_t HDR time_t_32.h DEST_HDR time_t.h)
else()
Expand Down
20 changes: 20 additions & 0 deletions libc/include/llvm-libc-types/sem_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Definition of sem_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_SEM_T_H
#define LLVM_LIBC_TYPES_SEM_T_H

#include "__futex_word.h"

typedef struct {
__futex_word __value; // current semaphore count
unsigned int __canary; // used for sanity check
unsigned char __reserved[8]; // for future usage, total fixed size 16 bytes
} sem_t;

#endif // LLVM_LIBC_TYPES_SEM_T_H
21 changes: 21 additions & 0 deletions libc/include/semaphore.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
header: semaphore.h
standards:
- posix
types:
- type_name: sem_t
functions:
- name: sem_destroy
return_type: int
arguments:
- type: sem_t *
- name: sem_getvalue
return_type: int
arguments:
- type: sem_t *__restrict
- type: int *__restrict
- name: sem_init
return_type: int
arguments:
- type: sem_t *
- type: int
- type: unsigned int
1 change: 1 addition & 0 deletions libc/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(poll)
add_subdirectory(pthread)
add_subdirectory(sched)
add_subdirectory(semaphore)
add_subdirectory(sys)
add_subdirectory(termios)
endif()
Expand Down
49 changes: 49 additions & 0 deletions libc/src/semaphore/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
add_header_library(
posix_semaphore
HDRS
posix_semaphore.h
DEPENDS
libc.hdr.types.sem_t
libc.src.__support.CPP.atomic
libc.src.__support.threads.linux.futex_word_type
)

add_entrypoint_object(
sem_init
SRCS
sem_init.cpp
HDRS
sem_init.h
DEPENDS
.posix_semaphore
libc.hdr.errno_macros
libc.hdr.limits_macros
libc.include.semaphore
libc.src.errno.errno
)

add_entrypoint_object(
sem_destroy
SRCS
sem_destroy.cpp
HDRS
sem_destroy.h
DEPENDS
.posix_semaphore
libc.hdr.errno_macros
libc.include.semaphore
libc.src.errno.errno
)

add_entrypoint_object(
sem_getvalue
SRCS
sem_getvalue.cpp
HDRS
sem_getvalue.h
DEPENDS
.posix_semaphore
libc.hdr.errno_macros
libc.include.semaphore
libc.src.errno.errno
)
72 changes: 72 additions & 0 deletions libc/src/semaphore/posix_semaphore.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//===-- Shared helpers for POSIX semaphores -------------------------------===//
//
// 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_SEMAPHORE_POSIX_SEMAPHORE_H
#define LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H

#include "hdr/types/sem_t.h"
#include "src/__support/CPP/atomic.h"
#include "src/__support/common.h"
#include "src/__support/threads/linux/futex_word.h"

namespace LIBC_NAMESPACE_DECL {
namespace sem_utils {

// 0x53 = S, 0x45 = E, 0x4D = M, 0x31 = 1
// canary value: SEM1 in hex
LIBC_INLINE_VAR constexpr unsigned int SEM_CANARY = 0x53454D31U;

static_assert(sizeof(__futex_word) == sizeof(FutexWordType));
static_assert(alignof(__futex_word) >= alignof(FutexWordType));

// TODO:
// 1. Add named semaphore support: sem_open, sem_close, sem_unlink
// 2. Add the posting and waiting operations: sem_post, sem_wait,
// sem_trywait, sem_timedwait, sem_clockwait.

LIBC_INLINE FutexWordType *value_ptr(sem_t *sem) {
return &sem->__value.__word;
}

// get the atomic reference for sem->__value
LIBC_INLINE cpp::AtomicRef<FutexWordType> value(sem_t *sem) {
return cpp::AtomicRef<FutexWordType>(*value_ptr(sem));
}

LIBC_INLINE void initialize(sem_t *sem, unsigned int initial_value) {
// used in sem_init
// init happens before the semaphore is published to any threads
// initialize a initialized semaphore is undefined
// so RELAXED ordering is enough
value(sem).store(initial_value, cpp::MemoryOrder::RELAXED);
sem->__canary = SEM_CANARY;
for (unsigned char &byte : sem->__reserved)
byte = 0;
}

LIBC_INLINE bool is_valid(const sem_t *sem) {
// sanity check for a given semaphore pointer
return sem != nullptr && sem->__canary == SEM_CANARY;
}

LIBC_INLINE void invalidate(sem_t *sem) {
// used in sem_destroy
// invalidate is safe only when no threads is using
// blocked by destroyed semaphore is undefined
// use a destroyed semaphore is undefined
// RELAXED ordering is enough
value(sem).store(0, cpp::MemoryOrder::RELAXED);
sem->__canary = 0;
for (unsigned char &byte : sem->__reserved)
byte = 0;
}

} // namespace sem_utils
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
29 changes: 29 additions & 0 deletions libc/src/semaphore/sem_destroy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===-- Implementation of sem_destroy ------------------------------------===//
//
// 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/semaphore/sem_destroy.h"

#include "src/semaphore/posix_semaphore.h"

#include "hdr/errno_macros.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, sem_destroy, (sem_t * sem)) {
if (!sem_utils::is_valid(sem)) {
libc_errno = EINVAL;
return -1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a TODO to check for processes blocked on the semaphore

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think posix specify this case is undefined:

The effect of destroying a semaphore upon which other threads are currently blocked is undefined.

sem_utils::invalidate(sem);
return 0;
}

} // namespace LIBC_NAMESPACE_DECL
21 changes: 21 additions & 0 deletions libc/src/semaphore/sem_destroy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for sem_destroy ------------------*- 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_SEMAPHORE_SEM_DESTROY_H
#define LLVM_LIBC_SRC_SEMAPHORE_SEM_DESTROY_H

#include "hdr/types/sem_t.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

int sem_destroy(sem_t *sem);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_DESTROY_H
33 changes: 33 additions & 0 deletions libc/src/semaphore/sem_getvalue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Implementation of sem_getvalue -----------------------------------===//
//
// 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/semaphore/sem_getvalue.h"

#include "src/semaphore/posix_semaphore.h"

#include "hdr/errno_macros.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, sem_getvalue,
(sem_t *__restrict sem, int *__restrict sval)) {
if (!sem_utils::is_valid(sem) || sval == nullptr) {
libc_errno = EINVAL;
return -1;
}

// get value is informational but not a synchronization op
// RELAXED ordering is enough
*sval =
static_cast<int>(sem_utils::value(sem).load(cpp::MemoryOrder::RELAXED));
return 0;
}

} // namespace LIBC_NAMESPACE_DECL
21 changes: 21 additions & 0 deletions libc/src/semaphore/sem_getvalue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for sem_getvalue -----------------*- 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_SEMAPHORE_SEM_GETVALUE_H
#define LLVM_LIBC_SRC_SEMAPHORE_SEM_GETVALUE_H

#include "hdr/types/sem_t.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

int sem_getvalue(sem_t *__restrict sem, int *__restrict sval);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_GETVALUE_H
Loading
Loading