提交 93e6cec0 编写于 作者: Y YuQing

locked_timer: atomic opt for lock_index

上级 b236808a
Version 1.44 2020-11-26 Version 1.44 2020-11-29
* add test file src/tests/test_pthread_lock.c * add test file src/tests/test_pthread_lock.c
* add uniq_skiplist.[hc] * add uniq_skiplist.[hc]
* add function split_string_ex * add function split_string_ex
......
...@@ -64,8 +64,9 @@ static int locked_timer_init_slots(LockedTimer *timer) ...@@ -64,8 +64,9 @@ static int locked_timer_init_slots(LockedTimer *timer)
return 0; return 0;
} }
int locked_timer_init(LockedTimer *timer, const int slot_count, int locked_timer_init_ex(LockedTimer *timer, const int slot_count,
const int64_t current_time, const int shared_lock_count) const int64_t current_time, const int shared_lock_count,
const bool set_lock_index)
{ {
if (slot_count <= 0 || current_time <= 0) { if (slot_count <= 0 || current_time <= 0) {
return EINVAL; return EINVAL;
...@@ -73,6 +74,7 @@ int locked_timer_init(LockedTimer *timer, const int slot_count, ...@@ -73,6 +74,7 @@ int locked_timer_init(LockedTimer *timer, const int slot_count,
timer->slot_count = slot_count; timer->slot_count = slot_count;
timer->entry_shares.count = shared_lock_count; timer->entry_shares.count = shared_lock_count;
timer->entry_shares.set_lock_index = set_lock_index;
timer->base_time = current_time; //base time for slot 0 timer->base_time = current_time; //base time for slot 0
timer->current_time = current_time; timer->current_time = current_time;
return locked_timer_init_slots(timer); return locked_timer_init_slots(timer);
...@@ -111,30 +113,50 @@ void locked_timer_destroy(LockedTimer *timer) ...@@ -111,30 +113,50 @@ void locked_timer_destroy(LockedTimer *timer)
#define TIMER_GET_SLOT_POINTER(timer, expires) \ #define TIMER_GET_SLOT_POINTER(timer, expires) \
(timer->slots + TIMER_GET_SLOT_INDEX(timer, expires)) (timer->slots + TIMER_GET_SLOT_INDEX(timer, expires))
#define TIMER_ENTRY_LOCK(timer, entry) \ #define TIMER_ENTRY_LOCK(timer, lock_index) \
PTHREAD_MUTEX_LOCK(timer->entry_shares.locks + entry->lock_index) PTHREAD_MUTEX_LOCK(timer->entry_shares.locks + lock_index)
#define TIMER_ENTRY_UNLOCK(timer, entry) \ #define TIMER_ENTRY_UNLOCK(timer, lock_index) \
PTHREAD_MUTEX_UNLOCK(timer->entry_shares.locks + entry->lock_index) PTHREAD_MUTEX_UNLOCK(timer->entry_shares.locks + lock_index)
#define TIMER_ENTRY_FETCH_LOCK_INDEX(timer, entry) \
(timer->entry_shares.set_lock_index ? \
__sync_add_and_fetch(&entry->lock_index, 0) : entry->lock_index)
#define TIMER_SET_ENTRY_STATUS_AND_SINDEX(timer, slot, entry) \ #define TIMER_ENTRY_FETCH_AND_LOCK(timer, entry) \
lock_index = TIMER_ENTRY_FETCH_LOCK_INDEX(timer, entry); \
PTHREAD_MUTEX_LOCK(timer->entry_shares.locks + lock_index)
#define TIMER_SET_ENTRY_STATUS_AND_SINDEX(timer, slot, entry, lock_index) \
do { \ do { \
TIMER_ENTRY_LOCK(timer, entry); \ TIMER_ENTRY_LOCK(timer, lock_index); \
entry->status = FAST_TIMER_STATUS_NORMAL; \ entry->status = FAST_TIMER_STATUS_NORMAL; \
entry->slot_index = slot - timer->slots; \ entry->slot_index = slot - timer->slots; \
TIMER_ENTRY_UNLOCK(timer, entry); \ TIMER_ENTRY_UNLOCK(timer, lock_index); \
} while (0) } while (0)
static inline void add_entry(LockedTimer *timer, LockedTimerSlot *slot, static inline void add_entry(LockedTimer *timer, LockedTimerSlot *slot,
LockedTimerEntry *entry, const int64_t expires, const int flags) LockedTimerEntry *entry, const int64_t expires, const int flags)
{ {
int lock_index;
if ((flags & FAST_TIMER_FLAGS_SET_ENTRY_LOCK) != 0) { if ((flags & FAST_TIMER_FLAGS_SET_ENTRY_LOCK) != 0) {
/* init the entry on the first call */ if (timer->entry_shares.set_lock_index) {
entry->lock_index = ((unsigned long)entry) % int old_index;
timer->entry_shares.count; /* init the entry on the first call */
lock_index = ((unsigned long)entry) % timer->entry_shares.count;
old_index = entry->lock_index;
while (!__sync_bool_compare_and_swap(&entry->lock_index,
old_index, lock_index))
{
old_index = __sync_add_and_fetch(&entry->lock_index, 0);
}
} else {
lock_index = entry->lock_index;
}
TIMER_SET_ENTRY_STATUS_AND_SINDEX(timer, slot, entry); TIMER_SET_ENTRY_STATUS_AND_SINDEX(timer, slot, entry, lock_index);
} else {
lock_index = TIMER_ENTRY_FETCH_LOCK_INDEX(timer, entry);
} }
PTHREAD_MUTEX_LOCK(&slot->lock); PTHREAD_MUTEX_LOCK(&slot->lock);
...@@ -146,7 +168,7 @@ static inline void add_entry(LockedTimer *timer, LockedTimerSlot *slot, ...@@ -146,7 +168,7 @@ static inline void add_entry(LockedTimer *timer, LockedTimerSlot *slot,
if ((flags & FAST_TIMER_FLAGS_SET_ENTRY_LOCK) == 0) { if ((flags & FAST_TIMER_FLAGS_SET_ENTRY_LOCK) == 0) {
/* MUST set entry status and slot index in the end when entry move */ /* MUST set entry status and slot index in the end when entry move */
TIMER_SET_ENTRY_STATUS_AND_SINDEX(timer, slot, entry); TIMER_SET_ENTRY_STATUS_AND_SINDEX(timer, slot, entry, lock_index);
} }
PTHREAD_MUTEX_UNLOCK(&slot->lock); PTHREAD_MUTEX_UNLOCK(&slot->lock);
} }
...@@ -159,9 +181,11 @@ static inline int check_set_entry_status(LockedTimer *timer, ...@@ -159,9 +181,11 @@ static inline int check_set_entry_status(LockedTimer *timer,
LockedTimerEntry *entry, int *slot_index, const int new_status) LockedTimerEntry *entry, int *slot_index, const int new_status)
{ {
int result; int result;
int lock_index;
lock_index = TIMER_ENTRY_FETCH_LOCK_INDEX(timer, entry);
while (1) { while (1) {
TIMER_ENTRY_LOCK(timer, entry); TIMER_ENTRY_LOCK(timer, lock_index);
switch (entry->status) { switch (entry->status) {
case FAST_TIMER_STATUS_CLEARED: case FAST_TIMER_STATUS_CLEARED:
result = ECANCELED; result = ECANCELED;
...@@ -183,7 +207,7 @@ static inline int check_set_entry_status(LockedTimer *timer, ...@@ -183,7 +207,7 @@ static inline int check_set_entry_status(LockedTimer *timer,
break; break;
} }
*slot_index = entry->slot_index; *slot_index = entry->slot_index;
TIMER_ENTRY_UNLOCK(timer, entry); TIMER_ENTRY_UNLOCK(timer, lock_index);
if (result != EAGAIN) { if (result != EAGAIN) {
return result; return result;
...@@ -266,6 +290,7 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, ...@@ -266,6 +290,7 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time,
LockedTimerEntry *tmp; LockedTimerEntry *tmp;
LockedTimerEntry *tail; LockedTimerEntry *tail;
bool is_valid; bool is_valid;
int lock_index;
int count; int count;
if (timer->current_time >= current_time) { if (timer->current_time >= current_time) {
...@@ -283,14 +308,14 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, ...@@ -283,14 +308,14 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time,
if (entry->rehash) { if (entry->rehash) {
new_slot = TIMER_GET_SLOT_POINTER(timer, entry->expires); new_slot = TIMER_GET_SLOT_POINTER(timer, entry->expires);
if (new_slot != slot) { //check to avoid deadlock if (new_slot != slot) { //check to avoid deadlock
TIMER_ENTRY_LOCK(timer, entry); TIMER_ENTRY_FETCH_AND_LOCK(timer, entry);
if (entry->status == FAST_TIMER_STATUS_NORMAL) { if (entry->status == FAST_TIMER_STATUS_NORMAL) {
entry->status = FAST_TIMER_STATUS_MOVING; entry->status = FAST_TIMER_STATUS_MOVING;
is_valid = true; is_valid = true;
} else { } else {
is_valid = false; is_valid = false;
} }
TIMER_ENTRY_UNLOCK(timer, entry); TIMER_ENTRY_UNLOCK(timer, lock_index);
if (is_valid) { if (is_valid) {
fc_list_del_init(&entry->dlink); fc_list_del_init(&entry->dlink);
...@@ -302,14 +327,14 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, ...@@ -302,14 +327,14 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time,
} }
} }
} else { //expired } else { //expired
TIMER_ENTRY_LOCK(timer, entry); TIMER_ENTRY_FETCH_AND_LOCK(timer, entry);
if (entry->status == FAST_TIMER_STATUS_NORMAL) { if (entry->status == FAST_TIMER_STATUS_NORMAL) {
entry->status = FAST_TIMER_STATUS_TIMEOUT; entry->status = FAST_TIMER_STATUS_TIMEOUT;
is_valid = true; is_valid = true;
} else { } else {
is_valid = false; is_valid = false;
} }
TIMER_ENTRY_UNLOCK(timer, entry); TIMER_ENTRY_UNLOCK(timer, lock_index);
if (is_valid) { if (is_valid) {
fc_list_del_init(&entry->dlink); fc_list_del_init(&entry->dlink);
......
...@@ -38,7 +38,7 @@ typedef struct locked_timer_entry { ...@@ -38,7 +38,7 @@ typedef struct locked_timer_entry {
struct fc_list_head dlink; //for timer slot struct fc_list_head dlink; //for timer slot
struct locked_timer_entry *next; //for timeout chain struct locked_timer_entry *next; //for timeout chain
uint32_t slot_index; //for slot lock uint32_t slot_index; //for slot lock
uint16_t lock_index; //for entry lock volatile uint16_t lock_index; //for entry lock
uint8_t status; uint8_t status;
bool rehash; bool rehash;
} LockedTimerEntry; } LockedTimerEntry;
...@@ -49,6 +49,7 @@ typedef struct locked_timer_slot { ...@@ -49,6 +49,7 @@ typedef struct locked_timer_slot {
} LockedTimerSlot; } LockedTimerSlot;
typedef struct locked_timer_shared_locks { typedef struct locked_timer_shared_locks {
bool set_lock_index;
uint16_t count; uint16_t count;
pthread_mutex_t *locks; pthread_mutex_t *locks;
} LockedTimerSharedLocks; } LockedTimerSharedLocks;
...@@ -65,6 +66,10 @@ typedef struct locked_timer { ...@@ -65,6 +66,10 @@ typedef struct locked_timer {
extern "C" { extern "C" {
#endif #endif
#define locked_timer_init(timer, slot_count, current_time, shared_lock_count) \
locked_timer_init_ex(timer, slot_count, current_time, shared_lock_count, \
true)
#define locked_timer_add(timer, entry) \ #define locked_timer_add(timer, entry) \
locked_timer_add_ex(timer, entry, (entry)->expires, \ locked_timer_add_ex(timer, entry, (entry)->expires, \
FAST_TIMER_FLAGS_SET_ENTRY_LOCK) FAST_TIMER_FLAGS_SET_ENTRY_LOCK)
...@@ -72,8 +77,9 @@ extern "C" { ...@@ -72,8 +77,9 @@ extern "C" {
#define locked_timer_remove(timer, entry) \ #define locked_timer_remove(timer, entry) \
locked_timer_remove_ex(timer, entry, FAST_TIMER_STATUS_CLEARED) locked_timer_remove_ex(timer, entry, FAST_TIMER_STATUS_CLEARED)
int locked_timer_init(LockedTimer *timer, const int slot_count, int locked_timer_init_ex(LockedTimer *timer, const int slot_count,
const int64_t current_time, const int shared_lock_count); const int64_t current_time, const int shared_lock_count,
const bool set_lock_index);
void locked_timer_destroy(LockedTimer *timer); void locked_timer_destroy(LockedTimer *timer);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册