Skip to content

Commit

Permalink
update hatomic
Browse files Browse the repository at this point in the history
  • Loading branch information
ithewei committed Jul 26, 2020
1 parent 00457d8 commit cc79c07
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 41 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ unittest: prepare
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/mkdir_p unittest/mkdir_test.c base/hbase.c
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/rmdir_p unittest/rmdir_test.c base/hbase.c
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/date unittest/date_test.c base/htime.c
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/hatomic_test unittest/hatomic_test.c -pthread
$(CXX) -g -Wall -std=c++11 -I. -Ibase -o bin/hatomic_cpp_test unittest/hatomic_test.cpp -pthread
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/hmutex_test unittest/hmutex_test.c base/htime.c -pthread
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/connect_test unittest/connect_test.c base/hsocket.c base/htime.c
$(CC) -g -Wall -std=c99 -I. -Ibase -o bin/socketpair_test unittest/socketpair_test.c base/hsocket.c
Expand Down
78 changes: 58 additions & 20 deletions base/hatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
// c++11
#include <atomic>

using std::atomic_flag;
using std::atomic_long;

#define ATOMIC_FLAG_TEST_AND_SET(p) ((p)->test_and_set())
#define ATOMIC_FLAG_CLEAR(p) ((p)->clear())

#else

#include "hconfig.h" // for HAVE_STDATOMIC_H
Expand All @@ -14,6 +20,13 @@
// c11
#include <stdatomic.h>

#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
#define ATOMIC_FLAG_CLEAR atomic_flag_clear
#define ATOMIC_ADD atomic_fetch_add
#define ATOMIC_SUB atomic_fetch_sub
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)

#else

#include "hplatform.h" // for bool, size_t
Expand All @@ -33,56 +46,81 @@ typedef volatile size_t atomic_size_t;

typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;

#define ATOMIC_FLAG_INIT { 0 }
#define ATOMIC_VAR_INIT(value) (value)
#ifdef _WIN32

#define ATOMIC_ADD InterlockedAdd
#define ATOMIC_SUB(p, n) InterlockedAdd(p, -n)
#define ATOMIC_INC InterlockedIncrement
#define ATOMIC_DEC InterlockedDecrement

#ifdef __GNUC__
#elif defined(__GNUC__)

#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
return !__sync_bool_compare_and_swap(&p->_Value, 0, 1);
}

static inline void atomic_flag_clear(atomic_flag* p) {
p->_Value = 0;
}
#define ATOMIC_ADD __sync_fetch_and_add
#define ATOMIC_SUB __sync_fetch_and_sub
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)

#endif

#define atomic_fetch_add __sync_fetch_and_add
#define atomic_fetch_sub __sync_fetch_add_sub
#endif // HAVE_STDATOMIC_H

#else
#endif // __cplusplus

#ifndef ATOMIC_FLAG_INIT
#define ATOMIC_FLAG_INIT { 0 }
#endif

#ifndef ATOMIC_VAR_INIT
#define ATOMIC_VAR_INIT(value) (value)
#endif

#ifndef ATOMIC_FLAG_TEST_AND_SET
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
bool ret = p->_Value;
p->_Value = 1;
return ret;
}
#endif

#ifndef ATOMIC_FLAG_CLEAR
#define ATOMIC_FLAG_CLEAR atomic_flag_clear
static inline void atomic_flag_clear(atomic_flag* p) {
p->_Value = 0;
}

#define atomic_fetch_add(p, n) *(p); *(p) += (n)
#define atomic_fetch_sub(p, n) *(p); *(p) -= (n)

#endif // __GNUC__
#endif // HAVE_STDATOMIC_H
#endif

#ifndef ATOMIC_ADD
#define ATOMIC_ADD atomic_fetch_add
#define ATOMIC_ADD(p, n) (*(p) += (n))
#endif

#ifndef ATOMIC_SUB
#define ATOMIC_SUB atomic_fetch_sub
#define ATOMIC_SUB(p, n) (*(p) -= (n))
#endif

#ifndef ATOMIC_INC
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
#define ATOMIC_INC(p) ((*(p))++)
#endif

#ifndef ATOMIC_DEC
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)
#define ATOMIC_DEC(p) ((*(p))--)
#endif

#endif // __cplusplus
typedef atomic_flag hatomic_flag_t;
#define HATOMIC_FLAG_INIT ATOMIC_FLAG_INIT
#define hatomic_flag_test_and_set ATOMIC_FLAG_TEST_AND_SET
#define hatomic_flag_clear ATOMIC_FLAG_CLEAR

typedef atomic_long hatomic_t;
#define HATOMIC_VAR_INIT ATOMIC_VAR_INIT
#define hatomic_add ATOMIC_ADD
#define hatomic_sub ATOMIC_SUB
#define hatomic_inc ATOMIC_INC
#define hatomic_dec ATOMIC_DEC

#endif // HV_ATOMIC_H_
20 changes: 10 additions & 10 deletions base/hbase.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

#include "hatomic.h"

static atomic_uint s_alloc_cnt = 0;
static atomic_uint s_free_cnt = 0;
static hatomic_t s_alloc_cnt = HATOMIC_VAR_INIT(0);
static hatomic_t s_free_cnt = HATOMIC_VAR_INIT(0);

unsigned int hv_alloc_cnt() {
long hv_alloc_cnt() {
return s_alloc_cnt;
}

unsigned int hv_free_cnt() {
long hv_free_cnt() {
return s_free_cnt;
}

void* safe_malloc(size_t size) {
ATOMIC_INC(&s_alloc_cnt);
hatomic_inc(&s_alloc_cnt);
void* ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "malloc failed!\n");
Expand All @@ -28,8 +28,8 @@ void* safe_malloc(size_t size) {
}

void* safe_realloc(void* oldptr, size_t newsize, size_t oldsize) {
ATOMIC_INC(&s_alloc_cnt);
ATOMIC_INC(&s_free_cnt);
hatomic_inc(&s_alloc_cnt);
hatomic_inc(&s_free_cnt);
void* ptr = realloc(oldptr, newsize);
if (!ptr) {
fprintf(stderr, "realloc failed!\n");
Expand All @@ -42,7 +42,7 @@ void* safe_realloc(void* oldptr, size_t newsize, size_t oldsize) {
}

void* safe_calloc(size_t nmemb, size_t size) {
ATOMIC_INC(&s_alloc_cnt);
hatomic_inc(&s_alloc_cnt);
void* ptr = calloc(nmemb, size);
if (!ptr) {
fprintf(stderr, "calloc failed!\n");
Expand All @@ -52,7 +52,7 @@ void* safe_calloc(size_t nmemb, size_t size) {
}

void* safe_zalloc(size_t size) {
ATOMIC_INC(&s_alloc_cnt);
hatomic_inc(&s_alloc_cnt);
void* ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "malloc failed!\n");
Expand All @@ -66,7 +66,7 @@ void safe_free(void* ptr) {
if (ptr) {
free(ptr);
ptr = NULL;
ATOMIC_INC(&s_free_cnt);
hatomic_inc(&s_free_cnt);
}
}

Expand Down
6 changes: 3 additions & 3 deletions base/hbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ HV_EXPORT void safe_free(void* ptr);
printd("free( %p )\tat [%s:%d:%s]\n", ptr, __FILE__, __LINE__, __FUNCTION__);\
} while(0)

HV_EXPORT unsigned int hv_alloc_cnt();
HV_EXPORT unsigned int hv_free_cnt();
HV_EXPORT long hv_alloc_cnt();
HV_EXPORT long hv_free_cnt();
static inline void hv_memcheck() {
printf("Memcheck => alloc:%u free:%u\n", hv_alloc_cnt(), hv_free_cnt());
printf("Memcheck => alloc:%ld free:%ld\n", hv_alloc_cnt(), hv_free_cnt());
}
#define HV_MEMCHECK atexit(hv_memcheck);

Expand Down
15 changes: 7 additions & 8 deletions docs/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,13 @@
- printd, printe

### hatomic.h
- atomic_bool, atomic_char, atomic_short, atomic_int, atomic_long ...
- atomic_flag
- atomic_flag_test_and_set
- atomic_flag_clear
- atomic_fetch_add
- atomic_fetch_sub
- ATOMIC_ADD, ATOMIC_SUB
- ATOMIC_INC, ATOMIC_DEC
- hatomic_flag_t, hatomic_t
- hatomic_flag_test_and_set
- hatomic_flag_clear
- hatomic_add
- hatomic_sub
- hatomic_inc
- hatomic_dec

### herr.h
- hv_strerror
Expand Down
5 changes: 5 additions & 0 deletions unittest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ target_include_directories(rmdir_p PRIVATE .. ../base)
add_executable(date date_test.c ../base/htime.c)
target_include_directories(date PRIVATE .. ../base)

add_executable(hatomic_test hatomic_test.c)
target_include_directories(hatomic_test PRIVATE .. ../base)
target_link_libraries(hatomic_test -lpthread)

add_executable(hmutex_test hmutex_test.c ../base/htime.c)
target_include_directories(hmutex_test PRIVATE .. ../base)
target_link_libraries(hmutex_test -lpthread)
Expand Down Expand Up @@ -60,6 +64,7 @@ add_custom_target(unittest DEPENDS
mkdir_p
rmdir_p
date
hatomic_test
hmutex_test
connect_test
socketpair_test
Expand Down
39 changes: 39 additions & 0 deletions unittest/hatomic_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <stdio.h>

#include "hatomic.h"
#include "hthread.h"

hatomic_flag_t flag = HATOMIC_FLAG_INIT;
hatomic_t cnt = HATOMIC_VAR_INIT(0);

HTHREAD_ROUTINE(test_hatomic_flag) {
if (!hatomic_flag_test_and_set(&flag)) {
printf("tid=%ld flag 0=>1\n", hv_gettid());
}
else {
printf("tid=%ld flag=1\n", hv_gettid());
}
return 0;
}

HTHREAD_ROUTINE(test_hatomic) {
for (int i = 0; i < 10; ++i) {
long n = hatomic_inc(&cnt);
printf("tid=%ld cnt=%ld\n", hv_gettid(), n);
hv_delay(1);
}
return 0;
}

int main() {
for (int i = 0; i < 10; ++i) {
hthread_create(test_hatomic_flag, NULL);
}

for (int i = 0; i < 10; ++i) {
hthread_create(test_hatomic, NULL);
}

hv_delay(1000);
return 0;
}
39 changes: 39 additions & 0 deletions unittest/hatomic_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <stdio.h>

#include "hatomic.h"
#include "hthread.h"

hatomic_flag_t flag = HATOMIC_FLAG_INIT;
hatomic_t cnt = HATOMIC_VAR_INIT(0);

HTHREAD_ROUTINE(test_hatomic_flag) {
if (!hatomic_flag_test_and_set(&flag)) {
printf("tid=%ld flag 0=>1\n", hv_gettid());
}
else {
printf("tid=%ld flag=1\n", hv_gettid());
}
return 0;
}

HTHREAD_ROUTINE(test_hatomic) {
for (int i = 0; i < 10; ++i) {
long n = hatomic_inc(&cnt);
printf("tid=%ld cnt=%ld\n", hv_gettid(), n);
hv_delay(1);
}
return 0;
}

int main() {
for (int i = 0; i < 10; ++i) {
hthread_create(test_hatomic_flag, NULL);
}

for (int i = 0; i < 10; ++i) {
hthread_create(test_hatomic, NULL);
}

hv_delay(1000);
return 0;
}

0 comments on commit cc79c07

Please sign in to comment.