Module Name: src Committed By: hannken Date: Sat Mar 14 09:52:49 UTC 2015
Modified Files: src/sys/dev/sysmon: sysmon_envsys.c sysmon_envsys_events.c sysmonvar.h Log Message: Add a counter of busy events and stop enqueueing more work if a device is busy. Protect this counter with a new short time lock "sme_work_mtx" and keep "sme_mtx" as long time lock. Removes a deadlock where an active event holds "sme_mtx", the callout "sme_events_check" blocks on "sme_mtx" and callout processing stops. To generate a diff of this commit: cvs rdiff -u -r1.128 -r1.129 src/sys/dev/sysmon/sysmon_envsys.c cvs rdiff -u -r1.113 -r1.114 src/sys/dev/sysmon/sysmon_envsys_events.c cvs rdiff -u -r1.45 -r1.46 src/sys/dev/sysmon/sysmonvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/sysmon/sysmon_envsys.c diff -u src/sys/dev/sysmon/sysmon_envsys.c:1.128 src/sys/dev/sysmon/sysmon_envsys.c:1.129 --- src/sys/dev/sysmon/sysmon_envsys.c:1.128 Sun Nov 23 10:00:20 2014 +++ src/sys/dev/sysmon/sysmon_envsys.c Sat Mar 14 09:52:49 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_envsys.c,v 1.128 2014/11/23 10:00:20 ozaki-r Exp $ */ +/* $NetBSD: sysmon_envsys.c,v 1.129 2015/03/14 09:52:49 hannken Exp $ */ /*- * Copyright (c) 2007, 2008 Juan Romero Pardines. @@ -64,7 +64,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.128 2014/11/23 10:00:20 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.129 2015/03/14 09:52:49 hannken Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -485,6 +485,7 @@ sysmon_envsys_create(void) TAILQ_INIT(&sme->sme_sensors_list); LIST_INIT(&sme->sme_events_list); mutex_init(&sme->sme_mtx, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&sme->sme_work_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&sme->sme_condvar, "sme_wait"); return sme; @@ -508,6 +509,7 @@ sysmon_envsys_destroy(struct sysmon_envs TAILQ_REMOVE(&sme->sme_sensors_list, edata, sensors_head); } mutex_destroy(&sme->sme_mtx); + mutex_destroy(&sme->sme_work_mtx); cv_destroy(&sme->sme_condvar); kmem_free(sme, sizeof(*sme)); } Index: src/sys/dev/sysmon/sysmon_envsys_events.c diff -u src/sys/dev/sysmon/sysmon_envsys_events.c:1.113 src/sys/dev/sysmon/sysmon_envsys_events.c:1.114 --- src/sys/dev/sysmon/sysmon_envsys_events.c:1.113 Sun Nov 23 10:00:20 2014 +++ src/sys/dev/sysmon/sysmon_envsys_events.c Sat Mar 14 09:52:49 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_envsys_events.c,v 1.113 2014/11/23 10:00:20 ozaki-r Exp $ */ +/* $NetBSD: sysmon_envsys_events.c,v 1.114 2015/03/14 09:52:49 hannken Exp $ */ /*- * Copyright (c) 2007, 2008 Juan Romero Pardines. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.113 2014/11/23 10:00:20 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.114 2015/03/14 09:52:49 hannken Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_envsy #include <sys/mutex.h> #include <sys/kmem.h> #include <sys/callout.h> +#include <sys/syslog.h> #include <dev/sysmon/sysmonvar.h> #include <dev/sysmon/sysmon_envsysvar.h> @@ -731,11 +732,23 @@ sme_events_check(void *arg) KASSERT(sme != NULL); + mutex_enter(&sme->sme_work_mtx); + if (sme->sme_busy > 0) { + log(LOG_WARNING, "%s: workqueue busy: updates stopped\n", + sme->sme_name); + mutex_exit(&sme->sme_work_mtx); + return; + } + mutex_exit(&sme->sme_work_mtx); + mutex_enter(&sme->sme_mtx); + mutex_enter(&sme->sme_work_mtx); LIST_FOREACH(see, &sme->sme_events_list, see_list) { workqueue_enqueue(sme->sme_wq, &see->see_wk, NULL); see->see_edata->flags |= ENVSYS_FNEED_REFRESH; + sme->sme_busy++; } + mutex_exit(&sme->sme_work_mtx); if (!sysmon_low_power) sme_schedule_callout(sme); mutex_exit(&sme->sme_mtx); @@ -815,6 +828,10 @@ sme_events_worker(struct work *wk, void out: see->see_flags &= ~SEE_EVENT_WORKING; cv_broadcast(&sme->sme_condvar); + mutex_enter(&sme->sme_work_mtx); + KASSERT(sme->sme_busy > 0); + sme->sme_busy--; + mutex_exit(&sme->sme_work_mtx); mutex_exit(&sme->sme_mtx); } Index: src/sys/dev/sysmon/sysmonvar.h diff -u src/sys/dev/sysmon/sysmonvar.h:1.45 src/sys/dev/sysmon/sysmonvar.h:1.46 --- src/sys/dev/sysmon/sysmonvar.h:1.45 Sat Nov 22 15:00:05 2014 +++ src/sys/dev/sysmon/sysmonvar.h Sat Mar 14 09:52:49 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: sysmonvar.h,v 1.45 2014/11/22 15:00:05 ozaki-r Exp $ */ +/* $NetBSD: sysmonvar.h,v 1.46 2015/03/14 09:52:49 hannken Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -207,7 +207,11 @@ struct sysmon_envsys { /* * Locking/synchronization. */ + int sme_busy; /* number of items on workqueue, + sme_mtx or sme_work_mtx to read, + both to write */ kmutex_t sme_mtx; + kmutex_t sme_work_mtx; kcondvar_t sme_condvar; };