Skip to content

Commit

Permalink
Merge pull request #1147 from 64/sigset
Browse files Browse the repository at this point in the history
options/internal: detect underlying type of sigset_t
  • Loading branch information
mintsuki authored Oct 13, 2024
2 parents 6479f8e + dddb771 commit a89e933
Showing 1 changed file with 48 additions and 9 deletions.
57 changes: 48 additions & 9 deletions options/internal/generic/sigset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,45 @@
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stddef.h>

namespace {

template<class T> struct remove_reference { typedef T type; };
template<class T> struct remove_reference<T&> { typedef T type; };

// Assume that the struct has a member named 'sig'.
template<typename T>
struct sigset_type_helper {
using type = typename remove_reference<decltype(T::sig[0])>::type;
static_assert(offsetof(T, sig) == 0);
};

template<>
struct sigset_type_helper<unsigned long> { using type = unsigned long; };

template<>
struct sigset_type_helper<unsigned long long> { using type = unsigned long long; };

template<>
struct sigset_type_helper<long> { using type = long; };

template<>
struct sigset_type_helper<long long> { using type = long long; };

// Some ABIs define sigset_t as a simple integer (e.g unsigned long),
// while others define it as a struct containing an array of integers.
using sigset_underlying_type = sigset_type_helper<sigset_t>::type;

size_t signo_to_field(int signo) {
return signo / (sizeof(sigset_underlying_type) * CHAR_BIT);
}

size_t signo_to_bit(int signo) {
return signo % (sizeof(sigset_underlying_type) * CHAR_BIT);
}

} // namespace

int sigemptyset(sigset_t *sigset) {
memset(sigset, 0, sizeof(*sigset));
Expand All @@ -20,9 +59,9 @@ int sigaddset(sigset_t *sigset, int sig) {
errno = EINVAL;
return -1;
}
auto ptr = reinterpret_cast<unsigned long *>(sigset);
int field = signo / (sizeof(unsigned long) * CHAR_BIT);
int bit = signo % (sizeof(unsigned long) * CHAR_BIT);
auto ptr = reinterpret_cast<sigset_underlying_type *>(sigset);
auto field = signo_to_field(signo);
auto bit = signo_to_bit(signo);
ptr[field] |= (1UL << bit);
return 0;
}
Expand All @@ -33,9 +72,9 @@ int sigdelset(sigset_t *sigset, int sig) {
errno = EINVAL;
return -1;
}
auto ptr = reinterpret_cast<unsigned long *>(sigset);
int field = signo / (sizeof(unsigned long) * CHAR_BIT);
int bit = signo % (sizeof(unsigned long) * CHAR_BIT);
auto ptr = reinterpret_cast<sigset_underlying_type *>(sigset);
auto field = signo_to_field(signo);
auto bit = signo_to_bit(signo);
ptr[field] &= ~(1UL << bit);
return 0;
}
Expand All @@ -46,8 +85,8 @@ int sigismember(const sigset_t *sigset, int sig) {
errno = EINVAL;
return -1;
}
auto ptr = reinterpret_cast<const unsigned long *>(sigset);
int field = signo / (sizeof(unsigned long) * CHAR_BIT);
int bit = signo % (sizeof(unsigned long) * CHAR_BIT);
auto ptr = reinterpret_cast<const sigset_underlying_type *>(sigset);
auto field = signo_to_field(signo);
auto bit = signo_to_bit(signo);
return (ptr[field] & (1UL << bit)) != 0;
}

0 comments on commit a89e933

Please sign in to comment.