Skip to content

Commit

Permalink
Add compile flag and macros to create thread safe version of the libr…
Browse files Browse the repository at this point in the history
…ary.
  • Loading branch information
Kerilk committed Jun 28, 2023
1 parent 375fe15 commit 51576d7
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 17 deletions.
4 changes: 3 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ AM_CONDITIONAL([ISMACOS], [test "x$macos" = xyes])
AC_ARG_ENABLE([strict], AS_HELP_STRING([--enable-strict], [Enable -Werror]))
AM_CONDITIONAL([STRICT], [test "x$enable_strict" = xyes])

AC_ARG_ENABLE([thread-safe], AS_HELP_STRING([--enable-thread-safe], [Build with thread saffety enabled]))
AM_CONDITIONAL([THREAD_SAFE], [test "x$enable_thread_safe" = xyes])

AC_ARG_ENABLE([kokkos-connector],
AS_HELP_STRING([--enable-kokkos-connector], [Enable CConfigSpace Kokkos connector]),
[], [enable_kokkos_connector=yes])
Expand Down Expand Up @@ -79,7 +82,6 @@ fi
PKG_CHECK_MODULES([GSL], [gsl])

#check for valgrind
AX_VALGRIND_DFLT([helgrind], [off])
AX_VALGRIND_DFLT([drd], [off])
AX_VALGRIND_DFLT([sgcheck], [off])
AX_VALGRIND_CHECK
Expand Down
4 changes: 4 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ if STRICT
AM_CFLAGS += -Werror
endif

if THREAD_SAFE
AM_CFLAGS += -DTHREAD_SAFE
endif

lib_LTLIBRARIES = libcconfigspace.la

version.h: $(srcdir)/version.h.subst .version_timestamp
Expand Down
29 changes: 18 additions & 11 deletions src/cconfigspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ const ccs_version_t ccs_version = {
CCS_VERSION_REVISION, CCS_VERSION_PATCH, CCS_VERSION_MINOR,
CCS_VERSION_MAJOR};

#if CCS_THREAD_SAFE
static pthread_mutex_t _ccs_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static int32_t _ccs_refcount = 0;

ccs_result_t
ccs_init()
{
ccs_result_t err = CCS_RESULT_SUCCESS;
pthread_mutex_lock(&_ccs_mutex);
CCS_MUTEX_LOCK(_ccs_mutex);

CCS_REFUTE_ERR_GOTO(
err, _ccs_refcount < 0 || _ccs_refcount == INT32_MAX,
Expand All @@ -32,21 +34,21 @@ ccs_init()
gsl_rng_env_setup();
_ccs_refcount += 1;
end:
pthread_mutex_unlock(&_ccs_mutex);
CCS_MUTEX_UNLOCK(_ccs_mutex);
return err;
}

ccs_result_t
ccs_fini()
{
ccs_result_t err = CCS_RESULT_SUCCESS;
pthread_mutex_lock(&_ccs_mutex);
CCS_MUTEX_LOCK(_ccs_mutex);

CCS_REFUTE_ERR_GOTO(
err, _ccs_refcount < 1, CCS_RESULT_ERROR_INVALID_VALUE, end);
_ccs_refcount -= 1;
end:
pthread_mutex_unlock(&_ccs_mutex);
CCS_MUTEX_UNLOCK(_ccs_mutex);
return err;
}

Expand Down Expand Up @@ -99,7 +101,8 @@ ccs_release_object(ccs_object_t object)
cb->callback(object, cb->user_data);
}
utarray_free(obj->callbacks);
pthread_mutex_destroy(&obj->mutex);
CCS_MUTEX_DESTROY(obj->mutex);
CCS_RWLOCK_DESTROY(obj->lock);
}
CCS_VALIDATE(obj->ops->del(object));
free(object);
Expand Down Expand Up @@ -142,9 +145,9 @@ ccs_object_set_destroy_callback(
if (!obj->callbacks)
utarray_new(obj->callbacks, &_object_callback_icd);
_ccs_object_callback_t cb = {callback, user_data};
pthread_mutex_lock(&obj->mutex);
CCS_MUTEX_LOCK(obj->mutex);
utarray_push_back(obj->callbacks, &cb);
pthread_mutex_unlock(&obj->mutex);
CCS_MUTEX_UNLOCK(obj->mutex);
return CCS_RESULT_SUCCESS;
}

