Changeset 740 for vendor/current/source3/lib/events.c
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/lib/events.c
r594 r740 20 20 21 21 #include "includes.h" 22 #include <tevent_internal.h> 23 24 void event_fd_set_writeable(struct tevent_fd *fde) 25 { 26 TEVENT_FD_WRITEABLE(fde); 27 } 28 29 void event_fd_set_not_writeable(struct tevent_fd *fde) 30 { 31 TEVENT_FD_NOT_WRITEABLE(fde); 32 } 33 34 void event_fd_set_readable(struct tevent_fd *fde) 35 { 36 TEVENT_FD_READABLE(fde); 37 } 38 39 void event_fd_set_not_readable(struct tevent_fd *fde) 40 { 41 TEVENT_FD_NOT_READABLE(fde); 42 } 43 44 /* 45 * Return if there's something in the queue 46 */ 47 48 bool event_add_to_select_args(struct tevent_context *ev, 49 const struct timeval *now, 50 fd_set *read_fds, fd_set *write_fds, 51 struct timeval *timeout, int *maxfd) 22 #include "lib/tevent/tevent_internal.h" 23 #include "../lib/util/select.h" 24 #include "system/select.h" 25 26 struct tevent_poll_private { 27 /* 28 * Index from file descriptor into the pollfd array 29 */ 30 int *pollfd_idx; 31 32 /* 33 * Cache for s3_event_loop_once to avoid reallocs 34 */ 35 struct pollfd *pfds; 36 }; 37 38 static struct tevent_poll_private *tevent_get_poll_private( 39 struct tevent_context *ev) 40 { 41 struct tevent_poll_private *state; 42 43 state = (struct tevent_poll_private *)ev->additional_data; 44 if (state == NULL) { 45 state = TALLOC_ZERO_P(ev, struct tevent_poll_private); 46 ev->additional_data = (void *)state; 47 if (state == NULL) { 48 DEBUG(10, ("talloc failed\n")); 49 } 50 } 51 return state; 52 } 53 54 static void count_fds(struct tevent_context *ev, 55 int *pnum_fds, int *pmax_fd) 52 56 { 53 57 struct tevent_fd *fde; 54 struct timeval diff; 55 bool ret = false; 58 int num_fds = 0; 59 int max_fd = 0; 60 61 for (fde = ev->fd_events; fde != NULL; fde = fde->next) { 62 if (fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) { 63 num_fds += 1; 64 if (fde->fd > max_fd) { 65 max_fd = fde->fd; 66 } 67 } 68 } 69 *pnum_fds = num_fds; 70 *pmax_fd = max_fd; 71 } 72 73 bool event_add_to_poll_args(struct tevent_context *ev, TALLOC_CTX *mem_ctx, 74 struct pollfd **pfds, int *pnum_pfds, 75 int *ptimeout) 76 { 77 struct tevent_poll_private *state; 78 struct tevent_fd *fde; 79 int i, num_fds, max_fd, num_pollfds, idx_len; 80 struct pollfd *fds; 81 struct timeval now, diff; 82 int timeout; 83 84 state = tevent_get_poll_private(ev); 85 if (state == NULL) { 86 return false; 87 } 88 count_fds(ev, &num_fds, &max_fd); 89 90 idx_len = max_fd+1; 91 92 if (talloc_array_length(state->pollfd_idx) < idx_len) { 93 state->pollfd_idx = TALLOC_REALLOC_ARRAY( 94 state, state->pollfd_idx, int, idx_len); 95 if (state->pollfd_idx == NULL) { 96 DEBUG(10, ("talloc_realloc failed\n")); 97 return false; 98 } 99 } 100 101 fds = *pfds; 102 num_pollfds = *pnum_pfds; 103 104 /* 105 * The +1 is for the sys_poll calling convention. It expects 106 * an array 1 longer for the signal pipe 107 */ 108 109 if (talloc_array_length(fds) < num_pollfds + num_fds + 1) { 110 fds = TALLOC_REALLOC_ARRAY(mem_ctx, fds, struct pollfd, 111 num_pollfds + num_fds + 1); 112 if (fds == NULL) { 113 DEBUG(10, ("talloc_realloc failed\n")); 114 return false; 115 } 116 } 117 118 memset(&fds[num_pollfds], 0, sizeof(struct pollfd) * num_fds); 119 120 /* 121 * This needs tuning. We need to cope with multiple fde's for a file 122 * descriptor. The problem is that we need to re-use pollfd_idx across 123 * calls for efficiency. One way would be a direct bitmask that might 124 * be initialized quicker, but our bitmap_init implementation is 125 * pretty heavy-weight as well. 126 */ 127 for (i=0; i<idx_len; i++) { 128 state->pollfd_idx[i] = -1; 129 } 56 130 57 131 for (fde = ev->fd_events; fde; fde = fde->next) { 58 if (fde->fd < 0 || fde->fd >= FD_SETSIZE) { 59 /* We ignore here, as it shouldn't be 60 possible to add an invalid fde->fd 61 but we don't want FD_SET to see an 62 invalid fd. */ 132 struct pollfd *pfd; 133 134 if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) == 0) { 63 135 continue; 64 136 } 65 137 138 if (state->pollfd_idx[fde->fd] == -1) { 139 /* 140 * We haven't seen this fd yet. Allocate a new pollfd. 141 */ 142 state->pollfd_idx[fde->fd] = num_pollfds; 143 pfd = &fds[num_pollfds]; 144 num_pollfds += 1; 145 } else { 146 /* 147 * We have already seen this fd. OR in the flags. 148 */ 149 pfd = &fds[state->pollfd_idx[fde->fd]]; 150 } 151 152 pfd->fd = fde->fd; 153 66 154 if (fde->flags & EVENT_FD_READ) { 67 FD_SET(fde->fd, read_fds); 68 ret = true; 155 pfd->events |= (POLLIN|POLLHUP); 69 156 } 70 157 if (fde->flags & EVENT_FD_WRITE) { 71 FD_SET(fde->fd, write_fds); 72 ret = true; 73 } 74 75 if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) 76 && (fde->fd > *maxfd)) { 77 *maxfd = fde->fd; 78 } 79 } 158 pfd->events |= POLLOUT; 159 } 160 } 161 *pfds = fds; 162 *pnum_pfds = num_pollfds; 80 163 81 164 if (ev->immediate_events != NULL) { 82 *timeout = timeval_zero(); 83 return true; 84 } 85 165 *ptimeout = 0; 166 return true; 167 } 86 168 if (ev->timer_events == NULL) { 87 return ret; 88 } 89 90 diff = timeval_until(now, &ev->timer_events->next_event); 91 *timeout = timeval_min(timeout, &diff); 169 *ptimeout = MIN(*ptimeout, INT_MAX); 170 return true; 171 } 172 173 now = timeval_current(); 174 diff = timeval_until(&now, &ev->timer_events->next_event); 175 timeout = timeval_to_msec(diff); 176 177 if (timeout < *ptimeout) { 178 *ptimeout = timeout; 179 } 92 180 93 181 return true; 94 182 } 95 183 96 bool run_events(struct tevent_context *ev, 97 int selrtn, fd_set *read_fds, fd_set *write_fds) 98 { 184 bool run_events_poll(struct tevent_context *ev, int pollrtn, 185 struct pollfd *pfds, int num_pfds) 186 { 187 struct tevent_poll_private *state; 188 int *pollfd_idx; 99 189 struct tevent_fd *fde; 100 190 struct timeval now; … … 140 230 } 141 231 142 if ( selrtn <= 0) {232 if (pollrtn <= 0) { 143 233 /* 144 234 * No fd ready … … 147 237 } 148 238 239 state = (struct tevent_poll_private *)ev->additional_data; 240 pollfd_idx = state->pollfd_idx; 241 149 242 for (fde = ev->fd_events; fde; fde = fde->next) { 243 struct pollfd *pfd; 150 244 uint16 flags = 0; 151 245 152 if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ; 153 if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE; 154 246 if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) == 0) { 247 continue; 248 } 249 250 if (pollfd_idx[fde->fd] >= num_pfds) { 251 DEBUG(1, ("internal error: pollfd_idx[fde->fd] (%d) " 252 ">= num_pfds (%d)\n", pollfd_idx[fde->fd], 253 num_pfds)); 254 return false; 255 } 256 pfd = &pfds[pollfd_idx[fde->fd]]; 257 258 if (pfd->fd != fde->fd) { 259 DEBUG(1, ("internal error: pfd->fd (%d) " 260 "!= fde->fd (%d)\n", pollfd_idx[fde->fd], 261 num_pfds)); 262 return false; 263 } 264 265 if (pfd->revents & (POLLHUP|POLLERR)) { 266 /* If we only wait for EVENT_FD_WRITE, we 267 should not tell the event handler about it, 268 and remove the writable flag, as we only 269 report errors when waiting for read events 270 to match the select behavior. */ 271 if (!(fde->flags & EVENT_FD_READ)) { 272 EVENT_FD_NOT_WRITEABLE(fde); 273 continue; 274 } 275 flags |= EVENT_FD_READ; 276 } 277 278 if (pfd->revents & POLLIN) { 279 flags |= EVENT_FD_READ; 280 } 281 if (pfd->revents & POLLOUT) { 282 flags |= EVENT_FD_WRITE; 283 } 155 284 if (flags & fde->flags) { 156 DLIST_DEMOTE(ev->fd_events, fde, struct tevent_fd *);285 DLIST_DEMOTE(ev->fd_events, fde, struct tevent_fd); 157 286 fde->handler(ev, fde, flags, fde->private_data); 158 287 return true; … … 162 291 return false; 163 292 } 164 165 293 166 294 struct timeval *get_timed_events_timeout(struct tevent_context *ev, … … 188 316 static int s3_event_loop_once(struct tevent_context *ev, const char *location) 189 317 { 190 struct t imeval now, to;191 fd_set r_fds, w_fds;192 int maxfd = 0;318 struct tevent_poll_private *state; 319 int timeout; 320 int num_pfds; 193 321 int ret; 194 322 195 FD_ZERO(&r_fds); 196 FD_ZERO(&w_fds); 197 198 to.tv_sec = 9999; /* Max timeout */ 199 to.tv_usec = 0; 200 201 if (run_events(ev, 0, NULL, NULL)) { 323 timeout = INT_MAX; 324 325 state = tevent_get_poll_private(ev); 326 if (state == NULL) { 327 errno = ENOMEM; 328 return -1; 329 } 330 331 if (run_events_poll(ev, 0, NULL, 0)) { 202 332 return 0; 203 333 } 204 334 205 GetTimeOfDay(&now);206 207 if (!event_add_to_select_args(ev, &now, &r_fds, &w_fds, &to, &maxfd)) {335 num_pfds = 0; 336 if (!event_add_to_poll_args(ev, state, 337 &state->pfds, &num_pfds, &timeout)) { 208 338 return -1; 209 339 } 210 340 211 ret = sys_select(maxfd+1, &r_fds, &w_fds, NULL, &to); 212 341 ret = sys_poll(state->pfds, num_pfds, timeout); 213 342 if (ret == -1 && errno != EINTR) { 214 343 tevent_debug(ev, TEVENT_DEBUG_FATAL, 215 " sys_select() failed: %d:%s\n",344 "poll() failed: %d:%s\n", 216 345 errno, strerror(errno)); 217 346 return -1; 218 347 } 219 348 220 run_events (ev, ret, &r_fds, &w_fds);349 run_events_poll(ev, ret, state->pfds, num_pfds); 221 350 return 0; 222 }223 224 void event_context_reinit(struct tevent_context *ev)225 {226 tevent_common_context_destructor(ev);227 return;228 351 } 229 352
Note:
See TracChangeset
for help on using the changeset viewer.