Skip to content

Commit 2e35ab7

Browse files
committed
Added QNX support
1 parent 51828c2 commit 2e35ab7

File tree

14 files changed

+684
-249
lines changed

14 files changed

+684
-249
lines changed

src/CMakeLists.txt

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
project(ipc)
22

3-
if(UNIX)
4-
file(GLOB SRC_FILES ${LIBIPC_PROJECT_DIR}/src/libipc/platform/linux/*.cpp
5-
${LIBIPC_PROJECT_DIR}/src/libipc/platform/linux/a0/*.c)
6-
else()
7-
file(GLOB SRC_FILES ${LIBIPC_PROJECT_DIR}/src/libipc/platform/win/*.cpp)
8-
endif()
93
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
104
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/sync SRC_FILES)
5+
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/platform SRC_FILES)
116

127
file(GLOB HEAD_FILES
138
${LIBIPC_PROJECT_DIR}/include/libipc/*.h
@@ -39,7 +34,7 @@ set_target_properties(${PROJECT_NAME}
3934
# set version
4035
set_target_properties(${PROJECT_NAME}
4136
PROPERTIES
42-
VERSION 1.2.0
37+
VERSION 1.1.2
4338
SOVERSION 3)
4439

4540
target_include_directories(${PROJECT_NAME}
@@ -49,7 +44,7 @@ target_include_directories(${PROJECT_NAME}
4944

5045
if(NOT MSVC)
5146
target_link_libraries(${PROJECT_NAME} PUBLIC
52-
pthread
47+
$<$<NOT:$<STREQUAL:${CMAKE_SYSTEM_NAME},QNX>>:pthread>
5348
$<$<NOT:$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>>:rt>)
5449
endif()
5550

src/libipc/platform/detail.h

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
1-
#pragma once
1+
#ifndef LIBIPC_SRC_PLATFORM_DETAIL_H_
2+
#define LIBIPC_SRC_PLATFORM_DETAIL_H_
3+
4+
// detect platform
5+
6+
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || \
7+
defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
8+
defined(WINCE) || defined(_WIN32_WCE)
9+
# define IPC_OS_WINDOWS_
10+
#elif defined(__linux__) || defined(__linux)
11+
# define IPC_OS_LINUX_
12+
#elif defined(__QNX__)
13+
# define IPC_OS_QNX_
14+
#elif defined(__APPLE__)
15+
#elif defined(__ANDROID__)
16+
// TBD
17+
#endif
18+
19+
#if defined(__cplusplus)
220

321
#include <memory>
422
#include <mutex>
@@ -22,18 +40,6 @@
2240
# error "IPC_CONSTEXPR_ has been defined."
2341
#endif
2442

25-
// detect platform
26-
27-
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || \
28-
defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
29-
defined(WINCE) || defined(_WIN32_WCE)
30-
# define IPC_OS_WINDOWS_
31-
#endif/*WIN*/
32-
33-
#if defined(__linux__) || defined(__linux)
34-
# define IPC_OS_LINUX_
35-
#endif/*linux*/
36-
3743
#if __cplusplus >= 201703L
3844

3945
#define IPC_UNUSED_ [[maybe_unused]]
@@ -123,17 +129,8 @@ constexpr const T& (min)(const T& a, const T& b) {
123129

124130
#endif/*__cplusplus < 201703L*/
125131

126-
template <typename T, typename U>
127-
auto horrible_cast(U rhs) noexcept
128-
-> typename std::enable_if<std::is_trivially_copyable<T>::value
129-
&& std::is_trivially_copyable<U>::value, T>::type {
130-
union {
131-
T t;
132-
U u;
133-
} r = {};
134-
r.u = rhs;
135-
return r.t;
136-
}
137-
138132
} // namespace detail
139133
} // namespace ipc
134+
135+
#endif // defined(__cplusplus)
136+
#endif // LIBIPC_SRC_PLATFORM_DETAIL_H_

src/libipc/platform/platform.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
#include "libipc/platform/detail.h"
3+
#if defined(IPC_OS_WINDOWS_)
4+
#elif defined(IPC_OS_LINUX_)
5+
#include "libipc/platform/linux/a0/err.c"
6+
#include "libipc/platform/linux/a0/mtx.c"
7+
#include "libipc/platform/linux/a0/strconv.c"
8+
#include "libipc/platform/linux/a0/tid.c"
9+
#include "libipc/platform/linux/a0/time.c"
10+
#elif defined(IPC_OS_QNX_)
11+
#else/*IPC_OS*/
12+
# error "Unsupported platform."
13+
#endif

src/libipc/platform/platform.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
#include "libipc/platform/detail.h"
3+
#if defined(IPC_OS_WINDOWS_)
4+
#include "libipc/platform/win/shm_win.cpp"
5+
#elif defined(IPC_OS_LINUX_) || defined(IPC_OS_QNX_)
6+
#include "libipc/platform/linux/shm_posix.cpp"
7+
#else/*IPC_OS*/
8+
# error "Unsupported platform."
9+
#endif

src/libipc/platform/posix/condition.h

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <cstring>
5+
6+
#include <pthread.h>
7+
8+
#include "libipc/platform/get_wait_time.h"
9+
#include "libipc/utility/log.h"
10+
#include "libipc/utility/scope_guard.h"
11+
#include "libipc/mutex.h"
12+
#include "libipc/shm.h"
13+
14+
namespace ipc {
15+
namespace detail {
16+
namespace sync {
17+
18+
class condition {
19+
ipc::shm::handle shm_;
20+
pthread_cond_t *cond_ = nullptr;
21+
22+
pthread_cond_t *acquire_cond(char const *name) {
23+
if (!shm_.acquire(name, sizeof(pthread_cond_t))) {
24+
ipc::error("[acquire_cond] fail shm.acquire: %s\n", name);
25+
return nullptr;
26+
}
27+
return static_cast<pthread_cond_t *>(shm_.get());
28+
}
29+
30+
public:
31+
condition() = default;
32+
~condition() = default;
33+
34+
pthread_cond_t const *native() const noexcept {
35+
return cond_;
36+
}
37+
38+
pthread_cond_t *native() noexcept {
39+
return cond_;
40+
}
41+
42+
bool valid() const noexcept {
43+
static const char tmp[sizeof(pthread_cond_t)] {};
44+
return (cond_ != nullptr)
45+
&& (std::memcmp(tmp, cond_, sizeof(pthread_cond_t)) != 0);
46+
}
47+
48+
bool open(char const *name) noexcept {
49+
close();
50+
if ((cond_ = acquire_cond(name)) == nullptr) {
51+
return false;
52+
}
53+
if (shm_.ref() > 1) {
54+
return valid();
55+
}
56+
::pthread_cond_destroy(cond_);
57+
auto finally = ipc::guard([this] { close(); }); // close when failed
58+
// init condition
59+
int eno;
60+
pthread_condattr_t cond_attr;
61+
if ((eno = ::pthread_condattr_init(&cond_attr)) != 0) {
62+
ipc::error("fail pthread_condattr_init[%d]\n", eno);
63+
return false;
64+
}
65+
IPC_UNUSED_ auto guard_cond_attr = unique_ptr(&cond_attr, ::pthread_condattr_destroy);
66+
if ((eno = ::pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED)) != 0) {
67+
ipc::error("fail pthread_condattr_setpshared[%d]\n", eno);
68+
return false;
69+
}
70+
*cond_ = PTHREAD_COND_INITIALIZER;
71+
if ((eno = ::pthread_cond_init(cond_, &cond_attr)) != 0) {
72+
ipc::error("fail pthread_cond_init[%d]\n", eno);
73+
return false;
74+
}
75+
finally.dismiss();
76+
return valid();
77+
}
78+
79+
void close() noexcept {
80+
if ((shm_.ref() <= 1) && cond_ != nullptr) {
81+
int eno;
82+
if ((eno = ::pthread_cond_destroy(cond_)) != 0) {
83+
ipc::error("fail pthread_cond_destroy[%d]\n", eno);
84+
}
85+
}
86+
shm_.release();
87+
cond_ = nullptr;
88+
}
89+
90+
bool wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept {
91+
if (!valid()) return false;
92+
switch (tm) {
93+
case invalid_value: {
94+
int eno;
95+
if ((eno = ::pthread_cond_wait(cond_, static_cast<pthread_mutex_t *>(mtx.native()))) != 0) {
96+
ipc::error("fail pthread_cond_wait[%d]\n", eno);
97+
return false;
98+
}
99+
}
100+
break;
101+
default: {
102+
auto ts = detail::make_timespec(tm);
103+
int eno;
104+
if ((eno = ::pthread_cond_timedwait(cond_, static_cast<pthread_mutex_t *>(mtx.native()), &ts)) != 0) {
105+
if (eno != ETIMEDOUT) {
106+
ipc::error("fail pthread_cond_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
107+
eno, tm, ts.tv_sec, ts.tv_nsec);
108+
}
109+
return false;
110+
}
111+
}
112+
break;
113+
}
114+
return true;
115+
}
116+
117+
bool notify() noexcept {
118+
if (!valid()) return false;
119+
int eno;
120+
if ((eno = ::pthread_cond_signal(cond_)) != 0) {
121+
ipc::error("fail pthread_cond_signal[%d]\n", eno);
122+
return false;
123+
}
124+
return true;
125+
}
126+
127+
bool broadcast() noexcept {
128+
if (!valid()) return false;
129+
int eno;
130+
if ((eno = ::pthread_cond_broadcast(cond_)) != 0) {
131+
ipc::error("fail pthread_cond_broadcast[%d]\n", eno);
132+
return false;
133+
}
134+
return true;
135+
}
136+
};
137+
138+
} // namespace sync
139+
} // namespace detail
140+
} // namespace ipc
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <system_error>
5+
6+
#include <sys/time.h>
7+
#include <time.h>
8+
#include <errno.h>
9+
10+
#include "libipc/utility/log.h"
11+
12+
namespace ipc {
13+
namespace detail {
14+
15+
inline bool calc_wait_time(timespec &ts, std::uint64_t tm /*ms*/) noexcept {
16+
timeval now;
17+
int eno = ::gettimeofday(&now, NULL);
18+
if (eno != 0) {
19+
ipc::error("fail gettimeofday [%d]\n", eno);
20+
return false;
21+
}
22+
ts.tv_nsec = (now.tv_usec + (tm % 1000) * 1000) * 1000;
23+
ts.tv_sec = now.tv_sec + (tm / 1000) + (ts.tv_nsec / 1000000000l);
24+
ts.tv_nsec %= 1000000000l;
25+
return true;
26+
}
27+
28+
inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) {
29+
timespec ts {};
30+
if (!calc_wait_time(ts, tm)) {
31+
ipc::error("fail calc_wait_time: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
32+
tm, ts.tv_sec, ts.tv_nsec);
33+
throw std::system_error{static_cast<int>(errno), std::system_category()};
34+
}
35+
return ts;
36+
}
37+
38+
} // namespace detail
39+
} // namespace ipc

0 commit comments

Comments
 (0)