Skip to content

Commit

Permalink
Split up compilation of rwlock to separate files.
Browse files Browse the repository at this point in the history
It is much easier to follow this way.

Signed-off-by: Chris Lalancette <[email protected]>
  • Loading branch information
clalancette committed Sep 13, 2023
1 parent 70e8eaa commit ab44fc8
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 120 deletions.
16 changes: 15 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,24 @@ if(NOT WIN32)
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic)
endif()

option(FORCE_STUB_RWLOCK "Force the use of a 'stub' rwlock implementation, which makes logging slower and inherently racy." OFF)

if(WIN32)
set(time_impl_c src/time_win32.c)
set(rwlock_impl_c src/rwlock_win32.c)
else()
set(time_impl_c src/time_unix.c)
find_package(Threads QUIET)
if(Threads_FOUND)
set(rwlock_impl_c src/rwlock_pthread.c)
else()
if(FORCE_STUB_RWLOCK)
set(rwlock_impl_c src/rwlock_stub.c)
add_definitions(-DRWLOCK_STUB)
else()
message(FATAL "No valid rwlock implementation found!")
endif()
endif()
endif()

set(rcutils_sources
Expand All @@ -63,7 +77,7 @@ set(rcutils_sources
src/process.c
src/qsort.c
src/repl_str.c
src/rwlock.c
${rwlock_impl_c}
src/sha256.c
src/shared_library.c
src/snprintf.c
Expand Down
6 changes: 6 additions & 0 deletions src/logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,11 @@ int rcutils_logging_get_logger_effective_level(const char * name)
severity = g_rcutils_logging_default_logger_level;
}

#if !defined(RWLOCK_STUB)
// If the RWLOCK implementation is a stub, this will definitely cause corruption, even between get
// calls, so we skip it (the consequence is that log level lookups are slower). With a stub
// RWLOCK there is still a race between get and set, but that is less common.

// If the calculated severity is anything but UNSET, we place it into the hashmap for speedier
// lookup next time. If the severity is UNSET, we don't bother because we are going to have to
// walk the hierarchy next time anyway.
Expand All @@ -995,6 +1000,7 @@ int rcutils_logging_get_logger_effective_level(const char * name)
"Failed to cache severity; this is not fatal but will impact performance\n");
}
}
#endif

return severity;
}
Expand Down
126 changes: 126 additions & 0 deletions src/rwlock_pthread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright 2023 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <pthread.h>
#include <stdlib.h>

#include "./rwlock.h" // NOLINT

#include "rcutils/allocator.h"
#include "rcutils/error_handling.h"
#include "rcutils/types/rcutils_ret.h"

typedef struct rcutils_rwlock_impl_s
{
pthread_rwlock_t lock;
rcutils_allocator_t allocator;
} rcutils_rwlock_impl_t;

rcutils_rwlock_t
rcutils_get_zero_initialized_rwlock(void)
{
static rcutils_rwlock_t zero_initialized_rwlock;
zero_initialized_rwlock.impl = NULL;
return zero_initialized_rwlock;
}

rcutils_ret_t
rcutils_rwlock_init(rcutils_rwlock_t * lock, rcutils_allocator_t allocator)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
if (lock->impl != NULL) {
RCUTILS_SET_ERROR_MSG("rwlock already initialized");
return RCUTILS_RET_ERROR;
}
RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
&allocator, "invalid allocator", return RCUTILS_RET_INVALID_ARGUMENT);

lock->impl = allocator.allocate(sizeof(rcutils_rwlock_impl_t), allocator.state);
if (NULL == lock->impl) {
RCUTILS_SET_ERROR_MSG("failed to allocate memory for string map impl struct");
return RCUTILS_RET_BAD_ALLOC;
}

lock->impl->allocator = allocator;

return pthread_rwlock_init(&lock->impl->lock, NULL) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}

rcutils_ret_t
rcutils_rwlock_read_lock(rcutils_rwlock_t * lock)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);

return pthread_rwlock_rdlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}

rcutils_ret_t
rcutils_rwlock_read_unlock(rcutils_rwlock_t * lock)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);

return pthread_rwlock_unlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}

rcutils_ret_t
rcutils_rwlock_write_trylock(rcutils_rwlock_t * lock)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);

return pthread_rwlock_trywrlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}

rcutils_ret_t
rcutils_rwlock_write_lock(rcutils_rwlock_t * lock)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);

return pthread_rwlock_wrlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}

rcutils_ret_t
rcutils_rwlock_write_unlock(rcutils_rwlock_t * lock)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
lock->impl, "invalid lock", return RCUTILS_RET_ERROR);

return pthread_rwlock_unlock(&lock->impl->lock) == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}

rcutils_ret_t
rcutils_rwlock_fini(rcutils_rwlock_t * lock)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(lock, RCUTILS_RET_INVALID_ARGUMENT);
if (NULL == lock->impl) {
return RCUTILS_RET_OK;
}

int retval = pthread_rwlock_destroy(&lock->impl->lock);

rcutils_allocator_t allocator = lock->impl->allocator;

allocator.deallocate(lock->impl, allocator.state);
lock->impl = NULL;

return retval == 0 ? RCUTILS_RET_OK : RCUTILS_RET_ERROR;
}
74 changes: 74 additions & 0 deletions src/rwlock_stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2023 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "./rwlock.h" // NOLINT

#include "rcutils/allocator.h"
#include "rcutils/types/rcutils_ret.h"

rcutils_rwlock_t
rcutils_get_zero_initialized_rwlock(void)
{
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_init(rcutils_rwlock_t * lock, rcutils_allocator_t allocator)
{
(void)lock;
(void)allocator;
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_read_lock(rcutils_rwlock_t * lock)
{
(void)lock;
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_read_unlock(rcutils_rwlock_t * lock)
{
(void)lock;
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_write_lock(rcutils_rwlock_t * lock)
{
(void)lock;
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_write_trylock(rcutils_rwlock_t * lock)
{
(void)lock;
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_write_unlock(rcutils_rwlock_t * lock)
{
(void)lock;
return RCUTILS_RET_OK;
}

rcutils_ret_t
rcutils_rwlock_fini(rcutils_rwlock_t * lock)
{
(void)lock;
return RCUTILS_RET_OK;
}
Loading

0 comments on commit ab44fc8

Please sign in to comment.