Expand All @@ -153,7 +156,9 @@ ccs_object_set_user_data(ccs_object_t object, void *user_data)
{
CCS_CHECK_BASE_OBJ(object);
_ccs_object_internal_t *obj = (_ccs_object_internal_t *)object;
CCS_ATOMIC_STORE(obj->user_data, user_data);
CCS_RWLOCK_WRLOCK(obj->lock);
obj->user_data = user_data;
CCS_RWLOCK_UNLOCK(obj->lock);
return CCS_RESULT_SUCCESS;
}

Expand All @@ -163,7 +168,9 @@ ccs_object_get_user_data(ccs_object_t object, void **user_data_ret)
CCS_CHECK_BASE_OBJ(object);
CCS_CHECK_PTR(user_data_ret);
_ccs_object_internal_t *obj = (_ccs_object_internal_t *)object;
*user_data_ret = CCS_ATOMIC_LOAD(obj->user_data);
CCS_RWLOCK_RDLOCK(obj->lock);
*user_data_ret = obj->user_data;
CCS_RWLOCK_UNLOCK(obj->lock);
return CCS_RESULT_SUCCESS;
}

Expand All @@ -175,10 +182,10 @@ ccs_object_set_serialize_callback(
{
CCS_CHECK_BASE_OBJ(object);
_ccs_object_internal_t *obj = (_ccs_object_internal_t *)object;
pthread_mutex_lock(&obj->mutex);
CCS_RWLOCK_WRLOCK(obj->lock);
obj->serialize_callback = callback;
obj->serialize_user_data = user_data;
pthread_mutex_unlock(&obj->mutex);
CCS_RWLOCK_UNLOCK(obj->lock);
return CCS_RESULT_SUCCESS;
}

Expand Down
119 changes: 119 additions & 0 deletions src/cconfigspace_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,119 @@ _ccs_interval_include(ccs_interval_t *interval, ccs_numeric_t value)
#define CCS_ATOMIC_STORE(val, set) \
__atomic_store_n(&(val), set, __ATOMIC_RELAXED)

#if THREAD_SAFE
#define CCS_THREAD_SAFE 1
#else
#define CCS_THREAD_SAFE 0
#endif

static inline int _ccs_do_nothing(void) { return 0; }

#if CCS_THREAD_SAFE

#define CCS_MUTEX_LOCK(mut) \
do { \
pthread_mutex_lock(&(mut)); \
} while (0)

#define CCS_MUTEX_UNLOCK(mut) \
do { \
pthread_mutex_unlock(&(mut)); \
} while (0)

#define CCS_MUTEX_INIT(mut) \
do { \
pthread_mutex_init(&(mut)); \
} while (0)

#define CCS_MUTEX_DESTROY(mut) \
do { \
pthread_mutex_destroy(&(mut)); \
} while (0)

#define CCS_RWLOCK_RDLOCK(lck) \
do { \
pthread_rwlock_rdlock(&(lck)); \
} while (0)

#define CCS_RWLOCK_WRLOCK(lck) \
do { \
pthread_rwlock_wrlock(&(lck)); \
} while (0)

#define CCS_RWLOCK_UNLOCK(lck) \
do { \
pthread_rwlock_unlock(&(lck)); \
} while (0)

#define CCS_RWLOCK_INIT(lck) \
do { \
pthread_rwlock_init(&(lck)); \
} while (0)

#define CCS_RWLOCK_DESTROY(lck) \
do { \
pthread_rwlock_destroy(&(lck)); \
} while (0)

#else

#define CCS_MUTEX_LOCK(mut) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_MUTEX_UNLOCK(mut) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_MUTEX_INIT(mut) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_MUTEX_DESTROY(mut) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_RWLOCK_RDLOCK(lck) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_RWLOCK_WRLOCK(lck) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_RWLOCK_UNLOCK(lck) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_RWLOCK_INIT(lck) \
do { \
_ccs_do_nothing(); \
} while (0)

#define CCS_RWLOCK_DESTROY(lck) \
do { \
_ccs_do_nothing(); \
} while (0)

#endif

#define CCS_OBJ_RDLOCK(o) \
CCS_RWLOCK_RDLOCK(((_ccs_object_template_t *)(o))->obj.lock)

#define CCS_OBJ_WRLOCK(o) \
CCS_RWLOCK_WRLOCK(((_ccs_object_template_t *)(o))->obj.lock)

#define CCS_OBJ_UNLOCK(o) \
CCS_RWLOCK_UNLOCK(((_ccs_object_template_t *)(o))->obj.lock)

#if CCS_RICH_ERRORS
#define CCS_ADD_STACK_ELEM() \
do { \
Expand Down Expand Up @@ -255,7 +368,10 @@ struct _ccs_object_internal_s {
ccs_object_type_t type;
int32_t refcount;
void *user_data;
#if CCS_THREAD_SAFE
pthread_mutex_t mutex;
pthread_rwlock_t lock;
#endif
UT_array *callbacks;
_ccs_object_ops_t *ops;
ccs_object_serialize_callback_t serialize_callback;
Expand All @@ -279,7 +395,10 @@ _ccs_object_init(
o->type = t;
o->refcount = 1;
o->user_data = NULL;
#if CCS_THREAD_SAFE
o->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
o->lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER;
#endif
o->callbacks = NULL;
o->ops = ops;
o->serialize_callback = NULL;
Expand Down
14 changes: 9 additions & 5 deletions src/parameter_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
struct _ccs_parameter_string_data_s {
_ccs_parameter_common_data_t common_data;
_ccs_hash_datum_t *stored_values;
#if CCS_THREAD_SAFE
pthread_mutex_t mutex;
#endif
};
typedef struct _ccs_parameter_string_data_s _ccs_parameter_string_data_t;

Expand Down Expand Up @@ -42,7 +44,7 @@ _ccs_parameter_string_del(ccs_object_t o)
HASH_DEL(data->stored_values, current);
free(current);
}
pthread_mutex_destroy(&data->mutex);
CCS_MUTEX_DESTROY(data->mutex);
return CCS_RESULT_SUCCESS;
}

Expand Down Expand Up @@ -121,7 +123,7 @@ _ccs_parameter_string_serialize(
{ \
CCS_RAISE_ERR_GOTO( \
err, CCS_RESULT_ERROR_OUT_OF_MEMORY, errmem, \
"Not enough memory to allocate array"); \
"Not enough memory to allocate hash"); \
}

static ccs_result_t
Expand All @@ -141,7 +143,7 @@ _ccs_parameter_string_check_values(
results[i] = CCS_TRUE;
if (!values_ret)
goto end;
pthread_mutex_lock(&d->mutex);
CCS_MUTEX_LOCK(d->mutex);
for (size_t i = 0; i < num_values; i++) {
if (results[i] == CCS_TRUE) {
_ccs_hash_datum_t *p;
Expand Down Expand Up @@ -173,11 +175,11 @@ _ccs_parameter_string_check_values(
values_ret[i] = ccs_inactive;
}
}
pthread_mutex_unlock(&d->mutex);
CCS_MUTEX_UNLOCK(d->mutex);
end:
return CCS_RESULT_SUCCESS;
errmem:
pthread_mutex_unlock(&d->mutex);
CCS_MUTEX_UNLOCK(d->mutex);
return err;
}

Expand Down Expand Up @@ -261,7 +263,9 @@ ccs_create_string_parameter(const char *name, ccs_parameter_t *parameter_ret)
strcpy((char *)parameter_data->common_data.name, name);
parameter_data->common_data.interval.type = CCS_NUMERIC_TYPE_INT;
parameter_data->stored_values = NULL;
#if CCS_THREAD_SAFE
parameter_data->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
#endif
parameter->data = (_ccs_parameter_data_t *)parameter_data;
*parameter_ret = parameter;

Expand Down

0 comments on commit 51576d7

Please sign in to comment.