⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_select.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
		     * 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 + -