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