📄 sys_select.c
字号:
* In that case, it is essential to not put the event * several times on the list of delayed cancellations. */ if (w->evdata[j]->to_be_deleted == FALSE) { w->evdata[j]->next = to_delete; to_delete = w->evdata[j]; w->evdata[j]->to_be_deleted = TRUE; } return 0; } /* * Free the event's EventData structure. */ w->evdata[j]->event = INVALID_HANDLE_VALUE; w->evdata[j]->port = -1; w->evdata[j]->handler = 0; w->evdata[j]->to_be_deleted = FALSE; w->evdata[j]->next = w->first_free_evdata; w->first_free_evdata = w->evdata[j]; /* * If the event is active, we will overwrite it * with the last active event and make the hole * the first non-active event. */ if (j < w->active_events) { w->active_events--; w->events[j] = w->events[w->active_events]; w->evdata[j] = w->evdata[w->active_events]; j = w->active_events; } /* * Overwrite the event (or the hole created above) * with the last event in the array. */ w->total_events--; w->events[j] = w->events[w->total_events]; w->evdata[j] = w->evdata[w->total_events];#ifdef DEBUG w->events[w->total_events] = (HANDLE) CleanLandFill; w->evdata[w->total_events] = (EventData *) CleanLandFill; consistency_check(w);#endif result = 0; break; } } } return result;}void win_check_io(int wait){ register int i; int n; EventData* ev; /* * If there is no I/O events ready and if we were asked to wait, * wait for the event until the next timer expires. */ if (wait && !sys_io_ready) { SysTimeval tv; DWORD timeout; HANDLE harr[2] = {event_io_ready}; int num_h = 1; erts_time_remaining(&tv); timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000; if (erts_service_event != NULL) { harr[num_h++] = erts_service_event; } WaitForMultipleObjects(num_h, harr, FALSE, timeout); } /* Poll the service event to see if we're to exit. */ if (erts_service_event != NULL && WaitForSingleObject(erts_service_event, 0) == WAIT_OBJECT_0) { erl_exit(0,""); } /* * Deliver the current time and get out of here if there are no * I/O events ready (meaning that a timer has expired). */ if (!sys_io_ready) { erts_deliver_time(); return; } /* * Since we are still here, we know that there one or more events * are ready. Find out which they are. Since stopping the waiters * involves context switches, we don't want to do sys_deliver_time() * until waiters are stopped. */ STOP_WAITERS(); sys_io_ready = 0; ResetEvent(event_io_ready); n = num_waiters; /* Essential; so that we won't iterate over * a newly inserted waiter. */ erts_deliver_time(); in_win_check_io = TRUE; for (i = 0; i < n; i++) { Waiter* w = waiter[i]; int j; int first; int last;#ifdef DEBUG consistency_check(w);#endif /* * The following code is essential to make sure that insertions * caused by calls to driver_select() from any of the rotines below * will work. Picking up "first" and "last" makes sure that we * won't iterate over any new entries. Setting w->active_events * makes sure set_driver_select() will insert the new entries * at the end without moving old entries. */ first = w->active_events; last = w->total_events; w->active_events = w->total_events; /* * Now call the routines for all selected events. * * Deletions and the macros STOP and START macros for waiters will * be disabled while the callbacks are active. */ for (j = first; j < last; j++) { ASSERT(w->evdata[j]->port != -1); ASSERT(w->events[j] != INVALID_HANDLE_VALUE); (*(w->evdata[j]->handler))(w->evdata[j]->port, (int) w->events[j]); } w->active_events = w->total_events; /* In case something was inserted. */#ifdef DEBUG consistency_check(w);#endif } in_win_check_io = FALSE; /* * If any of the routines above called driver_select() to cancel * a selection, these cancellations will be done now. */ while ((ev = to_delete) != NULL) { to_delete = ev->next; /* Essential to get the pointer before * the cancellation, before the struct * will be put into the free list. */ DEBUGF(("Delayed cancellation of 0x%x\n", ev->event)); cancel_driver_select(ev->event); } START_WAITERS();}static void my_do_break(int dummy1, int dummy2){ do_break();}BOOL WINAPI ctrl_handler_ignore_break(DWORD dwCtrlType){ switch (dwCtrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: return TRUE; break; case CTRL_LOGOFF_EVENT: if (nohup) return TRUE; /* else pour through... */ case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: erl_exit(0, ""); break; } return TRUE;}void erts_set_ignore_break(void) { ConSetCtrlHandler(ctrl_handler_ignore_break); SetConsoleCtrlHandler(ctrl_handler_ignore_break, TRUE);}BOOL WINAPI ctrl_handler_replace_intr(DWORD dwCtrlType){ switch (dwCtrlType) { case CTRL_C_EVENT: return FALSE; case CTRL_BREAK_EVENT: SetEvent(break_event); break; case CTRL_LOGOFF_EVENT: if (nohup) return TRUE; /* else pour through... */ case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: erl_exit(0, ""); break; } return TRUE;}/* Don't use ctrl-c for break handler but let it be used by the shell instead (see user_drv.erl) */void erts_replace_intr(void) { ConSetCtrlHandler(ctrl_handler_replace_intr); SetConsoleCtrlHandler(ctrl_handler_replace_intr, TRUE);}BOOL WINAPI ctrl_handler(DWORD dwCtrlType){ switch (dwCtrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: SetEvent(break_event); break; case CTRL_LOGOFF_EVENT: if (nohup) return TRUE; /* else pour through... */ case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: erl_exit(0, ""); break; } return TRUE;}void init_break_handler(){ ConSetCtrlHandler(ctrl_handler); SetConsoleCtrlHandler(ctrl_handler, TRUE);}#ifdef DEBUGstatic void *debug_alloc(ErtsAlcType_t type, Uint size){ void* p = erts_alloc(type, size); memset(p, CleanLandFill, size); return p;}static void *debug_realloc(ErtsAlcType_t type, void *ptr, Uint prev_size, Uint size){ void *p; size_t fill_size; void *fill_ptr; if (prev_size > size) { size_t fill_size = (size_t) (prev_size - size); void *fill_ptr = (void *) (((char *) p) + size); memset(fill_ptr, NoMansLandFill, fill_size); } p = erts_realloc(type, ptr, size); if (size > prev_size) { size_t fill_size = (size_t) (size - prev_size); void *fill_ptr = (void *) (((char *) p) + prev_size); memset(fill_ptr, CleanLandFill, fill_size); } return p;}#endifstatic void new_waiter(void){ register Waiter* w; DWORD tid; /* Id for thread. */ HANDLE thread; int i; if (num_waiters == allocated_waiters) { Uint old_size = sizeof(Waiter *)*allocated_waiters; allocated_waiters += 64; waiter = SEL_REALLOC(ERTS_ALC_T_WAITER_OBJ, (void *) waiter, old_size, sizeof(Waiter *)*allocated_waiters); } /* if (num_waiters == MAXIMUM_WAIT_OBJECTS) { erl_exit(1, "Can't wait for more than %d events", MAXIMUM_WAIT_OBJECTS * MAXIMUM_WAIT_OBJECTS); } */ w = (Waiter *) SEL_ALLOC(ERTS_ALC_T_WAITER_OBJ, sizeof(Waiter)); waiter[num_waiters] = w; w->events[0] = CreateAutoEvent(FALSE); w->evdata[0] = NULL; /* Should never be used. */ w->active_events = 1; w->total_events = 1; /* * Form the free list of EventData objects. */ w->evdata_heap[0].port = -1; w->evdata_heap[0].next = 0; /* Last in free list. */ for (i = 1; i < MAXIMUM_WAIT_OBJECTS; i++) { w->evdata_heap[i].port = -1; w->evdata_heap[i].next = w->evdata_heap+i-1; } w->first_free_evdata = w->evdata_heap+MAXIMUM_WAIT_OBJECTS-1; /* * Create the other events. */ w->go_ahead = CreateAutoEvent(FALSE); /* * Create the thread. */ thread = (HANDLE) _beginthreadex(NULL, 0, threaded_waiter, w, 0, &tid); if (thread == (HANDLE) -1) { erl_exit(1, "Can't create more threads in driver_select()"); } CloseHandle(thread); /* * Finally, done. */ num_waiters++;}#ifdef DEBUGstatic void consistency_check(Waiter* w){ int i; ASSERT(w->active_events <= w->total_events); ASSERT(w->evdata[0] == NULL); for (i = 1; i < w->total_events; i++) { ASSERT(w->events[i] == w->evdata[i]->event); ASSERT(w->evdata[i]->port != -1); }}#endifstatic DWORD WINAPI threaded_waiter(LPVOID param){ register Waiter* w = (Waiter *) param; again: WaitForSingleObject(w->go_ahead, INFINITE); if (w->active_events == 0) { return 0; } ASSERT(w->evdata[0] == NULL); for (;;) { int i; i = WaitForMultipleObjects(w->active_events, w->events, FALSE, INFINITE); switch (i) { case WAIT_FAILED: DEBUGF(("Wait failed: %s\n", last_error())); for (i = 0; i < w->active_events; i++) { if (WaitForSingleObject(w->events[i], 0) == WAIT_FAILED) { DEBUGF(("Invalid handle: i = %d, handle = 0x%0x\n", i, w->events[i])); erl_exit(1, "Invalid handle %d in WaitForMultipleObjects", w->events[i]); } } ASSERT(0); /* Can't happen. */ break; case WAIT_OBJECT_0: signal_standby(); goto again;#ifdef DEBUG case WAIT_TIMEOUT: ASSERT(0);#endif default:#ifdef DEBUG consistency_check(w);#endif ASSERT(WAIT_OBJECT_0 < i && i < WAIT_OBJECT_0+w->active_events); if (w->active_events == w->total_events) { /* * To avoid race conditions in win_check_io(), * sys_io_ready should be set before setting the event. */ sys_io_ready = 1; SetEvent(event_io_ready); } ASSERT(i >= WAIT_OBJECT_0+1); i -= WAIT_OBJECT_0; ASSERT(i >= 1); w->active_events--; if (i < w->active_events) { HANDLE te = w->events[i]; EventData* tp = w->evdata[i]; w->events[i] = w->events[w->active_events]; w->evdata[i] = w->evdata[w->active_events]; w->events[w->active_events] = te; w->evdata[w->active_events] = tp; }#ifdef DEBUG consistency_check(w);#endif break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -