Skip to content

Commit ab44fc8

Browse files
committed
Split up compilation of rwlock to separate files.
It is much easier to follow this way. Signed-off-by: Chris Lalancette <[email protected]>
1 parent 70e8eaa commit ab44fc8

File tree

5 files changed

+235
-120
lines changed

5 files changed

+235
-120
lines changed

CMakeLists.txt

+15-1
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,24 @@ if(NOT WIN32)
4242
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic)
4343
endif()
4444

45+
option(FORCE_STUB_RWLOCK "Force the use of a 'stub' rwlock implementation, which makes logging slower and inherently racy." OFF)
46+
4547
if(WIN32)
4648
set(time_impl_c src/time_win32.c)
49+
set(rwlock_impl_c src/rwlock_win32.c)
4750
else()
4851
set(time_impl_c src/time_unix.c)
52+
find_package(Threads QUIET)
53+
if(Threads_FOUND)
54+
set(rwlock_impl_c src/rwlock_pthread.c)
55+
else()
56+
if(FORCE_STUB_RWLOCK)
57+
set(rwlock_impl_c src/rwlock_stub.c)
58+
add_definitions(-DRWLOCK_STUB)
59+
else()
60+
message(FATAL "No valid rwlock implementation found!")
61+
endif()
62+
endif()
4963
endif()
5064

5165
set(rcutils_sources
@@ -63,7 +77,7 @@ set(rcutils_sources
6377
src/process.c
6478
src/qsort.c
6579
src/repl_str.c
66-
src/rwlock.c
80+
${rwlock_impl_c}
6781
src/sha256.c
6882
src/shared_library.c
6983
src/snprintf.c

src/logging.c

+6
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,11 @@ int rcutils_logging_get_logger_effective_level(const char * name)
983983
severity = g_rcutils_logging_default_logger_level;
984984
}
985985

986+
#if !defined(RWLOCK_STUB)
987+
// If the RWLOCK implementation is a stub, this will definitely cause corruption, even between get
988+
// calls, so we skip it (the consequence is that log level lookups are slower). With a stub
989+
// RWLOCK there is still a race between get and set, but that is less common.
990+
986991
// If the calculated severity is anything but UNSET, we place it into the hashmap for speedier
987992
// lookup next time. If the severity is UNSET, we don't bother because we are going to have to
988993
// walk the hierarchy next time anyway.
@@ -995,6 +1000,7 @@ int rcutils_logging_get_logger_effective_level(const char * name)
9951000
"Failed to cache severity; this is not fatal but will impact performance\n");
9961001
}
9971002
}
1003+
#endif
9981004

9991005
return severity;
10001006
}

