Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Run timers in workqueue
details: https://anonhg.NetBSD.org/src/rev/ba82a26f6f7d
branches: trunk
changeset: 346370:ba82a26f6f7d
user: ozaki-r <ozaki-r%NetBSD.org@localhost>
date: Mon Jul 11 07:37:00 2016 +0000
description:
Run timers in workqueue
Timers (such as nd6_timer) typically free/destroy some data in callout
(softint). If we apply psz/psref for such data, we cannot do free/destroy
process in there because synchronization of psz/psref cannot be used in
softint. So run timer callbacks in workqueue works (normal LWP context).
Doing workqueue_enqueue a work twice (i.e., call workqueue_enqueue before
a previous task is scheduled) isn't allowed. For nd6_timer and
rt_timer_timer, this doesn't happen because callout_reset is called only
from workqueue's work. OTOH, ip{,6}flow_slowtimo's callout can be called
before its work starts and completes because the callout is periodically
called regardless of completion of the work. To avoid such a situation,
add a flag for each protocol; the flag is set true when a work is
enqueued and set false after the work finished. workqueue_enqueue is
called only if the flag is false.
Proposed on tech-net and tech-kern.
diffstat:
sys/net/route.c | 27 ++++++++++++++++++++++-----
sys/netinet/ip_flow.c | 38 ++++++++++++++++++++++++++++++++++----
sys/netinet6/ip6_flow.c | 37 +++++++++++++++++++++++++++++++++----
sys/netinet6/nd6.c | 23 ++++++++++++++++++++---
4 files changed, 109 insertions(+), 16 deletions(-)
diffs (truncated from 353 to 300 lines):
diff -r d5a19e7fc980 -r ba82a26f6f7d sys/net/route.c
--- a/sys/net/route.c Mon Jul 11 07:11:08 2016 +0000
+++ b/sys/net/route.c Mon Jul 11 07:37:00 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: route.c,v 1.169 2016/07/07 06:55:43 msaitoh Exp $ */
+/* $NetBSD: route.c,v 1.170 2016/07/11 07:37:00 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -96,7 +96,7 @@
#endif
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.169 2016/07/07 06:55:43 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.170 2016/07/11 07:37:00 ozaki-r Exp $");
#include <sys/param.h>
#ifdef RTFLUSH_DEBUG
@@ -114,6 +114,7 @@
#include <sys/ioctl.h>
#include <sys/pool.h>
#include <sys/kauth.h>
+#include <sys/workqueue.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -136,6 +137,8 @@
static struct pool rttimer_pool;
static struct callout rt_timer_ch; /* callout for rt_timer_timer() */
+struct workqueue *rt_timer_wq;
+struct work rt_timer_wk;
#ifdef RTFLUSH_DEBUG
static int _rtcache_debug = 0;
@@ -1147,14 +1150,22 @@
* that this is run when the first queue is added...
*/
+static void rt_timer_work(struct work *, void *);
+
void
rt_timer_init(void)
{
+ int error;
+
assert(rt_init_done == 0);
LIST_INIT(&rttimer_queue_head);
callout_init(&rt_timer_ch, 0);
callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
+ error = workqueue_create(&rt_timer_wq, "rt_timer",
+ rt_timer_work, NULL, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
+ if (error)
+ panic("%s: workqueue_create failed (%d)\n", __func__, error);
rt_init_done = 1;
}
@@ -1287,9 +1298,8 @@
return 0;
}
-/* ARGSUSED */
-void
-rt_timer_timer(void *arg)
+static void
+rt_timer_work(struct work *wk, void *arg)
{
struct rttimer_queue *rtq;
struct rttimer *r;
@@ -1315,6 +1325,13 @@
callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
}
+void
+rt_timer_timer(void *arg)
+{
+
+ workqueue_enqueue(rt_timer_wq, &rt_timer_wk, NULL);
+}
+
static struct rtentry *
_rtcache_init(struct route *ro, int flag)
{
diff -r d5a19e7fc980 -r ba82a26f6f7d sys/netinet/ip_flow.c
--- a/sys/netinet/ip_flow.c Mon Jul 11 07:11:08 2016 +0000
+++ b/sys/netinet/ip_flow.c Mon Jul 11 07:37:00 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_flow.c,v 1.72 2016/06/20 06:46:38 knakahara Exp $ */
+/* $NetBSD: ip_flow.c,v 1.73 2016/07/11 07:37:00 ozaki-r Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.72 2016/06/20 06:46:38 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.73 2016/07/11 07:37:00 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -45,6 +45,7 @@
#include <sys/kernel.h>
#include <sys/pool.h>
#include <sys/sysctl.h>
+#include <sys/workqueue.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -105,6 +106,10 @@
static struct ipflow *ipflow_reap(bool);
static void ipflow_sysctl_init(struct sysctllog **);
+static void ipflow_slowtimo_work(struct work *, void *);
+static struct workqueue *ipflow_slowtimo_wq;
+static struct work ipflow_slowtimo_wk;
+
static size_t
ipflow_hash(const struct ip *ip)
{
@@ -176,6 +181,12 @@
void
ipflow_init(void)
{
+ int error;
+
+ error = workqueue_create(&ipflow_slowtimo_wq, "ipflow_slowtimo",
+ ipflow_slowtimo_work, NULL, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
+ if (error != 0)
+ panic("%s: workqueue_create failed (%d)\n", __func__, error);
mutex_init(&ipflow_lock, MUTEX_DEFAULT, IPL_NONE);
@@ -419,8 +430,10 @@
return NULL;
}
-void
-ipflow_slowtimo(void)
+static bool ipflow_work_enqueued = false;
+
+static void
+ipflow_slowtimo_work(struct work *wk, void *arg)
{
struct rtentry *rt;
struct ipflow *ipf, *next_ipf;
@@ -445,12 +458,29 @@
ipf->ipf_uses = 0;
}
}
+ ipflow_work_enqueued = false;
KERNEL_UNLOCK_ONE(NULL);
mutex_exit(&ipflow_lock);
mutex_exit(softnet_lock);
}
void
+ipflow_slowtimo(void)
+{
+
+ /* Avoid enqueuing another work when one is already enqueued */
+ mutex_enter(&ipflow_lock);
+ if (ipflow_work_enqueued) {
+ mutex_exit(&ipflow_lock);
+ return;
+ }
+ ipflow_work_enqueued = true;
+ mutex_exit(&ipflow_lock);
+
+ workqueue_enqueue(ipflow_slowtimo_wq, &ipflow_slowtimo_wk, NULL);
+}
+
+void
ipflow_create(const struct route *ro, struct mbuf *m)
{
const struct ip *const ip = mtod(m, const struct ip *);
diff -r d5a19e7fc980 -r ba82a26f6f7d sys/netinet6/ip6_flow.c
--- a/sys/netinet6/ip6_flow.c Mon Jul 11 07:11:08 2016 +0000
+++ b/sys/netinet6/ip6_flow.c Mon Jul 11 07:37:00 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_flow.c,v 1.27 2016/06/20 06:46:38 knakahara Exp $ */
+/* $NetBSD: ip6_flow.c,v 1.28 2016/07/11 07:37:00 ozaki-r Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_flow.c,v 1.27 2016/06/20 06:46:38 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_flow.c,v 1.28 2016/07/11 07:37:00 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -52,6 +52,7 @@
#include <sys/kernel.h>
#include <sys/pool.h>
#include <sys/sysctl.h>
+#include <sys/workqueue.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -100,6 +101,10 @@
static struct ip6flowhead ip6flowlist;
static int ip6flow_inuse;
+static void ip6flow_slowtimo_work(struct work *, void *);
+static struct workqueue *ip6flow_slowtimo_wq;
+static struct work ip6flow_slowtimo_wk;
+
/*
* Insert an ip6flow into the list.
*/
@@ -217,7 +222,12 @@
int
ip6flow_init(int table_size)
{
- int ret;
+ int ret, error;
+
+ error = workqueue_create(&ip6flow_slowtimo_wq, "ip6flow_slowtimo",
+ ip6flow_slowtimo_work, NULL, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
+ if (error != 0)
+ panic("%s: workqueue_create failed (%d)\n", __func__, error);
mutex_init(&ip6flow_lock, MUTEX_DEFAULT, IPL_NONE);
@@ -456,8 +466,10 @@
return ip6f;
}
+static bool ip6flow_work_enqueued = false;
+
void
-ip6flow_slowtimo(void)
+ip6flow_slowtimo_work(struct work *wk, void *arg)
{
struct ip6flow *ip6f, *next_ip6f;
@@ -478,12 +490,29 @@
ip6f->ip6f_forwarded = 0;
}
}
+ ip6flow_work_enqueued = false;
KERNEL_UNLOCK_ONE(NULL);
mutex_exit(&ip6flow_lock);
mutex_exit(softnet_lock);
}
+void
+ip6flow_slowtimo(void)
+{
+
+ /* Avoid enqueuing another work when one is already enqueued */
+ mutex_enter(&ip6flow_lock);
+ if (ip6flow_work_enqueued) {
+ mutex_exit(&ip6flow_lock);
+ return;
+ }
+ ip6flow_work_enqueued = true;
+ mutex_exit(&ip6flow_lock);
+
+ workqueue_enqueue(ip6flow_slowtimo_wq, &ip6flow_slowtimo_wk, NULL);
+}
+
/*
* We have successfully forwarded a packet using the normal
* IPv6 stack. Now create/update a flow.
diff -r d5a19e7fc980 -r ba82a26f6f7d sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c Mon Jul 11 07:11:08 2016 +0000
+++ b/sys/netinet6/nd6.c Mon Jul 11 07:37:00 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6.c,v 1.202 2016/07/07 09:32:03 ozaki-r Exp $ */
+/* $NetBSD: nd6.c,v 1.203 2016/07/11 07:37:00 ozaki-r Exp $ */
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.202 2016/07/07 09:32:03 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.203 2016/07/11 07:37:00 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -56,6 +56,7 @@
#include <sys/syslog.h>
#include <sys/queue.h>
#include <sys/cprng.h>
+#include <sys/workqueue.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -113,10 +114,13 @@
static void nd6_free(struct llentry *, int);
static void nd6_llinfo_timer(void *);
static void nd6_timer(void *);
Home |
Main Index |
Thread Index |
Old Index