Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci -avoid lock leak in error case
details: https://anonhg.NetBSD.org/src/rev/5ed851c0a526
branches: trunk
changeset: 535167:5ed851c0a526
user: drochner <drochner%NetBSD.org@localhost>
date: Sun Aug 11 12:40:47 2002 +0000
description:
-avoid lock leak in error case
-Free AGP memory on close, to avoid a memory leak in case
the X server doesn't free it explicitely.
(It appears that the X server never calls AGPIOC_DEALLOCATE.)
Fixes PR kern/17869 by Emmanuel Dreyfus.
diffstat:
sys/dev/pci/agp.c | 32 +++++++++++++++++++++++++++-----
1 files changed, 27 insertions(+), 5 deletions(-)
diffs (73 lines):
diff -r 4642b64ff723 -r 5ed851c0a526 sys/dev/pci/agp.c
--- a/sys/dev/pci/agp.c Sun Aug 11 12:40:46 2002 +0000
+++ b/sys/dev/pci/agp.c Sun Aug 11 12:40:47 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: agp.c,v 1.15 2002/06/27 18:37:10 drochner Exp $ */
+/* $NetBSD: agp.c,v 1.16 2002/08/11 12:40:47 drochner Exp $ */
/*-
* Copyright (c) 2000 Doug Rabson
@@ -65,7 +65,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: agp.c,v 1.15 2002/06/27 18:37:10 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: agp.c,v 1.16 2002/08/11 12:40:47 drochner Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -514,8 +514,10 @@
for (contigpages = 8; contigpages > 0; contigpages >>= 1) {
nseg = (mem->am_size / (contigpages * PAGE_SIZE)) + 1;
segs = malloc(nseg * sizeof *segs, M_AGP, M_WAITOK);
- if (segs == NULL)
+ if (segs == NULL) {
+ lockmgr(&sc->as_lock, LK_RELEASE, 0);
return ENOMEM;
+ }
if (bus_dmamem_alloc(sc->as_dmat, mem->am_size, PAGE_SIZE, 0,
segs, nseg, &mem->am_nseg,
contigpages > 1 ?
@@ -669,7 +671,8 @@
return EBUSY;
/*
- * Clear out the aperture and free any outstanding memory blocks.
+ * Clear out outstanding aperture mappings.
+ * (should not be necessary, done by caller)
*/
TAILQ_FOREACH(mem, &sc->as_memory, am_link) {
if (mem->am_is_bound) {
@@ -798,12 +801,31 @@
agpclose(dev_t dev, int fflag, int devtype, struct proc *p)
{
struct agp_softc *sc = device_lookup(&agp_cd, AGPUNIT(dev));
+ struct agp_memory *mem;
/*
* Clear the GATT and force release on last close
*/
- if (sc->as_state == AGP_ACQUIRE_USER)
+ if (sc->as_state == AGP_ACQUIRE_USER) {
+ while ((mem = TAILQ_FIRST(&sc->as_memory))) {
+ if (mem->am_is_bound) {
+ printf("agpclose: mem %d is bound\n",
+ mem->am_id);
+ AGP_UNBIND_MEMORY(sc, mem);
+ }
+ /*
+ * XXX it is not documented, but if the protocol allows
+ * allocate->acquire->bind, it would be possible that
+ * memory ranges are allocated by the kernel here,
+ * which we shouldn't free. We'd have to keep track of
+ * the memory range's owner.
+ * The kernel API is unsed yet, so we get away with
+ * freeing all.
+ */
+ AGP_FREE_MEMORY(sc, mem);
+ }
agp_release_helper(sc, AGP_ACQUIRE_USER);
+ }
sc->as_isopen = 0;
return 0;
Home |
Main Index |
Thread Index |
Old Index