From nobody Thu Oct 24 17:14:37 2024 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4XZCFp1Ckrz5Zg1y; Thu, 24 Oct 2024 17:14:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XZCFp0j31z4cD0; Thu, 24 Oct 2024 17:14:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1729790078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6C9XKKtXrGhXJhvNcp8OVOcYIf1X78OU12iwTG86N08=; b=cwJwZr7fAANrRlKHOJXnLwTLbsvWNnv/b7EFTJ1CU3wHiiqrSGQ5EvTUCXYZdL+J9LeIf0 9ditq7t/Hjo9IIUVLfkgIt7Fuk0Kewq7VlNY5LP8OicsCuA8L7CUMTHUnmHORTcKHwin8U 5QwgLxIcC7bP5ujuwXF0zoLtiS6+oUcjj7Al/gSiCcfAkwtl37zt40PxxIccq+VK6diCpp yiow7iZVth0uhcmY78MDGYjdU8epJwol3o3uxDtgC49s5UKgmFlbHIn0jsskwxw7WQ+vPi u0PJhYOLVPCxlHHAsBRO6HYS9pDLXKcZPnlw9YKKOi9YUBSXgtNy9ccYfOT5wA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1729790078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6C9XKKtXrGhXJhvNcp8OVOcYIf1X78OU12iwTG86N08=; b=NvKJlZuHNjKPxEi9oi1QH6JgOrN7hA4L0dZzAYNCJ+nyPVhURf1hoFyzhHvq9HPKPJTnSQ gXdXMCggMTYj+/Fw929+saA2L4pT856OP3pV4+DV0ylz5MHQW1W7+3FOqgNkC6/EYDgWOV lus+IQlMy5fbKuoqgr1cayRlKlcI932UFhINt7hoYJMp5V0MHVlbRAaKdWsvqgrHpEWkQm 1XTFB4SIIloqs8dOBu0ngYlAdrWL6mbZuv0Vq9b76FtcZj8SUB2gX7l5NHFAfETBXP9jYW qp6Q1v5UlgAYPmxEdlXnI0vMdMQb1O9QdV3uS1kHDzdB24TfVpH99x4o7gKiMA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1729790078; a=rsa-sha256; cv=none; b=yUkUEdM2H4jlOL7Ug51jYL54mHpgPguDpbJrXeGuY7tlNbLVEARGcSKudOC8Mb1H1E8OEG /IARru5v7DEwP5NnvWuhGrT2TYwQye3QkWPmwWC01Nsh62zhJM19HbE8sXUdcGfPismONm cG+97nuOhpVL9FdGFJdmIfO/C8no3zPYfIEeuPTb2dG9iMjvdBt874J6C+1zJE9EeIorqJ /8fKqZOkHynIPVDQpTUFq5gEdmoIC7qIBejilRUvgUJD0wjJjC+yKhRYXaZP4V5dPE3WKV JYoR3+rTfZDQTmCdUV0T2BaBYnCjPx0jO0mn1L0IdVxhzIBavp91qffUi/HbHQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XZCFp0HlHzr3h; Thu, 24 Oct 2024 17:14:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 49OHEbiO000321; Thu, 24 Oct 2024 17:14:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 49OHEbC9000318; Thu, 24 Oct 2024 17:14:37 GMT (envelope-from git) Date: Thu, 24 Oct 2024 17:14:37 GMT Message-Id: <202410241714.49OHEbC9000318@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: efcb2ec8cb81 - main - callout: provide CALLOUT_TRYLOCK flag List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: efcb2ec8cb81ea44c58e41082c6d965f9493099f Auto-Submitted: auto-generated The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=efcb2ec8cb81ea44c58e41082c6d965f9493099f commit efcb2ec8cb81ea44c58e41082c6d965f9493099f Author: Gleb Smirnoff AuthorDate: 2024-10-24 16:58:05 +0000 Commit: Gleb Smirnoff CommitDate: 2024-10-24 17:14:03 +0000 callout: provide CALLOUT_TRYLOCK flag If a callout was initialized with the flag, then the callout(9) system will not drop the callwheel lock in softclock_call_cc() to obtain the callout lock. Instead it will use try-lock semantic to obtain the callout's lock. In case of a failure the callout will be rescheduled to the 50% of the precision value. The main benefit of such behavior is not the avoidance of the lock contention in the callout thread, but the fact that callout with such flag can be actually stopped in a safe manner, because the race window in the beginning of softclock_call_cc() is closed. Call of callout_stop() on such a callout would guarantee that nothing will be executed after callout_stop() returns, neither callout lock will be dereferenced. A callout marked as CALLOUT_TRYLOCK | CALLOUT_RETURNUNLOCKED can call callout_stop() from the callout function itself (0, a failure to stop, will be returned), then unlock the lock and then free the memory containing the callout structure. Caveat: when calling callout_stop() from outside the callout function, the return value from callout_stop() is still inconsistent. A race window at the end of softclock_call_cc() still exists, so callout_stop() may report failure to stop, which would not be true. Reviewed by: jtl, kib Differential Revision: https://reviews.freebsd.org/D45746 --- sys/kern/kern_timeout.c | 40 ++++++++++++++++++++++++++++++---------- sys/sys/callout.h | 2 +- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 699a57d51f0e..0fa1af6ef5a7 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -649,6 +649,7 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc, static callout_func_t *lastfunc; #endif + CC_LOCK_ASSERT(cc); KASSERT((c->c_iflags & CALLOUT_PENDING) == CALLOUT_PENDING, ("softclock_call_cc: pend %p %x", c, c->c_iflags)); KASSERT((c->c_flags & CALLOUT_ACTIVE) == CALLOUT_ACTIVE, @@ -671,16 +672,29 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc, cc_exec_last_func(cc, direct) = c_func; cc_exec_last_arg(cc, direct) = c_arg; cc_exec_cancel(cc, direct) = false; - CC_UNLOCK(cc); if (c_lock != NULL) { - class->lc_lock(c_lock, lock_status); - /* - * The callout may have been cancelled - * while we switched locks. - */ - if (cc_exec_cancel(cc, direct)) { - class->lc_unlock(c_lock); - goto skip; + if (c_iflags & CALLOUT_TRYLOCK) { + if (__predict_false(class->lc_trylock(c_lock, + lock_status) == 0)) { + cc_exec_curr(cc, direct) = NULL; + callout_cc_add(c, cc, + cc->cc_lastscan + c->c_precision / 2, + qmax(c->c_precision / 2, 1), c_func, c_arg, + (direct) ? C_DIRECT_EXEC : 0); + return; + } + CC_UNLOCK(cc); + } else { + CC_UNLOCK(cc); + class->lc_lock(c_lock, lock_status); + /* + * The callout may have been cancelled + * while we switched locks. + */ + if (cc_exec_cancel(cc, direct)) { + class->lc_unlock(c_lock); + goto skip; + } } /* The callout cannot be stopped now. */ cc_exec_cancel(cc, direct) = true; @@ -698,6 +712,7 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc, c, c_func, c_arg); } } else { + CC_UNLOCK(cc); #ifdef CALLOUT_PROFILING (*mpcalls)++; #endif @@ -1332,10 +1347,15 @@ void _callout_init_lock(struct callout *c, struct lock_object *lock, int flags) { KASSERT(lock != NULL, ("%s: no lock", __func__)); - KASSERT((flags & ~(CALLOUT_RETURNUNLOCKED | CALLOUT_SHAREDLOCK)) == 0, + KASSERT((flags & ~(CALLOUT_RETURNUNLOCKED | CALLOUT_SHAREDLOCK | + CALLOUT_TRYLOCK)) == 0, ("%s: bad flags %d", __func__, flags)); KASSERT(!(LOCK_CLASS(lock)->lc_flags & LC_SLEEPABLE), ("%s: callout %p has sleepable lock", __func__, c)); + KASSERT(!(flags & CALLOUT_TRYLOCK) || + (LOCK_CLASS(lock)->lc_trylock != NULL), + ("%s: CALLOUT_TRYLOCK requested for %s", + __func__, LOCK_CLASS(lock)->lc_name)); *c = (struct callout ){ .c_lock = lock, diff --git a/sys/sys/callout.h b/sys/sys/callout.h index 5d0d896b5d3b..c3350b324296 100644 --- a/sys/sys/callout.h +++ b/sys/sys/callout.h @@ -39,7 +39,7 @@ #include -#define CALLOUT_LOCAL_ALLOC 0x0001 /* was allocated from callfree */ +#define CALLOUT_TRYLOCK 0x0001 /* try semantic in softclock_call_cc */ #define CALLOUT_ACTIVE 0x0002 /* callout is currently active */ #define CALLOUT_PENDING 0x0004 /* callout is waiting for timeout */ #define CALLOUT_MPSAFE 0x0008 /* deprecated */