skynet_timer.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #include "skynet.h"
  2. #include "skynet_timer.h"
  3. #include "skynet_mq.h"
  4. #include "skynet_server.h"
  5. #include "skynet_handle.h"
  6. #include "spinlock.h"
  7. #include <time.h>
  8. #include <assert.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <stdint.h>
  12. typedef void (*timer_execute_func)(void *ud,void *arg);
  13. #define TIME_NEAR_SHIFT 8
  14. #define TIME_NEAR (1 << TIME_NEAR_SHIFT)
  15. #define TIME_LEVEL_SHIFT 6
  16. #define TIME_LEVEL (1 << TIME_LEVEL_SHIFT)
  17. #define TIME_NEAR_MASK (TIME_NEAR-1)
  18. #define TIME_LEVEL_MASK (TIME_LEVEL-1)
  19. struct timer_event {
  20. uint32_t handle;
  21. int session;
  22. };
  23. struct timer_node {
  24. struct timer_node *next;
  25. uint32_t expire;
  26. };
  27. struct link_list {
  28. struct timer_node head;
  29. struct timer_node *tail;
  30. };
  31. struct timer {
  32. struct link_list near[TIME_NEAR];
  33. struct link_list t[4][TIME_LEVEL];
  34. struct spinlock lock;
  35. uint32_t time;
  36. uint32_t starttime;
  37. uint64_t current;
  38. uint64_t current_point;
  39. };
  40. static struct timer * TI = NULL;
  41. static inline struct timer_node *
  42. link_clear(struct link_list *list) {
  43. struct timer_node * ret = list->head.next;
  44. list->head.next = 0;
  45. list->tail = &(list->head);
  46. return ret;
  47. }
  48. static inline void
  49. link(struct link_list *list,struct timer_node *node) {
  50. list->tail->next = node;
  51. list->tail = node;
  52. node->next=0;
  53. }
  54. static void
  55. add_node(struct timer *T,struct timer_node *node) {
  56. uint32_t time=node->expire;
  57. uint32_t current_time=T->time;
  58. if ((time|TIME_NEAR_MASK)==(current_time|TIME_NEAR_MASK)) {
  59. link(&T->near[time&TIME_NEAR_MASK],node);
  60. } else {
  61. int i;
  62. uint32_t mask=TIME_NEAR << TIME_LEVEL_SHIFT;
  63. for (i=0;i<3;i++) {
  64. if ((time|(mask-1))==(current_time|(mask-1))) {
  65. break;
  66. }
  67. mask <<= TIME_LEVEL_SHIFT;
  68. }
  69. link(&T->t[i][((time>>(TIME_NEAR_SHIFT + i*TIME_LEVEL_SHIFT)) & TIME_LEVEL_MASK)],node);
  70. }
  71. }
  72. static void
  73. timer_add(struct timer *T,void *arg,size_t sz,int time) {
  74. struct timer_node *node = (struct timer_node *)skynet_malloc(sizeof(*node)+sz);
  75. memcpy(node+1,arg,sz);
  76. SPIN_LOCK(T);
  77. node->expire=time+T->time;
  78. add_node(T,node);
  79. SPIN_UNLOCK(T);
  80. }
  81. static void
  82. move_list(struct timer *T, int level, int idx) {
  83. struct timer_node *current = link_clear(&T->t[level][idx]);
  84. while (current) {
  85. struct timer_node *temp=current->next;
  86. add_node(T,current);
  87. current=temp;
  88. }
  89. }
  90. static void
  91. timer_shift(struct timer *T) {
  92. int mask = TIME_NEAR;
  93. uint32_t ct = ++T->time;
  94. if (ct == 0) {
  95. move_list(T, 3, 0);
  96. } else {
  97. uint32_t time = ct >> TIME_NEAR_SHIFT;
  98. int i=0;
  99. while ((ct & (mask-1))==0) {
  100. int idx=time & TIME_LEVEL_MASK;
  101. if (idx!=0) {
  102. move_list(T, i, idx);
  103. break;
  104. }
  105. mask <<= TIME_LEVEL_SHIFT;
  106. time >>= TIME_LEVEL_SHIFT;
  107. ++i;
  108. }
  109. }
  110. }
  111. static inline void
  112. dispatch_list(struct timer_node *current) {
  113. do {
  114. struct timer_event * event = (struct timer_event *)(current+1);
  115. struct skynet_message message;
  116. message.source = 0;
  117. message.session = event->session;
  118. message.data = NULL;
  119. message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;
  120. skynet_context_push(event->handle, &message);
  121. struct timer_node * temp = current;
  122. current=current->next;
  123. skynet_free(temp);
  124. } while (current);
  125. }
  126. static inline void
  127. timer_execute(struct timer *T) {
  128. int idx = T->time & TIME_NEAR_MASK;
  129. while (T->near[idx].head.next) {
  130. struct timer_node *current = link_clear(&T->near[idx]);
  131. SPIN_UNLOCK(T);
  132. // dispatch_list don't need lock T
  133. dispatch_list(current);
  134. SPIN_LOCK(T);
  135. }
  136. }
  137. static void
  138. timer_update(struct timer *T) {
  139. SPIN_LOCK(T);
  140. // try to dispatch timeout 0 (rare condition)
  141. timer_execute(T);
  142. // shift time first, and then dispatch timer message
  143. timer_shift(T);
  144. timer_execute(T);
  145. SPIN_UNLOCK(T);
  146. }
  147. static struct timer *
  148. timer_create_timer() {
  149. struct timer *r=(struct timer *)skynet_malloc(sizeof(struct timer));
  150. memset(r,0,sizeof(*r));
  151. int i,j;
  152. for (i=0;i<TIME_NEAR;i++) {
  153. link_clear(&r->near[i]);
  154. }
  155. for (i=0;i<4;i++) {
  156. for (j=0;j<TIME_LEVEL;j++) {
  157. link_clear(&r->t[i][j]);
  158. }
  159. }
  160. SPIN_INIT(r)
  161. r->current = 0;
  162. return r;
  163. }
  164. int
  165. skynet_timeout(uint32_t handle, int time, int session) {
  166. if (time <= 0) {
  167. struct skynet_message message;
  168. message.source = 0;
  169. message.session = session;
  170. message.data = NULL;
  171. message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;
  172. if (skynet_context_push(handle, &message)) {
  173. return -1;
  174. }
  175. } else {
  176. struct timer_event event;
  177. event.handle = handle;
  178. event.session = session;
  179. timer_add(TI, &event, sizeof(event), time);
  180. }
  181. return session;
  182. }
  183. // centisecond: 1/100 second
  184. static void
  185. systime(uint32_t *sec, uint32_t *cs) {
  186. struct timespec ti;
  187. clock_gettime(CLOCK_REALTIME, &ti);
  188. *sec = (uint32_t)ti.tv_sec;
  189. *cs = (uint32_t)(ti.tv_nsec / 10000000);
  190. }
  191. static uint64_t
  192. gettime() {
  193. uint64_t t;
  194. struct timespec ti;
  195. clock_gettime(CLOCK_MONOTONIC, &ti);
  196. t = (uint64_t)ti.tv_sec * 100;
  197. t += ti.tv_nsec / 10000000;
  198. return t;
  199. }
  200. void
  201. skynet_updatetime(void) {
  202. uint64_t cp = gettime();
  203. if(cp < TI->current_point) {
  204. skynet_error(NULL, "time diff error: change from %lld to %lld", cp, TI->current_point);
  205. TI->current_point = cp;
  206. } else if (cp != TI->current_point) {
  207. uint32_t diff = (uint32_t)(cp - TI->current_point);
  208. TI->current_point = cp;
  209. TI->current += diff;
  210. int i;
  211. for (i=0;i<diff;i++) {
  212. timer_update(TI);
  213. }
  214. }
  215. }
  216. uint32_t
  217. skynet_starttime(void) {
  218. return TI->starttime;
  219. }
  220. uint64_t
  221. skynet_now(void) {
  222. return TI->current;
  223. }
  224. void
  225. skynet_timer_init(void) {
  226. TI = timer_create_timer();
  227. uint32_t current = 0;
  228. systime(&TI->starttime, &current);
  229. TI->current = current;
  230. TI->current_point = gettime();
  231. }
  232. // for profile
  233. #define NANOSEC 1000000000
  234. #define MICROSEC 1000000
  235. uint64_t
  236. skynet_thread_time(void) {
  237. struct timespec ti;
  238. clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ti);
  239. return (uint64_t)ti.tv_sec * MICROSEC + (uint64_t)ti.tv_nsec / (NANOSEC / MICROSEC);
  240. }