Date: Thu, 6 Dec 2012 12:59:07 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r243949 - projects/calloutng/sys/kern Message-ID: <201212061259.qB6Cx7EN047807@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Thu Dec 6 12:59:06 2012 New Revision: 243949 URL: http://svnweb.freebsd.org/changeset/base/243949 Log: MFC r243901, r243912 with some adaptation. Modified: projects/calloutng/sys/kern/kern_timeout.c Directory Properties: projects/calloutng/ (props changed) projects/calloutng/sys/ (props changed) Modified: projects/calloutng/sys/kern/kern_timeout.c ============================================================================== --- projects/calloutng/sys/kern/kern_timeout.c Thu Dec 6 11:54:25 2012 (r243948) +++ projects/calloutng/sys/kern/kern_timeout.c Thu Dec 6 12:59:06 2012 (r243949) @@ -178,7 +178,7 @@ struct callout_cpu cc_cpu; static int timeout_cpu; void (*callout_new_inserted)(int cpu, struct bintime bt, struct bintime bt_opt) = NULL; -static struct callout * +static void softclock_call_cc(struct callout *c, struct callout_cpu *cc, int *mpcalls, int *lockcalls, int *gcalls, int direct); @@ -445,10 +445,13 @@ callout_process(struct bintime *now) */ if (tmp->c_flags & CALLOUT_DIRECT) { ++depth_dir; + cc->cc_exec_next_dir = + TAILQ_NEXT(tmp, c_links.tqe); TAILQ_REMOVE(sc, tmp, c_links.tqe); - tmp = softclock_call_cc(tmp, cc, + softclock_call_cc(tmp, cc, &mpcalls_dir, &lockcalls_dir, NULL, 1); + tmp = cc->cc_exec_next_dir; } else { TAILQ_INSERT_TAIL(&cc->cc_expireq, tmp, c_staiter); @@ -605,20 +608,16 @@ callout_cc_add(struct callout *c, struct } static void -callout_cc_del(struct callout *c, struct callout_cpu *cc, int direct) +callout_cc_del(struct callout *c, struct callout_cpu *cc) { - - if (cc->cc_exec_next_dir == c) - cc->cc_exec_next_dir = TAILQ_NEXT(c, c_links.tqe); - else if (cc->cc_exec_next == c) - cc->cc_exec_next = TAILQ_NEXT(c, c_staiter); - if (c->c_flags & CALLOUT_LOCAL_ALLOC) { - c->c_func = NULL; - SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle); - } + + if ((c->c_flags & CALLOUT_LOCAL_ALLOC) == 0) + return; + c->c_func = NULL; + SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle); } -static struct callout * +static void softclock_call_cc(struct callout *c, struct callout_cpu *cc, int *mpcalls, int *lockcalls, int *gcalls, int direct) { @@ -641,10 +640,9 @@ softclock_call_cc(struct callout *c, str static timeout_t *lastfunc; #endif - if (direct) - cc->cc_exec_next_dir = TAILQ_NEXT(c, c_links.tqe); - else - cc->cc_exec_next = TAILQ_NEXT(c, c_staiter); + KASSERT((c->c_flags & (CALLOUT_PENDING | CALLOUT_ACTIVE)) == + (CALLOUT_PENDING | CALLOUT_ACTIVE), + ("softclock_call_cc: pend|act %p %x", c, c->c_flags)); class = (c->c_lock != NULL) ? LOCK_CLASS(c->c_lock) : NULL; sharedlock = (c->c_flags & CALLOUT_SHAREDLOCK) ? 0 : 1; c_lock = c->c_lock; @@ -718,20 +716,7 @@ softclock_call_cc(struct callout *c, str class->lc_unlock(c_lock); skip: CC_LOCK(cc); - /* - * If the current callout is locally allocated (from - * timeout(9)) then put it on the freelist. - * - * Note: we need to check the cached copy of c_flags because - * if it was not local, then it's not safe to deref the - * callout pointer. - */ - if (c_flags & CALLOUT_LOCAL_ALLOC) { - KASSERT(c->c_flags == CALLOUT_LOCAL_ALLOC, - ("corrupted callout")); - c->c_func = NULL; - SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle); - } + KASSERT(cc->cc_curr == c, ("mishandled cc_curr")); cc->cc_exec_entity[direct].cc_curr = NULL; if (cc->cc_exec_entity[direct].cc_waiting) { /* @@ -740,13 +725,22 @@ skip: * If the callout was scheduled for * migration just cancel it. */ - if (cc_cme_migrating(cc, direct)) + if (cc_cme_migrating(cc, direct)) { cc_cme_cleanup(cc, direct); + + /* + * It should be assert here that the callout is not + * destroyed but that is not easy. + */ + c->c_flags &= ~CALLOUT_DFRMIGRATION; + } cc->cc_exec_entity[direct].cc_waiting = 0; CC_UNLOCK(cc); wakeup(&cc->cc_exec_entity[direct].cc_waiting); CC_LOCK(cc); } else if (cc_cme_migrating(cc, direct)) { + KASSERT((c_flags & CALLOUT_LOCAL_ALLOC) == 0, + ("Migrating legacy callout %p", c)); #ifdef SMP /* * If the callout was scheduled for @@ -759,23 +753,20 @@ skip: cc_cme_cleanup(cc, direct); /* - * Handle deferred callout stops + * It should be assert here that the callout is not destroyed + * but that is not easy. + * + * As first thing, handle deferred callout stops. */ if ((c->c_flags & CALLOUT_DFRMIGRATION) == 0) { CTR3(KTR_CALLOUT, "deferred cancelled %p func %p arg %p", c, new_func, new_arg); - callout_cc_del(c, cc, direct); - goto nextc; + callout_cc_del(c, cc); + return; } - c->c_flags &= ~CALLOUT_DFRMIGRATION; - /* - * It should be assert here that the - * callout is not destroyed but that - * is not easy. - */ new_cc = callout_cpu_switch(c, cc, new_cpu); flags = (direct) ? C_DIRECT_EXEC : 0; callout_cc_add(c, new_cc, new_time, new_func, new_arg, @@ -786,10 +777,19 @@ skip: panic("migration should not happen"); #endif } -#ifdef SMP -nextc: -#endif - return cc->cc_exec_entity[direct].cc_next; + /* + * If the current callout is locally allocated (from + * timeout(9)) then put it on the freelist. + * + * Note: we need to check the cached copy of c_flags because + * if it was not local, then it's not safe to deref the + * callout pointer. + */ + KASSERT((c_flags & CALLOUT_LOCAL_ALLOC) == 0 || + c->c_flags == CALLOUT_LOCAL_ALLOC, + ("corrupted callout")); + if (c_flags & CALLOUT_LOCAL_ALLOC) + callout_cc_del(c, cc); } /* @@ -824,17 +824,18 @@ softclock(void *arg) c = TAILQ_FIRST(&cc->cc_expireq); while (c != NULL) { ++depth; + cc->cc_exec_next = TAILQ_NEXT(c, c_staiter); TAILQ_REMOVE(&cc->cc_expireq, c, c_staiter); - c = softclock_call_cc(c, cc, &mpcalls, - &lockcalls, &gcalls, 0); + softclock_call_cc(c, cc, &mpcalls, &lockcalls, &gcalls, 0); + c = cc->cc_exec_next; } + cc->cc_exec_next = NULL; #ifdef CALLOUT_PROFILING avg_depth += (depth * 1000 - avg_depth) >> 8; avg_mpcalls += (mpcalls * 1000 - avg_mpcalls) >> 8; avg_lockcalls += (lockcalls * 1000 - avg_lockcalls) >> 8; avg_gcalls += (gcalls * 1000 - avg_gcalls) >> 8; #endif - cc->cc_exec_next = NULL; CC_UNLOCK(cc); } @@ -1198,12 +1199,17 @@ again: CTR3(KTR_CALLOUT, "cancelled %p func %p arg %p", c, c->c_func, c->c_arg); if ((c->c_flags & CALLOUT_PROCESSED) == 0) { + if (cc->cc_exec_next_dir == c) + cc->cc_exec_next_dir = TAILQ_NEXT(c, c_links.tqe); bucket = get_bucket(&c->c_time); TAILQ_REMOVE(&cc->cc_callwheel[bucket], c, c_links.tqe); - } else + } else { + if (cc->cc_exec_next == c) + cc->cc_exec_next = TAILQ_NEXT(c, c_links.tqe); TAILQ_REMOVE(&cc->cc_expireq, c, c_staiter); - callout_cc_del(c, cc, direct); + } + callout_cc_del(c, cc); CC_UNLOCK(cc); return (1);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212061259.qB6Cx7EN047807>