diff --git a/skynet-src/skynet_timer.c b/skynet-src/skynet_timer.c index 489f8d09..32b71f77 100644 --- a/skynet-src/skynet_timer.c +++ b/skynet-src/skynet_timer.c @@ -16,6 +16,9 @@ typedef void (*timer_execute_func)(void *ud,void *arg); +#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {} +#define UNLOCK(q) __sync_lock_release(&(q)->lock); + #define TIME_NEAR_SHIFT 8 #define TIME_NEAR (1 << TIME_NEAR_SHIFT) #define TIME_LEVEL_SHIFT 6 @@ -50,8 +53,7 @@ struct timer { static struct timer * TI = NULL; static inline struct timer_node * -link_clear(struct link_list *list) -{ +link_clear(struct link_list *list) { struct timer_node * ret = list->head.next; list->head.next = 0; list->tail = &(list->head); @@ -60,23 +62,20 @@ link_clear(struct link_list *list) } static inline void -link(struct link_list *list,struct timer_node *node) -{ +link(struct link_list *list,struct timer_node *node) { list->tail->next = node; list->tail = node; node->next=0; } static void -add_node(struct timer *T,struct timer_node *node) -{ +add_node(struct timer *T,struct timer_node *node) { int time=node->expire; int current_time=T->time; if ((time|TIME_NEAR_MASK)==(current_time|TIME_NEAR_MASK)) { link(&T->near[time&TIME_NEAR_MASK],node); - } - else { + } else { int i; int mask=TIME_NEAR << TIME_LEVEL_SHIFT; for (i=0;i<3;i++) { @@ -90,21 +89,21 @@ add_node(struct timer *T,struct timer_node *node) } static void -timer_add(struct timer *T,void *arg,size_t sz,int time) -{ +timer_add(struct timer *T,void *arg,size_t sz,int time) { struct timer_node *node = (struct timer_node *)skynet_malloc(sizeof(*node)+sz); memcpy(node+1,arg,sz); - while (__sync_lock_test_and_set(&T->lock,1)) {}; + LOCK(T); node->expire=time+T->time; add_node(T,node); - __sync_lock_release(&T->lock); + UNLOCK(T); } static void timer_shift(struct timer *T) { + LOCK(T); int mask = TIME_NEAR; int time = (++T->time) >> TIME_NEAR_SHIFT; int i=0; @@ -125,50 +124,57 @@ timer_shift(struct timer *T) { time >>= TIME_LEVEL_SHIFT; ++i; } + UNLOCK(T); +} + +static inline void +dispatch_list(struct timer_node *current) { + do { + struct timer_event * event = (struct timer_event *)(current+1); + struct skynet_message message; + message.source = 0; + message.session = event->session; + message.data = NULL; + message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT; + + skynet_context_push(event->handle, &message); + + struct timer_node * temp = current; + current=current->next; + skynet_free(temp); + } while (current); } static inline void timer_execute(struct timer *T) { + LOCK(T); int idx = T->time & TIME_NEAR_MASK; while (T->near[idx].head.next) { struct timer_node *current = link_clear(&T->near[idx]); - - do { - struct timer_event * event = (struct timer_event *)(current+1); - struct skynet_message message; - message.source = 0; - message.session = event->session; - message.data = NULL; - message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT; - - skynet_context_push(event->handle, &message); - - struct timer_node * temp = current; - current=current->next; - skynet_free(temp); - } while (current); + UNLOCK(T); + // dispatch_list don't need lock T + dispatch_list(current); + LOCK(T); } + + UNLOCK(T); } static void -timer_update(struct timer *T) -{ - while (__sync_lock_test_and_set(&T->lock,1)) {}; - +timer_update(struct timer *T) { // try to dispatch timeout 0 (rare condition) timer_execute(T); // shift time first, and then dispatch timer message timer_shift(T); + timer_execute(T); - __sync_lock_release(&T->lock); } static struct timer * -timer_create_timer() -{ +timer_create_timer() { struct timer *r=(struct timer *)skynet_malloc(sizeof(struct timer)); memset(r,0,sizeof(*r));