Skip to content

Commit

Permalink
Implement [ap_]atomics for [u]int/[u]long/size_t based on APR ones, w…
Browse files Browse the repository at this point in the history
…ith and without saturation.
  • Loading branch information
ylavic committed Nov 29, 2023
1 parent 9fbb998 commit 0dc3ead
Show file tree
Hide file tree
Showing 9 changed files with 1,009 additions and 1 deletion.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ SET(LIBHTTPD_SOURCES
server/ssl.c
server/scoreboard.c
server/util.c
server/util_atomics.c
server/util_cfgtree.c
server/util_cookies.c
server/util_debug.c
Expand Down
1 change: 1 addition & 0 deletions NWGNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ FILES_nlm_objs = \
$(OBJDIR)/request.o \
$(OBJDIR)/scoreboard.o \
$(OBJDIR)/util.o \
$(OBJDIR)/util_atomics.o \
$(OBJDIR)/util_cfgtree.o \
$(OBJDIR)/util_charset.o \
$(OBJDIR)/util_cookies.o \
Expand Down
1 change: 1 addition & 0 deletions build/nw_export.inc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "httpd.h"

/* Preprocess all of the standard HTTPD headers. */
#include "ap_atomics.h"
#include "ap_compat.h"
#include "ap_listen.h"
#include "ap_mmn.h"
Expand Down
122 changes: 122 additions & 0 deletions include/ap_atomics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "ap_config.h"

#include "apr.h"


/* Atomics for int (uses int32_t's on all platforms we care about) */

AP_DECLARE(int) ap_atomic_int_get(int volatile *val);

AP_DECLARE(void) ap_atomic_int_set(int volatile *val, int to);

AP_DECLARE(int) ap_atomic_int_xchg(int volatile *val, int with);

AP_DECLARE(int) ap_atomic_int_cas(int volatile *val, int with, int cmp);

AP_DECLARE(int) ap_atomic_int_add(int volatile *val, int add);

AP_DECLARE(int) ap_atomic_int_add_sat(int volatile *val, int add);

AP_DECLARE(int) ap_atomic_int_sub(int volatile *val, int sub);

AP_DECLARE(int) ap_atomic_int_sub_sat(int volatile *val, int sub);


/* Atomics for unsigned int (uses uint32_t's on all platforms we care about) */

AP_DECLARE(unsigned int) ap_atomic_uint_get(unsigned int volatile *val);

AP_DECLARE(void) ap_atomic_uint_set(unsigned int volatile *val,
unsigned int to);

AP_DECLARE(unsigned int) ap_atomic_uint_xchg(unsigned int volatile *val,
unsigned int with);

AP_DECLARE(unsigned int) ap_atomic_uint_cas(unsigned int volatile *val,
unsigned int with,
unsigned int cmp);

AP_DECLARE(unsigned int) ap_atomic_uint_add(unsigned int volatile *val,
unsigned int add);

AP_DECLARE(unsigned int) ap_atomic_uint_add_sat(unsigned int volatile *val,
unsigned int add);

AP_DECLARE(unsigned int) ap_atomic_uint_sub(unsigned int volatile *val,
unsigned int sub);

AP_DECLARE(unsigned int) ap_atomic_uint_sub_sat(unsigned int volatile *val,
unsigned int sub);


/* Atomics for long (uses int32_t's or int64_t's depending on LONG_MAX) */

AP_DECLARE(long) ap_atomic_long_get(long volatile *val);

AP_DECLARE(void) ap_atomic_long_set(long volatile *val, long to);

AP_DECLARE(long) ap_atomic_long_xchg(long volatile *val, long with);

AP_DECLARE(long) ap_atomic_long_cas(long volatile *val, long with, long cmp);

AP_DECLARE(long) ap_atomic_long_add(long volatile *val, long add);

AP_DECLARE(long) ap_atomic_long_add_sat(long volatile *val, long add);

AP_DECLARE(long) ap_atomic_long_sub(long volatile *val, long sub);

AP_DECLARE(long) ap_atomic_long_sub_sat(long volatile *val, long sub);


/* Atomics for unsigned long (uses uint32_t's or uint64_t's depending on ULONG_MAX) */

AP_DECLARE(unsigned long) ap_atomic_ulong_get(unsigned long volatile *val);

AP_DECLARE(void) ap_atomic_ulong_set(unsigned long volatile *val,
unsigned long to);

AP_DECLARE(unsigned long) ap_atomic_ulong_xchg(unsigned long volatile *val,
unsigned long with);

AP_DECLARE(unsigned long) ap_atomic_ulong_cas(unsigned long volatile *val,
unsigned long with,
unsigned long cmp);

AP_DECLARE(unsigned long) ap_atomic_ulong_add(unsigned long volatile *val,
unsigned long add);

AP_DECLARE(unsigned long) ap_atomic_ulong_add_sat(unsigned long volatile *val,
unsigned long add);

AP_DECLARE(unsigned long) ap_atomic_ulong_sub(unsigned long volatile *val,
unsigned long sub);

AP_DECLARE(unsigned long) ap_atomic_ulong_sub_sat(unsigned long volatile *val,
unsigned long sub);


/* Atomics for size_t (uses uint32_t's or uint64_t's depending on sizeof(void*)) */

AP_DECLARE(apr_size_t) ap_atomic_size_get(apr_size_t volatile *val);

AP_DECLARE(void) ap_atomic_size_set(apr_size_t volatile *val,
apr_size_t to);

AP_DECLARE(apr_size_t) ap_atomic_size_xchg(apr_size_t volatile *val,
apr_size_t with);

AP_DECLARE(apr_size_t) ap_atomic_size_cas(apr_size_t volatile *val,
apr_size_t with,
apr_size_t cmp);

AP_DECLARE(apr_size_t) ap_atomic_size_add(apr_size_t volatile *val,
apr_size_t add);

AP_DECLARE(apr_size_t) ap_atomic_size_add_sat(apr_size_t volatile *val,
apr_size_t add);

AP_DECLARE(apr_size_t) ap_atomic_size_sub(apr_size_t volatile *val,
apr_size_t sub);

AP_DECLARE(apr_size_t) ap_atomic_size_sub_sat(apr_size_t volatile *val,
apr_size_t sub);
18 changes: 18 additions & 0 deletions include/ap_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,19 @@
#define AP_HAVE_DESIGNATED_INITIALIZER
#endif

#ifndef __has_builtin /* check for supported builtin on clang */
#define __has_builtin(x) 0
#endif
#ifndef __has_feature /* check for supported feature on clang */
#define __has_feature(x) 0
#endif
#ifndef __has_extension /* check for supported extension on clang */
#define __has_extension __has_feature
#endif
#ifndef __has_attribute /* check for supported attributes on clang */
#define __has_attribute(x) 0
#endif

#if (defined(__GNUC__) && __GNUC__ >= 4) || __has_attribute(sentinel)
#define AP_FN_ATTR_SENTINEL __attribute__((sentinel))
#else
Expand Down Expand Up @@ -261,5 +271,13 @@
#define AP_FN_ATTR_NONNULL(x)
#endif

/** Try harder to inline */
#if __has_attribute(always_inline)
#define AP_FORCE_INLINE APR_INLINE __attribute__((always_inline))
#elif defined(_MSC_VER)
#define AP_FORCE_INLINE APR_INLINE __forceinline
#else
#define AP_FORCE_INLINE APR_INLINE
#endif

#endif /* AP_CONFIG_H */
55 changes: 55 additions & 0 deletions include/httpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
#if APR_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if defined(__STDC__) || defined(_MSC_VER) /* C89 */
#include <assert.h> /* for static_assert */
#endif

/* Note: apr_uri.h is also included, see below */

Expand Down Expand Up @@ -2423,6 +2426,58 @@ AP_DECLARE(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
#define AP_DEBUG_ASSERT(exp) ((void)0)
#endif

/**
* Compile time assertion with custom error message.
* @param exp static expression/condition
* @param msg error message (string literal)
*/
#if (defined(static_assert) \
|| (defined(__cplusplus) && __cplusplus >= 201103L) \
|| (defined(__has_feature) && __has_feature(cxx_static_assert)) \
|| (defined(_MSC_VER ) && _MSC_VER >= 1600))

#define AP_STATIC_ASSERT(exp, msg) static_assert(exp, msg)

#elif (defined(_Static_assert) \
|| (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \
|| (defined(__has_feature) && __has_feature(c_static_assert)) \
|| (defined(__GNUC__) && __GNUC_PREREQ (4, 6)))

#define AP_STATIC_ASSERT(exp, msg) _Static_assert(exp, msg)

#else /* Fail compilation using bit-field with negative width */

#ifdef __COUNTER__

#define AP_STATIC_ASSERT(exp, msg) \
typedef __attribute__((unused)) struct { \
int static_assertion_failed: !!(exp) * 2 - 1; \
} AP_CONCATIFY(ap__static_assert_t_, __COUNTER__)

#else /* __COUNTER__ */

#define AP_STATIC_ASSERT(exp, msg) \
typedef __attribute__((unused)) struct { \
int static_assertion_failed: !!(exp) * 2 - 1; \
} AP_CONCATIFY(ap__static_assert_t_, __LINE__)

#endif /* __COUNTER__ */

#endif /* AP_STATIC_ASSERT */

/**
* Compile time assertion with the expression as error message.
* @param exp static expression/condition
*/
#define AP_BUILD_ASSERT(exp) \
AP_STATIC_ASSERT(exp, "static assertion failed at " \
__FILE__ ":" APR_STRINGIFY(__LINE__) ": " \
APR_STRINGIFY(exp))

/** Properly concatenate two values in the C preprocessor */
#define AP_CONCATIFY(x, y) AP__CONCATIFY(x, y)
#define AP__CONCATIFY(x, y) x ## y

/**
* @defgroup stopsignal Flags which indicate places where the server should stop for debugging.
* @{
Expand Down
8 changes: 8 additions & 0 deletions libhttpd.dsp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LTLIBRARY_NAME = libmain.la
LTLIBRARY_SOURCES = \
config.c log.c main.c vhost.c util.c util_etag.c util_fcgi.c \
util_script.c util_md5.c util_cfgtree.c util_ebcdic.c util_time.c \
connection.c listen.c util_mutex.c \
connection.c listen.c util_mutex.c util_atomics.c \
mpm_common.c mpm_unix.c mpm_fdqueue.c \
util_charset.c util_cookies.c util_debug.c util_xml.c \
util_filter.c util_pcre.c util_regex.c $(EXPORTS_DOT_C) \
Expand Down
Loading

0 comments on commit 0dc3ead

Please sign in to comment.