Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168241343
D17787.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
23 KB
Referenced Files
None
Subscribers
None
D17787.id.diff
View Options
Index: sys/kern/genoffset.c
===================================================================
--- sys/kern/genoffset.c
+++ sys/kern/genoffset.c
@@ -36,7 +36,6 @@
#include <sys/assym.h>
#include <sys/proc.h>
-OFFSYM(td_pre_epoch_prio, thread, u_char);
OFFSYM(td_priority, thread, u_char);
OFFSYM(td_epochnest, thread, u_char);
OFFSYM(td_critnest, thread, u_int);
Index: sys/kern/kern_thread.c
===================================================================
--- sys/kern/kern_thread.c
+++ sys/kern/kern_thread.c
@@ -272,6 +272,7 @@
td->td_rlqe = NULL;
EVENTHANDLER_DIRECT_INVOKE(thread_init, td);
umtx_thread_init(td);
+ epoch_thread_init(td);
td->td_kstack = 0;
td->td_sel = NULL;
return (0);
@@ -291,6 +292,7 @@
turnstile_free(td->td_turnstile);
sleepq_free(td->td_sleepqueue);
umtx_thread_fini(td);
+ epoch_thread_fini(td);
seltdfini(td);
}
Index: sys/kern/subr_epoch.c
===================================================================
--- sys/kern/subr_epoch.c
+++ sys/kern/subr_epoch.c
@@ -55,11 +55,32 @@
static MALLOC_DEFINE(M_EPOCH, "epoch", "epoch based reclamation");
+#ifdef __amd64__
+#define EPOCH_ALIGN CACHE_LINE_SIZE*2
+#else
+#define EPOCH_ALIGN CACHE_LINE_SIZE
+#endif
+
+TAILQ_HEAD (epoch_tdlist, epoch_tracker);
+typedef struct epoch_record {
+ ck_epoch_record_t er_record;
+ volatile struct epoch_tdlist er_tdlist;
+ volatile uint32_t er_gen;
+ uint32_t er_cpuid;
+} __aligned(EPOCH_ALIGN) *epoch_record_t;
+
+struct epoch {
+ struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
+ epoch_record_t e_pcpu_record;
+ int e_idx;
+ int e_flags;
+};
+
/* arbitrary --- needs benchmarking */
#define MAX_ADAPTIVE_SPIN 100
#define MAX_EPOCHS 64
-CTASSERT(sizeof(ck_epoch_entry_t) == sizeof(struct epoch_context));
+CTASSERT(sizeof(epoch_context_t) == sizeof(struct epoch_context_user));
SYSCTL_NODE(_kern, OID_AUTO, epoch, CTLFLAG_RW, 0, "epoch information");
SYSCTL_NODE(_kern_epoch, OID_AUTO, stats, CTLFLAG_RW, 0, "epoch stats");
@@ -151,11 +172,19 @@
er = zpcpu_get_cpu(epoch->e_pcpu_record, cpu);
bzero(er, sizeof(*er));
ck_epoch_register(&epoch->e_epoch, &er->er_record, NULL);
- TAILQ_INIT((struct threadlist *)(uintptr_t)&er->er_tdlist);
+ TAILQ_INIT(&er->er_tdlist);
er->er_cpuid = cpu;
}
}
+static void
+epoch_adjust_prio(struct thread *td, u_char prio)
+{
+ thread_lock(td);
+ sched_prio(td, prio);
+ thread_unlock(td);
+}
+
epoch_t
epoch_alloc(int flags)
{
@@ -191,32 +220,107 @@
free(epoch, M_EPOCH);
}
+static epoch_record_t
+epoch_currecord(epoch_t epoch)
+{
+
+ return zpcpu_get_cpu(epoch->e_pcpu_record, curcpu);
+}
+
+#define INIT_CHECK(epoch) \
+ do { \
+ if (__predict_false((epoch) == NULL)) \
+ return; \
+ } while (0)
+
void
-epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
+epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
{
+ struct epoch_record *er;
+ struct thread *td;
+
+ MPASS(cold || epoch != NULL);
+ INIT_CHECK(epoch);
+ MPASS(epoch->e_flags & EPOCH_PREEMPT);
+#ifdef EPOCH_TRACKER_DEBUG
+ et->et_magic_pre = EPOCH_MAGIC0;
+ et->et_magic_post = EPOCH_MAGIC1;
+#endif
+ td = curthread;
+ et->et_td = td;
+ td->td_epochnest++;
+ critical_enter();
+ sched_pin();
- epoch_enter_preempt(epoch, et);
+ td->td_pre_epoch_prio = td->td_priority;
+ er = epoch_currecord(epoch);
+ TAILQ_INSERT_TAIL(&er->er_tdlist, et, et_link);
+ ck_epoch_begin(&er->er_record, &et->et_section);
+ critical_exit();
}
void
-epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
+epoch_enter(epoch_t epoch)
{
+ struct thread *td;
+ epoch_record_t er;
- epoch_exit_preempt(epoch, et);
+ MPASS(cold || epoch != NULL);
+ INIT_CHECK(epoch);
+ td = curthread;
+
+ td->td_epochnest++;
+ critical_enter();
+ er = epoch_currecord(epoch);
+ ck_epoch_begin(&er->er_record, NULL);
}
void
-epoch_enter_KBI(epoch_t epoch)
+epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
{
+ struct epoch_record *er;
+ struct thread *td;
- epoch_enter(epoch);
+ INIT_CHECK(epoch);
+ td = curthread;
+ critical_enter();
+ sched_unpin();
+ MPASS(td->td_epochnest);
+ td->td_epochnest--;
+ er = epoch_currecord(epoch);
+ MPASS(epoch->e_flags & EPOCH_PREEMPT);
+ MPASS(et != NULL);
+ MPASS(et->et_td == td);
+#ifdef EPOCH_TRACKER_DEBUG
+ MPASS(et->et_magic_pre == EPOCH_MAGIC0);
+ MPASS(et->et_magic_post == EPOCH_MAGIC1);
+ et->et_magic_pre = 0;
+ et->et_magic_post = 0;
+#endif
+#ifdef INVARIANTS
+ et->et_td = (void*)0xDEADBEEF;
+#endif
+ ck_epoch_end(&er->er_record, &et->et_section);
+ TAILQ_REMOVE(&er->er_tdlist, et, et_link);
+ er->er_gen++;
+ if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
+ epoch_adjust_prio(td, td->td_pre_epoch_prio);
+ critical_exit();
}
void
-epoch_exit_KBI(epoch_t epoch)
+epoch_exit(epoch_t epoch)
{
+ struct thread *td;
+ epoch_record_t er;
- epoch_exit(epoch);
+ INIT_CHECK(epoch);
+ td = curthread;
+ MPASS(td->td_epochnest);
+ td->td_epochnest--;
+ er = epoch_currecord(epoch);
+ ck_epoch_end(&er->er_record, NULL);
+ critical_exit();
}
/*
@@ -229,7 +333,7 @@
{
epoch_record_t record;
struct thread *td, *owner, *curwaittd;
- struct epoch_thread *tdwait;
+ struct epoch_tracker *tdwait;
struct turnstile *ts;
struct lock_object *lock;
int spincount, gen;
@@ -442,12 +546,10 @@
}
void
-epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t))
+epoch_call(epoch_t epoch, epoch_context_t *ctx, epoch_cb_t callback)
{
epoch_record_t er;
- ck_epoch_entry_t *cb;
-
- cb = (void *)ctx;
+ ck_epoch_entry_t *cb = ctx;
MPASS(callback);
/* too early in boot to have epoch set up */
@@ -511,7 +613,7 @@
int
in_epoch_verbose(epoch_t epoch, int dump_onfail)
{
- struct epoch_thread *tdwait;
+ struct epoch_tracker *tdwait;
struct thread *td;
epoch_record_t er;
@@ -547,9 +649,15 @@
}
void
-epoch_adjust_prio(struct thread *td, u_char prio)
+epoch_thread_init(struct thread *td)
{
- thread_lock(td);
- sched_prio(td, prio);
- thread_unlock(td);
+
+ td->td_et = malloc(sizeof(struct epoch_tracker), M_EPOCH, M_WAITOK);
+}
+
+void
+epoch_thread_fini(struct thread *td)
+{
+
+ free(td->td_et, M_EPOCH);
}
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -610,7 +610,7 @@
}
static void
-if_destroy(epoch_context_t ctx)
+if_destroy(epoch_context_t *ctx)
{
struct ifnet *ifp;
@@ -1764,35 +1764,29 @@
void
if_addr_rlock(struct ifnet *ifp)
{
- MPASS(*(uint64_t *)&ifp->if_addr_et == 0);
- epoch_enter_preempt(net_epoch_preempt, &ifp->if_addr_et);
+
+ epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_addr_runlock(struct ifnet *ifp)
{
- epoch_exit_preempt(net_epoch_preempt, &ifp->if_addr_et);
-#ifdef INVARIANTS
- bzero(&ifp->if_addr_et, sizeof(struct epoch_tracker));
-#endif
+
+ epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_maddr_rlock(if_t ifp)
{
- MPASS(*(uint64_t *)&ifp->if_maddr_et == 0);
- epoch_enter_preempt(net_epoch_preempt, &ifp->if_maddr_et);
+ epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_maddr_runlock(if_t ifp)
{
- epoch_exit_preempt(net_epoch_preempt, &ifp->if_maddr_et);
-#ifdef INVARIANTS
- bzero(&ifp->if_maddr_et, sizeof(struct epoch_tracker));
-#endif
+ epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
}
/*
@@ -1842,7 +1836,7 @@
}
static void
-ifa_destroy(epoch_context_t ctx)
+ifa_destroy(epoch_context_t *ctx)
{
struct ifaddr *ifa;
@@ -3439,7 +3433,7 @@
}
static void
-if_destroymulti(epoch_context_t ctx)
+if_destroymulti(epoch_context_t *ctx)
{
struct ifmultiaddr *ifma;
Index: sys/net/if_lagg.h
===================================================================
--- sys/net/if_lagg.h
+++ sys/net/if_lagg.h
@@ -251,8 +251,8 @@
const struct sockaddr *, struct route *);
struct lagg_counters port_counters; /* ifp counters copy */
- CK_SLIST_ENTRY(lagg_port) lp_entries;
- struct epoch_context lp_epoch_ctx;
+ CK_SLIST_ENTRY(lagg_port) lp_entries;
+ epoch_context_t lp_epoch_ctx;
};
extern struct mbuf *(*lagg_input_p)(struct ifnet *, struct mbuf *);
Index: sys/net/if_lagg.c
===================================================================
--- sys/net/if_lagg.c
+++ sys/net/if_lagg.c
@@ -805,7 +805,7 @@
#endif
static void
-lagg_port_destroy_cb(epoch_context_t ec)
+lagg_port_destroy_cb(epoch_context_t *ec)
{
struct lagg_port *lp;
struct ifnet *ifp;
Index: sys/net/if_llatbl.h
===================================================================
--- sys/net/if_llatbl.h
+++ sys/net/if_llatbl.h
@@ -82,7 +82,7 @@
struct callout lle_timer;
struct rwlock lle_lock;
struct mtx req_mtx;
- struct epoch_context lle_epoch_ctx;
+ epoch_context_t lle_epoch_ctx;
};
#define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock)
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -380,9 +380,7 @@
* Netdump hooks to be called while dumping.
*/
struct netdump_methods *if_netdump_methods;
- struct epoch_context if_epoch_ctx;
- struct epoch_tracker if_addr_et;
- struct epoch_tracker if_maddr_et;
+ epoch_context_t if_epoch_ctx;
/*
* Spare fields to be added before branching a stable branch, so
@@ -543,7 +541,7 @@
counter_u64_t ifa_opackets;
counter_u64_t ifa_ibytes;
counter_u64_t ifa_obytes;
- struct epoch_context ifa_epoch_ctx;
+ epoch_context_t ifa_epoch_ctx;
};
struct ifaddr * ifa_alloc(size_t size, int flags);
@@ -564,7 +562,7 @@
int ifma_flags;
void *ifma_protospec; /* protocol-specific state, if any */
struct ifmultiaddr *ifma_llifma; /* pointer to ifma for ifma_lladdr */
- struct epoch_context ifma_epoch_ctx;
+ epoch_context_t ifma_epoch_ctx;
};
extern struct rwlock ifnet_rwlock;
Index: sys/net/if_vlan.c
===================================================================
--- sys/net/if_vlan.c
+++ sys/net/if_vlan.c
@@ -153,7 +153,7 @@
struct vlan_mc_entry {
struct sockaddr_dl mc_addr;
CK_SLIST_ENTRY(vlan_mc_entry) mc_entries;
- struct epoch_context mc_epoch_ctx;
+ epoch_context_t mc_epoch_ctx;
};
struct ifvlan {
@@ -318,7 +318,7 @@
#define HASH(n, m) ((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m))
static void
-vlan_mc_free(struct epoch_context *ctx)
+vlan_mc_free(epoch_context_t *ctx)
{
struct vlan_mc_entry *mc = __containerof(ctx, struct vlan_mc_entry, mc_epoch_ctx);
free(mc, M_VLAN);
Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -1060,7 +1060,7 @@
* Do actual deallocation of @lle.
*/
static void
-in_lltable_destroy_lle_unlocked(epoch_context_t ctx)
+in_lltable_destroy_lle_unlocked(epoch_context_t *ctx)
{
struct llentry *lle;
Index: sys/netinet/in_pcb.h
===================================================================
--- sys/netinet/in_pcb.h
+++ sys/netinet/in_pcb.h
@@ -330,7 +330,7 @@
CK_LIST_ENTRY(inpcb) inp_list; /* (p/l) list for all PCBs for proto */
/* (e[r]) for list iteration */
/* (p[w]/l) for addition/removal */
- struct epoch_context inp_epoch_ctx;
+ epoch_context_t inp_epoch_ctx;
};
#endif /* _KERNEL */
@@ -405,7 +405,7 @@
#endif /* _SYS_SOCKETVAR_H_ */
struct inpcbport {
- struct epoch_context phd_epoch_ctx;
+ epoch_context_t phd_epoch_ctx;
CK_LIST_ENTRY(inpcbport) phd_hash;
struct inpcbhead phd_pcblist;
u_short phd_port;
@@ -413,7 +413,7 @@
struct in_pcblist {
int il_count;
- struct epoch_context il_epoch_ctx;
+ epoch_context_t il_epoch_ctx;
struct inpcbinfo *il_pcbinfo;
struct inpcb *il_inp_list[0];
};
@@ -568,7 +568,7 @@
*/
struct inpcblbgroup {
CK_LIST_ENTRY(inpcblbgroup) il_list;
- struct epoch_context il_epoch_ctx;
+ epoch_context_t il_epoch_ctx;
uint16_t il_lport; /* (c) */
u_char il_vflag; /* (c) */
u_char il_pad;
@@ -874,7 +874,7 @@
int in_pcbrele(struct inpcb *);
int in_pcbrele_rlocked(struct inpcb *);
int in_pcbrele_wlocked(struct inpcb *);
-void in_pcblist_rele_rlocked(epoch_context_t ctx);
+void in_pcblist_rele_rlocked(epoch_context_t *ctx);
void in_losing(struct inpcb *);
void in_pcbsetsolabel(struct socket *so);
int in_getpeeraddr(struct socket *so, struct sockaddr **nam);
Index: sys/netinet/in_pcb.c
===================================================================
--- sys/netinet/in_pcb.c
+++ sys/netinet/in_pcb.c
@@ -240,7 +240,7 @@
}
static void
-in_pcblbgroup_free_deferred(epoch_context_t ctx)
+in_pcblbgroup_free_deferred(epoch_context_t *ctx)
{
struct inpcblbgroup *grp;
@@ -1547,7 +1547,7 @@
}
void
-in_pcblist_rele_rlocked(epoch_context_t ctx)
+in_pcblist_rele_rlocked(epoch_context_t *ctx)
{
struct in_pcblist *il;
struct inpcb *inp;
@@ -1569,7 +1569,7 @@
}
static void
-inpcbport_free(epoch_context_t ctx)
+inpcbport_free(epoch_context_t *ctx)
{
struct inpcbport *phd;
@@ -1578,7 +1578,7 @@
}
static void
-in_pcbfree_deferred(epoch_context_t ctx)
+in_pcbfree_deferred(epoch_context_t *ctx)
{
struct inpcb *inp;
int released __unused;
@@ -2559,7 +2559,7 @@
if (phd == NULL) {
return (ENOBUFS); /* XXX */
}
- bzero(&phd->phd_epoch_ctx, sizeof(struct epoch_context));
+ bzero(&phd->phd_epoch_ctx, sizeof(phd->phd_epoch_ctx));
phd->phd_port = inp->inp_lport;
CK_LIST_INIT(&phd->phd_pcblist);
CK_LIST_INSERT_HEAD(pcbporthash, phd, phd_hash);
Index: sys/netinet/ip_var.h
===================================================================
--- sys/netinet/ip_var.h
+++ sys/netinet/ip_var.h
@@ -96,7 +96,7 @@
u_short imo_max_memberships; /* max memberships this socket */
struct in_multi **imo_membership; /* group memberships */
struct in_mfilter *imo_mfilters; /* source filters */
- struct epoch_context imo_epoch_ctx;
+ epoch_context_t imo_epoch_ctx;
};
struct ipstat {
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -2049,7 +2049,7 @@
* Do actual deallocation of @lle.
*/
static void
-in6_lltable_destroy_lle_unlocked(epoch_context_t ctx)
+in6_lltable_destroy_lle_unlocked(epoch_context_t *ctx)
{
struct llentry *lle;
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h
+++ sys/netinet6/ip6_var.h
@@ -123,7 +123,7 @@
u_short im6o_max_memberships; /* max memberships this socket */
struct in6_multi **im6o_membership; /* group memberships */
struct in6_mfilter *im6o_mfilters; /* source filters */
- struct epoch_context imo6_epoch_ctx;
+ epoch_context_t imo6_epoch_ctx;
};
/*
Index: sys/sys/epoch.h
===================================================================
--- sys/sys/epoch.h
+++ sys/sys/epoch.h
@@ -29,10 +29,24 @@
#ifndef _SYS_EPOCH_H_
#define _SYS_EPOCH_H_
+
+/*
+ * For applications that use kvm(3) and see kernel structures
+ * define a placeholder for epoch_context, and protect its
+ * size with CTASSERT in subr_epoch.c.
+ */
+struct epoch_context_user {
+ void *data[2];
+};
+
+#ifndef _KERNEL
+typedef struct epoch_context_user epoch_context_t;
+#endif
+
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/pcpu.h>
-#endif
+#include <ck_epoch.h>
struct epoch;
typedef struct epoch *epoch_t;
@@ -43,51 +57,41 @@
extern epoch_t global_epoch;
extern epoch_t global_epoch_preempt;
-struct epoch_context {
- void *data[2];
-} __aligned(sizeof(void *));
-
-typedef struct epoch_context *epoch_context_t;
-
-
struct epoch_tracker {
- void *datap[3];
#ifdef EPOCH_TRACKER_DEBUG
- int datai[5];
-#else
- int datai[1];
+#define EPOCH_MAGIC0 0xFADECAFEF00DD00D
+#define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
+ uint64_t et_magic_pre;
+#endif
+ TAILQ_ENTRY(epoch_tracker) et_link;
+ struct thread *et_td;
+ ck_epoch_section_t et_section;
+#ifdef EPOCH_TRACKER_DEBUG
+ uint64_t et_magic_post;
#endif
} __aligned(sizeof(void *));
-
typedef struct epoch_tracker *epoch_tracker_t;
+typedef struct ck_epoch_entry epoch_context_t;
+typedef void epoch_cb_t(epoch_context_t *);
+
epoch_t epoch_alloc(int flags);
void epoch_free(epoch_t epoch);
void epoch_wait(epoch_t epoch);
void epoch_wait_preempt(epoch_t epoch);
-void epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t));
+void epoch_call(epoch_t epoch, epoch_context_t *ctx, epoch_cb_t callback);
int in_epoch(epoch_t epoch);
int in_epoch_verbose(epoch_t epoch, int dump_onfail);
-#ifdef _KERNEL
DPCPU_DECLARE(int, epoch_cb_count);
DPCPU_DECLARE(struct grouptask, epoch_cb_task);
-#define EPOCH_MAGIC0 0xFADECAFEF00DD00D
-#define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
-void epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
-void epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
-void epoch_enter_KBI(epoch_t epoch);
-void epoch_exit_KBI(epoch_t epoch);
+void epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_enter(epoch_t epoch);
+void epoch_exit(epoch_t epoch);
-
-#if defined(KLD_MODULE) && !defined(KLD_TIED)
-#define epoch_enter_preempt(e, t) epoch_enter_preempt_KBI((e), (t))
-#define epoch_exit_preempt(e, t) epoch_exit_preempt_KBI((e), (t))
-#define epoch_enter(e) epoch_enter_KBI((e))
-#define epoch_exit(e) epoch_exit_KBI((e))
-#else
-#include <sys/epoch_private.h>
-#endif /* KLD_MODULE */
+void epoch_thread_init(struct thread *);
+void epoch_thread_fini(struct thread *);
#endif /* _KERNEL */
-#endif
+#endif /* _SYS_EPOCH_H_ */
Index: sys/sys/epoch_private.h
===================================================================
--- sys/sys/epoch_private.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2018, Matthew Macy <mmacy@freebsd.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _SYS_EPOCH_PRIVATE_H_
-#define _SYS_EPOCH_PRIVATE_H_
-#ifndef _KERNEL
-#error "no user serviceable parts"
-#else
-#include <ck_epoch.h>
-#include <sys/kpilite.h>
-
-#include <sys/mutex.h>
-
-extern void epoch_adjust_prio(struct thread *td, u_char prio);
-#ifndef _SYS_SYSTM_H_
-extern void critical_exit_preempt(void);
-#endif
-
-#ifdef __amd64__
-#define EPOCH_ALIGN CACHE_LINE_SIZE*2
-#else
-#define EPOCH_ALIGN CACHE_LINE_SIZE
-#endif
-
-/*
- * Standalone (_sa) routines for thread state manipulation
- */
-static __inline void
-critical_enter_sa(void *tdarg)
-{
- struct thread_lite *td;
-
- td = tdarg;
- td->td_critnest++;
- __compiler_membar();
-}
-
-static __inline void
-critical_exit_sa(void *tdarg)
-{
- struct thread_lite *td;
-
- td = tdarg;
- MPASS(td->td_critnest > 0);
- __compiler_membar();
- td->td_critnest--;
- __compiler_membar();
- if (__predict_false(td->td_owepreempt != 0))
- critical_exit_preempt();
-}
-
-typedef struct epoch_thread {
-#ifdef EPOCH_TRACKER_DEBUG
- uint64_t et_magic_pre;
-#endif
- TAILQ_ENTRY(epoch_thread) et_link; /* Epoch queue. */
- struct thread *et_td; /* pointer to thread in section */
- ck_epoch_section_t et_section; /* epoch section object */
-#ifdef EPOCH_TRACKER_DEBUG
- uint64_t et_magic_post;
-#endif
-} *epoch_thread_t;
-TAILQ_HEAD (epoch_tdlist, epoch_thread);
-
-typedef struct epoch_record {
- ck_epoch_record_t er_record;
- volatile struct epoch_tdlist er_tdlist;
- volatile uint32_t er_gen;
- uint32_t er_cpuid;
-} __aligned(EPOCH_ALIGN) *epoch_record_t;
-
-struct epoch {
- struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
- epoch_record_t e_pcpu_record;
- int e_idx;
- int e_flags;
-};
-
-static epoch_record_t
-epoch_currecord(epoch_t epoch)
-{
- return zpcpu_get_cpu(epoch->e_pcpu_record, curcpu);
-}
-
-#define INIT_CHECK(epoch) \
- do { \
- if (__predict_false((epoch) == NULL)) \
- return; \
- } while (0)
-
-static __inline void
-epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
-{
- struct epoch_record *er;
- struct epoch_thread *etd;
- struct thread_lite *td;
-
- MPASS(cold || epoch != NULL);
- INIT_CHECK(epoch);
- etd = (void *)et;
- MPASS(epoch->e_flags & EPOCH_PREEMPT);
-#ifdef EPOCH_TRACKER_DEBUG
- etd->et_magic_pre = EPOCH_MAGIC0;
- etd->et_magic_post = EPOCH_MAGIC1;
-#endif
- td = (struct thread_lite *)curthread;
- etd->et_td = (void*)td;
- td->td_epochnest++;
- critical_enter_sa(td);
- sched_pin_lite(td);
-
- td->td_pre_epoch_prio = td->td_priority;
- er = epoch_currecord(epoch);
- TAILQ_INSERT_TAIL(&er->er_tdlist, etd, et_link);
- ck_epoch_begin(&er->er_record, (ck_epoch_section_t *)&etd->et_section);
- critical_exit_sa(td);
-}
-
-static __inline void
-epoch_enter(epoch_t epoch)
-{
- struct thread_lite *td;
- epoch_record_t er;
-
- MPASS(cold || epoch != NULL);
- INIT_CHECK(epoch);
- td = (struct thread_lite *)curthread;
-
- td->td_epochnest++;
- critical_enter_sa(td);
- er = epoch_currecord(epoch);
- ck_epoch_begin(&er->er_record, NULL);
-}
-
-static __inline void
-epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
-{
- struct epoch_record *er;
- struct epoch_thread *etd;
- struct thread_lite *td;
-
- INIT_CHECK(epoch);
- td = (struct thread_lite *)curthread;
- critical_enter_sa(td);
- sched_unpin_lite(td);
- MPASS(td->td_epochnest);
- td->td_epochnest--;
- er = epoch_currecord(epoch);
- MPASS(epoch->e_flags & EPOCH_PREEMPT);
- etd = (void *)et;
- MPASS(etd != NULL);
- MPASS(etd->et_td == (struct thread *)td);
-#ifdef EPOCH_TRACKER_DEBUG
- MPASS(etd->et_magic_pre == EPOCH_MAGIC0);
- MPASS(etd->et_magic_post == EPOCH_MAGIC1);
- etd->et_magic_pre = 0;
- etd->et_magic_post = 0;
-#endif
- etd->et_td = (void*)0xDEADBEEF;
- ck_epoch_end(&er->er_record,
- (ck_epoch_section_t *)&etd->et_section);
- TAILQ_REMOVE(&er->er_tdlist, etd, et_link);
- er->er_gen++;
- if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
- epoch_adjust_prio((struct thread *)td, td->td_pre_epoch_prio);
- critical_exit_sa(td);
-}
-
-static __inline void
-epoch_exit(epoch_t epoch)
-{
- struct thread_lite *td;
- epoch_record_t er;
-
- INIT_CHECK(epoch);
- td = (struct thread_lite *)curthread;
- MPASS(td->td_epochnest);
- td->td_epochnest--;
- er = epoch_currecord(epoch);
- ck_epoch_end(&er->er_record, NULL);
- critical_exit_sa(td);
-}
-#endif /* _KERNEL */
-#endif /* _SYS_EPOCH_PRIVATE_H_ */
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -193,6 +193,7 @@
struct turnstile;
struct vm_map;
struct vm_map_entry;
+struct epoch_tracker;
/*
* XXX: Does this belong in resource.h or resourcevar.h instead?
@@ -360,6 +361,7 @@
int td_lastcpu; /* (t) Last cpu we were on. */
int td_oncpu; /* (t) Which cpu we are on. */
void *td_lkpi_task; /* LinuxKPI task struct pointer */
+ struct epoch_tracker *td_et; /* (k) compat KPI spare tracker */
int td_pmcpend;
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 3:17 AM (18 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37263710
Default Alt Text
D17787.id.diff (23 KB)
Attached To
Mode
D17787: While debugging some epoch related races at Netflix, we discoveredfew non fundamental, but annoying issues with epoch.First, the inlining makes it difficult to profile and trace epoch.At the same time, inlining doesn't effectively happens. In...
Attached
Detach File
Event Timeline
Log In to Comment