scheduler.c (3210B)
1 #include <stdlib.h> 2 #include <sys/select.h> 3 #include <sys/time.h> 4 5 #include "rxi/log.h" 6 #include "domain/scheduler.h" 7 8 #ifndef NULL 9 #define NULL ((void*)0) 10 #endif 11 12 pt_task_t *pt_first = NULL; 13 fd_set g_select_result; 14 static fd_set g_want_fds; 15 16 int domain_schedmod_pt_create(pt_task_fn fn, void *udata) { 17 if (!fn) return 1; 18 19 pt_task_t *node = calloc(1, sizeof(pt_task_t)); 20 node->next = pt_first; 21 node->func = fn; 22 node->udata = udata; 23 PT_INIT(&node->pt); 24 node->is_active = 1; 25 pt_first = node; 26 27 log_trace("scheduler: created task %p (func=%p, udata=%p), pt_first=%p", (void*)node, (void*)fn, udata, (void*)pt_first); 28 29 return 0; 30 } 31 32 int domain_schedmod_pt_remove(pt_task_t *task) { 33 if (!task) return 1; 34 35 pt_task_t *curr = pt_first; 36 pt_task_t *prev = NULL; 37 38 while (curr) { 39 if (curr == task) { 40 if (prev) { 41 prev->next = curr->next; 42 } else { 43 pt_first = curr->next; 44 } 45 free(curr); 46 return 0; 47 } 48 prev = curr; 49 curr = curr->next; 50 } 51 52 return 1; 53 } 54 55 int domain_schedmod_has_data(int *in_fds, int **out_fds) { 56 if (!in_fds || in_fds[0] == 0) return 0; 57 log_trace("domain_schedmod_has_data: in_fds[0]=%d", in_fds[0]); 58 59 for (int i = 1; i <= in_fds[0]; i++) { 60 int fd = in_fds[i]; 61 if (fd >= 0) { 62 FD_SET(fd, &g_want_fds); 63 } 64 } 65 66 if (*out_fds) free(*out_fds); 67 *out_fds = NULL; 68 69 int count = 0; 70 for (int i = 1; i <= in_fds[0]; i++) { 71 if (in_fds[i] >= 0 && FD_ISSET(in_fds[i], &g_select_result)) { 72 count++; 73 } 74 } 75 76 if (count == 0) return 0; 77 78 *out_fds = malloc(sizeof(int) * (count + 1)); 79 if (!*out_fds) return 0; 80 81 (*out_fds)[0] = count; 82 int idx = 1; 83 for (int i = 1; i <= in_fds[0]; i++) { 84 if (in_fds[i] >= 0 && FD_ISSET(in_fds[i], &g_select_result)) { 85 (*out_fds)[idx++] = in_fds[i]; 86 FD_CLR(in_fds[i], &g_select_result); 87 } 88 } 89 90 return count; 91 } 92 93 int domain_schedmod_main(void) { 94 if (!pt_first) return 0; 95 96 struct timeval tv; 97 int maxfd = -1; 98 99 for(;;) { 100 maxfd = -1; 101 for (int fd = 0; fd < FD_SETSIZE; fd++) { 102 if (FD_ISSET(fd, &g_want_fds)) { 103 if (fd > maxfd) maxfd = fd; 104 } 105 } 106 107 108 tv.tv_sec = 0; 109 tv.tv_usec = 100000; 110 select(maxfd + 1, &g_want_fds, NULL, NULL, &tv); 111 log_trace("scheduler: select returned"); 112 113 struct timeval now; 114 gettimeofday(&now, NULL); 115 int64_t timestamp = (int64_t)now.tv_sec * 1000 + now.tv_usec / 1000; 116 g_select_result = g_want_fds; 117 118 FD_ZERO(&g_want_fds); 119 120 pt_task_t *task = pt_first; 121 while (task) { 122 pt_task_t *next = task->next; 123 log_trace("scheduler: about to run task %p (func=%p, is_active=%d)", (void*)task, (void*)task->func, task->is_active); 124 task->is_active = PT_SCHEDULE(task->func(&task->pt, timestamp, task)); 125 log_trace("scheduler: task %p (func=%p) returned, is_active=%d, next=%p", (void*)task, (void*)task->func, task->is_active, (void*)next); 126 if (!task->is_active) { 127 log_trace("scheduler: removing inactive task %p", (void*)task); 128 domain_schedmod_pt_remove(task); 129 } 130 task = next; 131 } 132 log_trace("scheduler: loop done, pt_first=%p", (void*)pt_first); 133 134 if (!pt_first) break; 135 } 136 137 return 0; 138 }