scheduler.c (2254B)
1 #include "scheduler.h" 2 3 #include <stdlib.h> 4 #include <sys/select.h> 5 #include <sys/time.h> 6 7 #ifndef NULL 8 #define NULL ((void *)0) 9 #endif 10 11 pt_task_t *pt_first = NULL; 12 fd_set g_select_result; 13 static fd_set g_want_fds; 14 15 pt_task_t *sched_create(pt_task_fn fn, void *udata) { 16 if (!fn) return NULL; 17 18 pt_task_t *node = calloc(1, sizeof(pt_task_t)); 19 node->next = pt_first; 20 node->func = fn; 21 node->udata = udata; 22 node->is_active = 1; 23 pt_first = node; 24 25 return node; 26 } 27 28 int sched_remove(pt_task_t *task) { 29 if (!task) return 1; 30 31 pt_task_t *curr = pt_first; 32 pt_task_t *prev = NULL; 33 34 while (curr) { 35 if (curr == task) { 36 if (prev) { 37 prev->next = curr->next; 38 } else { 39 pt_first = curr->next; 40 } 41 free(curr); 42 return 0; 43 } 44 prev = curr; 45 curr = curr->next; 46 } 47 48 return 1; 49 } 50 51 int sched_has_data(int *in_fds) { 52 if (!in_fds || in_fds[0] == 0) return -1; 53 54 for (int i = 1; i <= in_fds[0]; i++) { 55 int fd = in_fds[i]; 56 if (fd >= 0) { 57 FD_SET(fd, &g_want_fds); 58 } 59 } 60 61 for (int i = 1; i <= in_fds[0]; i++) { 62 int fd = in_fds[i]; 63 if (fd >= 0 && FD_ISSET(fd, &g_select_result)) { 64 FD_CLR(fd, &g_select_result); 65 return fd; 66 } 67 } 68 69 return -1; 70 } 71 72 int sched_main(void) { 73 if (!pt_first) return 0; 74 75 struct timeval tv; 76 int maxfd; 77 78 for (;;) { 79 maxfd = -1; 80 for (int fd = 0; fd < FD_SETSIZE; fd++) { 81 if (FD_ISSET(fd, &g_want_fds)) { 82 if (fd > maxfd) maxfd = fd; 83 } 84 } 85 86 if (maxfd < 0) { 87 tv.tv_sec = 0; 88 tv.tv_usec = 100000; 89 select(0, NULL, NULL, NULL, &tv); 90 } else { 91 tv.tv_sec = 0; 92 tv.tv_usec = 100000; 93 select(maxfd + 1, &g_want_fds, NULL, NULL, &tv); 94 g_select_result = g_want_fds; 95 FD_ZERO(&g_want_fds); 96 } 97 98 struct timeval now; 99 gettimeofday(&now, NULL); 100 int64_t timestamp = (int64_t)now.tv_sec * 1000 + now.tv_usec / 1000; 101 102 pt_task_t *task = pt_first; 103 while (task) { 104 pt_task_t *next = task->next; 105 task->is_active = (task->func(timestamp, task) == SCHED_RUNNING); 106 if (!task->is_active) { 107 sched_remove(task); 108 } 109 task = next; 110 } 111 112 if (!pt_first) break; 113 } 114 115 return 0; 116 }