src/rwlock_pthread.c

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 2023 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <pthread.h>
16+
#include <stdlib.h>
17+
18+
#include "./rwlock.h" // NOLINT
19+
20+
#include "rcutils/allocator.h"
21+
#include "rcutils/error_handling.h"
22+
#include "rcutils/types/rcutils_ret.h"
23+
24+
typedef struct rcutils_rwlock_impl_s
25+
{
26+
pthread_rwlock_t lock;
27+
rcutils_allocator_t allocator;
28+
} rcutils_rwlock_impl_t;
29+
30+
rcutils_rwlock_t
31+
rcutils_get_zero_initialized_rwlock(void)
32+
{
33+
static rcutils_rwlock_t zero_initialized_rwlock;
34+
zero_initialized_rwlock.impl = NULL;
35+
return zero_initialized_rwlock;
36+
}
37+
38+
rcutils_ret_t
39+
rcutils_rwlock_init(rcutils_rwlock_t * lock, rcutils_allocator_t allocator)
40+
{
41+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
42+
if (lock->impl != NULL) {
43+
RCUTILS_SET_ERROR_MSG("rwlock already initialized");
44+
return RCUTILS_RET_ERROR;
45+
}
46+
RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
47+
&allocator, "invalid allocator", return RCUTILS_RET_INVALID_ARGUMENT);
48+
49+
lock->impl = allocator.allocate(sizeof(rcutils_rwlock_impl_t), allocator.state);
50+
if (NULL == lock->impl) {
51+
RCUTILS_SET_ERROR_MSG("failed to allocate memory for string map impl struct");
52+
return RCUTILS_RET_BAD_ALLOC;
53+
}
54+
55+
lock->impl->allocator = allocator;
56+
57+
return pthread_rwlock_init(&lock->impl->lock, NULL) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
58+
}
59+
60+
rcutils_ret_t
61+
rcutils_rwlock_read_lock(rcutils_rwlock_t * lock)
62+
{
63+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
64+
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
65+
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);
66+
67+
return pthread_rwlock_rdlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
68+
}
69+
70+
rcutils_ret_t
71+
rcutils_rwlock_read_unlock(rcutils_rwlock_t * lock)
72+
{
73+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
74+
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
75+
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);
76+
77+
return pthread_rwlock_unlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
78+
}
79+
80+
rcutils_ret_t
81+
rcutils_rwlock_write_trylock(rcutils_rwlock_t * lock)
82+
{
83+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
84+
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
85+
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);
86+
87+
return pthread_rwlock_trywrlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
88+
}
89+
90+
rcutils_ret_t
91+
rcutils_rwlock_write_lock(rcutils_rwlock_t * lock)
92+
{
93+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
94+
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
95+
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);
96+
97+
return pthread_rwlock_wrlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
98+
}
99+
100+
rcutils_ret_t
101+
rcutils_rwlock_write_unlock(rcutils_rwlock_t * lock)
102+
{
103+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
104+
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
105+
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);
106+
107+
return pthread_rwlock_unlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
108+
}
109+
110+
rcutils_ret_t
111+
rcutils_rwlock_fini(rcutils_rwlock_t * lock)
112+
{
113+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
114+
if (NULL == lock->impl) {
115+
return RCUTILS_RET_OK;
116+
}
117+
118+
int retval = pthread_rwlock_destroy(&lock->impl->lock);
119+
120+
rcutils_allocator_t allocator = lock->impl->allocator;
121+
122+
allocator.deallocate(lock->impl, allocator.state);
123+
lock->impl = NULL;
124+
125+
return retval == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
126+
}

src/rwlock_stub.c

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2023 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "./rwlock.h" // NOLINT
16+
17+
#include "rcutils/allocator.h"
18+
#include "rcutils/types/rcutils_ret.h"
19+
20+
rcutils_rwlock_t
21+
rcutils_get_zero_initialized_rwlock(void)
22+
{
23+
return RCUTILS_RET_OK;
24+
}
25+
26+
rcutils_ret_t
27+
rcutils_rwlock_init(rcutils_rwlock_t * lock, rcutils_allocator_t allocator)
28+
{
29+
(void)lock;
30+
(void)allocator;
31+
return RCUTILS_RET_OK;
32+
}
33+
34+
rcutils_ret_t
35+
rcutils_rwlock_read_lock(rcutils_rwlock_t * lock)
36+
{
37+
(void)lock;
38+
return RCUTILS_RET_OK;
39+
}
40+
41+
rcutils_ret_t
42+
rcutils_rwlock_read_unlock(rcutils_rwlock_t * lock)
43+
{
44+
(void)lock;
45+
return RCUTILS_RET_OK;
46+
}
47+
48+
rcutils_ret_t
49+
rcutils_rwlock_write_lock(rcutils_rwlock_t * lock)
50+
{
51+
(void)lock;
52+
return RCUTILS_RET_OK;
53+
}
54+
55+
rcutils_ret_t
56+
rcutils_rwlock_write_trylock(rcutils_rwlock_t * lock)
57+
{
58+
(void)lock;
59+
return RCUTILS_RET_OK;
60+
}
61+
62+
rcutils_ret_t
63+
rcutils_rwlock_write_unlock(rcutils_rwlock_t * lock)
64+
{
65+
(void)lock;
66+
return RCUTILS_RET_OK;
67+
}
68+
69+
rcutils_ret_t
70+
rcutils_rwlock_fini(rcutils_rwlock_t * lock)
71+
{
72+
(void)lock;
73+
return RCUTILS_RET_OK;
74+
}

0 commit comments

Comments
 (0)