📄 ndet_loop.c
字号:
ntfy_assert(n == 0, "Unexpected error: gettimeofday"); /* enum_itimer.min_tv is initialized in ndet_update_itimer. */ /* Determine and set process real itimer */ ndet_update_itimer(&enum_itimer);}static struct timeval NDET_END_OF_TIME = {100000000,0}; /* For explanation of why 100000000, see ndet_check_tv */static voidndet_update_itimer(enum_itimer) NDET_ENUM_ITIMER *enum_itimer;{ u_int sigs_tmp; struct itimerval process_itimer; int n; /* Remember bits of notifier auto signal catcher */ sigs_tmp = ndet_sigs_auto; /* Zero out polling bit */ ndet_flags &= ~enum_itimer->polling_bit; ndet_sigs_auto &= ~SIG_BIT(enum_itimer->signal); /* Recompute interval timer */ enum_itimer->min_tv = NDET_END_OF_TIME; (void) ntfy_enum_conditions(ndet_clients, ndet_itimer_change, (NTFY_ENUM_DATA)enum_itimer); /* Toggle notifier auto signal catching if situation changed */ ndet_toggle_auto(sigs_tmp, enum_itimer->signal); /* Set interval timer */ timerclear(&process_itimer.it_interval); if (ndet_tv_equal(enum_itimer->min_tv, NDET_END_OF_TIME)) /* No one reset min_tv */ timerclear(&enum_itimer->min_tv); process_itimer.it_value = enum_itimer->min_tv; n = setitimer(enum_itimer->which, &process_itimer, /* SYSTEM CALL */ (struct itimerval *)0); ntfy_assert(n == 0, "Unexpected error: setitimer");}/* * Called to update global polling flags and find global minimum until next * itimer expiration. */static NTFY_ENUMndet_itimer_change(client, condition, context) NTFY_CLIENT *client; NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ struct timeval local_min; register NDET_ENUM_ITIMER *enum_itimer = (NDET_ENUM_ITIMER *)context; register NTFY_ITIMER *n_itimer; switch (condition->type) { case NTFY_VIRTUAL_ITIMER: case NTFY_REAL_ITIMER: n_itimer = condition->data.ntfy_itimer; if (condition->type != enum_itimer->type) break; /* See if polling itimer */ if (ndet_tv_polling(n_itimer->itimer.it_value)) ndet_flags |= enum_itimer->polling_bit; else { /* Figure time to go until expiration for this client */ local_min = enum_itimer->min_func(n_itimer, enum_itimer->current_tv); /* See if expired */ if (!timerisset(&local_min)) { /* * Dispatch notification, reset itimer value, * remove if nothing to wait for (returns !0). */ ndet_flags |= NDET_ITIMER_ENQ; if (ndet_itimer_expired(client, condition)) /* * Know can skip rest of clients * conditions because only one itimer * of each type is allowed per client. */ return(NTFY_ENUM_SKIP); /* Else update local_min and set time */ local_min = n_itimer->itimer.it_value; n_itimer->set_tv = enum_itimer->current_tv; } /* Figure global minimum time to go until expiration */ enum_itimer->min_tv = ndet_tv_min(local_min, enum_itimer->min_tv); /* * Tell automatic signal mechanism to watch for this * kind of interval timer expiration. */ ndet_sigs_auto |= SIG_BIT(enum_itimer->signal); } /* * Know can skip rest of clients conditions because only one * itimer of each type is allowed per client. */ return(NTFY_ENUM_SKIP); default: {} } return(NTFY_ENUM_NEXT);}/* Update every virtual itimer's set_tv field *//* ARGSUSED */static NTFY_ENUMndet_virtual_set_tv_update(client, condition, context) NTFY_CLIENT *client; NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ struct timeval *set_tv = (struct timeval *)context; if (condition->type == NTFY_VIRTUAL_ITIMER) { condition->data.ntfy_itimer->set_tv = *set_tv; /* * Know can skip rest of clients conditions because only one * itimer of each type is allowed per client. */ return(NTFY_ENUM_SKIP); } else return(NTFY_ENUM_NEXT);}static voidndet_fig_destroy_change(){ u_int sigs_auto_tmp; ndet_flags &= ~NDET_DESTROY_CHANGE; /* Remember what signals were catching for auto client */ sigs_auto_tmp = ndet_sigs_auto; /* Zero out what used to collect the data for auto client */ ndet_sigs_auto &= ~(SIG_BIT(SIGTERM)); /* Recompute SIGTERM managing */ (void) ntfy_enum_conditions(ndet_clients, ndet_destroy_change, NTFY_ENUM_DATA_NULL); /* Toggle notifier auto signal catching if situation changed */ ndet_toggle_auto(sigs_auto_tmp, SIGTERM);}static voidndet_fig_sig_change(){ register u_int sig_bit, sigs_tmp, sigs_dif; register int sig; int n; ndet_flags &= ~NDET_SIGNAL_CHANGE; /* Remember what signals were catching */ sigs_tmp = ndet_sigs_managing; /* Zero out what used to collect the data */ /* * Note: ndet_signal_catcher shouldn't look at * ndet_sigs_managing when NTFY_IN_CRITICAL. */ ndet_sigs_managing = 0; /* Recompute signals managing */ (void) ntfy_enum_conditions(ndet_clients, ndet_sig_change, NTFY_ENUM_DATA_NULL); /* Update signal catching */ sigs_dif = ndet_sigs_managing^sigs_tmp; for (sig = 1;sig < NSIG;sig++) { if ((sig_bit = SIG_BIT(sig) & sigs_dif)) { if (sig_bit & ndet_sigs_managing) { ndet_enable_sig(sig); } if (sig_bit & sigs_tmp) { /* * Don't catch this signal, * currently we are */ n = sigvec(sig, &ndet_prev_sigvec[sig], (struct sigvec *)0); /* SYSTEM CALL */ ntfy_assert(n == 0, "Unexpected error: sigvec"); } else ntfy_set_errno(NOTIFY_INTERNAL_ERROR); } }}/* * Call this routine (other than from ndet_fig_sig_change) when you need * to make sure that a signal is being caught but don't want to go through * the whole process of globally finding out who else needs it. */pkg_private voidndet_enable_sig(sig) int sig;{ if (!(SIG_BIT(sig) & ndet_sigs_managing)) { int n; /* Arrange to catch this signal, currently we are not */ n = sigvec(sig, &ndet_sigvec, &ndet_prev_sigvec[sig]); /* SYSTEM CALL */ ntfy_assert(n == 0, "Unexpected error: sigvec"); ndet_sigs_managing |= SIG_BIT(sig); }}pkg_private_data int ndet_track_sigs = 0;pkg_private void /* Should be static but there might be clients of it */ndet_signal_catcher(sig, code, scp) int sig; int code; struct sigcontext *scp;{ int oldmask = sigblock((int)ndet_sigs_managing); /* SYSTEM CALL */ void (*old_handler)() = ndet_prev_sigvec[sig].sv_handler; if (NTFY_IN_CRITICAL || ntfy_nodes_avail < NTFY_PRE_ALLOCED_MIN) { ntfy_sigs_delayed |= SIG_BIT(sig); (void) sigsetmask(oldmask); /* SYSTEM CALL */#ifdef NTFY_DEBUG if (ndet_track_sigs) (void) fprintf(stdout, "SIG caught when CRITICAL %ld\n", sig);#endif NTFY_DEBUG goto Done; } NTFY_BEGIN_INTERRUPT; ndet_signal_code = code; ndet_signal_context = scp; ndet_send_async_sigs(SIG_BIT(sig)); (void) sigsetmask(oldmask); /* SYSTEM CALL */ NTFY_END_INTERRUPT;Done: /* * Call previous handler. This feature is not part of the * notifier definition but is included as a means of reducing * compatibility problems. */ if (old_handler != SIG_DFL && old_handler != SIG_IGN) old_handler(sig, code, scp);#ifdef NTFY_DEBUG if (ndet_track_sigs) (void) fprintf(stdout, "SIG caught %ld\n", sig);#endif NTFY_DEBUG return;}pkg_private voidndet_send_delayed_sigs(){ register int sigs; int oldmask; ntfy_assert(!NTFY_IN_INTERRUPT, "Tried send delayed sig in interrupt"); ntfy_assert(!NTFY_IN_CRITICAL, "Tried send delayed sig when protected"); /* Don't need to enter critical section because blocking signals. */ /* Carefully reset ntfy_sigs_delayed so don't loose signal. */ oldmask = sigblock((int)ndet_sigs_managing); /* SYSTEM CALL */ sigs = ntfy_sigs_delayed; ntfy_sigs_delayed = 0; /* Send delayed signals */ ndet_send_async_sigs(sigs); (void) sigsetmask(oldmask); /* SYSTEM CALL */}/* Don't need to enter critical section because blocking signals when called. */static voidndet_send_async_sigs(sigs) int sigs;{ ndet_sigs_received |= sigs; (void) ntfy_paranoid_enum_conditions(ndet_clients, ndet_async_sig_send, (NTFY_ENUM_DATA)sigs);}static NTFY_ENUMndet_async_sig_send(client, condition, context) NTFY_CLIENT *client; register NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ u_int sigs = (u_int)context; if (condition->type == NTFY_ASYNC_SIGNAL && (SIG_BIT(condition->data.signal) & sigs)) { Notify_func func; /* Push condition on interposition stack */ func = nint_push_callout(client, condition); /* The notifier doesn't catch any async sigs */ (void) func(client->nclient, condition->data.signal, NOTIFY_ASYNC); /* Pop condition from interposition stack */ nint_unprotected_pop_callout(); /* Note: condition/client may be undefined now! */ } return(NTFY_ENUM_NEXT);}/* ARGSUSED */static NTFY_ENUMndet_destroy_change(client, condition, context) NTFY_CLIENT *client; NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ if (condition->type == NTFY_DESTROY) /* Tell automatic signal mechanism to watch for SIGTERM */ ndet_sigs_auto |= SIG_BIT(SIGTERM); return(NTFY_ENUM_NEXT);}/* ARGSUSED */static NTFY_ENUMndet_sig_change(client, condition, context) NTFY_CLIENT *client; NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ if ((condition->type == NTFY_SYNC_SIGNAL) || (condition->type == NTFY_ASYNC_SIGNAL)) ndet_sigs_managing |= SIG_BIT(condition->data.signal); return(NTFY_ENUM_NEXT);}pkg_private NTFY_ENUMndet_fd_send(client, condition, context) NTFY_CLIENT *client; register NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ register NDET_ENUM_SEND *enum_send = (NDET_ENUM_SEND *)context; switch (condition->type) { case NTFY_INPUT: if (FD_ISSET(condition->data.fd, &enum_send->ibits)) goto EnQ; break; case NTFY_OUTPUT: if (FD_ISSET(condition->data.fd, &enum_send->obits)) goto EnQ; break; case NTFY_EXCEPTION: if (FD_ISSET(condition->data.fd, &enum_send->ebits)) goto EnQ; break; default: {} } return(NTFY_ENUM_NEXT);EnQ: if (ndis_enqueue(client, condition) != NOTIFY_OK) /* Internal fatal error */ return(NTFY_ENUM_TERM); return(NTFY_ENUM_NEXT);}static NTFY_ENUMndet_sig_send(client, condition, context) NTFY_CLIENT *client; register NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ register NDET_ENUM_SEND *enum_send = (NDET_ENUM_SEND *)context; if (condition->type == NTFY_SYNC_SIGNAL && (SIG_BIT(condition->data.signal) & enum_send->sigs)) { /* Intercept conditions that were set by the notifier */ if (client->nclient == ndet_auto_nclient) return(ndet_auto_sig_send(client, condition, context)); else { if (ndis_enqueue(client, condition) != NOTIFY_OK) ntfy_fatal_error("Error when enq condition"); } } return(NTFY_ENUM_NEXT);}/* ARGSUSED */static NTFY_ENUMndet_poll_send(client, condition, context) NTFY_CLIENT *client; register NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ if ((condition->type == NTFY_REAL_ITIMER || condition->type == NTFY_VIRTUAL_ITIMER) && ndet_tv_polling(condition->data.ntfy_itimer->itimer.it_value)) { /* * Dispatch notification, reset itimer value, * remove if nothing to wait for an return -1 else 0. */ if (!ndet_itimer_expired(client, condition)) { /* * Avoid making system call in ndet_reset_itimer_set_tv * if just only to be polling again. */ if (!ndet_tv_polling( condition->data.ntfy_itimer->itimer.it_value)) ndet_reset_itimer_set_tv(condition); } /* * Know can skip rest of clients conditions because * only one itimer of each type is allowed per client. */ return(NTFY_ENUM_SKIP); } return(NTFY_ENUM_NEXT);}extern voidnotify_set_signal_check(tv) struct timeval tv;{ ndet_signal_check = tv;}extern struct timevalnotify_get_signal_check(){ return (ndet_signal_check);}extern intnotify_get_signal_code(){ /* Could put check to see if in interrupt (should be) */ return (ndet_signal_code);}extern struct sigcontext *notify_get_signal_context(){ /* Could put check to see if in interrupt (should be) */ return (ndet_signal_context);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -