Except for the first patch, this is mostly adding a bunch of different
null checks:

1. r300g: Fix macro
This fixes a potential bug if (has_hyperz) is false (it would act as
if has_hyperz is true).
2. r300g: Fix leaks in failed context creation
This patch is the biggest one: It refactors the create/destroy context
functions; before, if r300_create_context failed to allocate something
essential it was either ignored or it only partly cleaned up after
itself (ex: leaking all the allocations in r300_init_atoms(),
forgetting to decrement the number of existing contexts, leaking the
mutexes initialized by r300_hyperz_init_mm, etc), and there's a *lot*
to stuff to clean up, so this just re-uses the logic in
r300_destroy_context to avoid code duplication.
3. r300g: Let hyperz init fail
Adds a boolean return value to check if the calls to u_mmInit failed
(they can potentially return null)
4. gallium: Check if draw_create returns null
This changes all the drivers that depend on the draw module to abort
if draw_create returned null (which it might if using LLVM and on a
CPU without SSE2, or if it just couldn't allocate memory)
5. draw: Check if llvm returns null
Always check for null and don't rely on assert(), since that won't
help on non-debug builds. Might also help with
http://bugs.freedesktop.org/29578 .
From 7ff36acc6da61bf1a7efe12bc84479b75adf893d Mon Sep 17 00:00:00 2001
From: nobled <nob...@dreamwidth.org>
Date: Sun, 15 Aug 2010 02:50:04 +0000
Subject: [PATCH] r300g: Fix macro

This fixes a potential bug if (has_hyperz) is false
(it would still init the atom as if has_hyperz were true).
---
 src/gallium/drivers/r300/r300_context.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index e8b6c4f..23b654e 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -158,12 +158,14 @@ void r300_flush_cb(void *data)
 }
 
 #define R300_INIT_ATOM(atomname, atomsize) \
+ do { \
     r300->atomname.name = #atomname; \
     r300->atomname.state = NULL; \
     r300->atomname.size = atomsize; \
     r300->atomname.emit = r300_emit_##atomname; \
     r300->atomname.dirty = FALSE; \
-    insert_at_tail(&r300->atom_list, &r300->atomname);
+    insert_at_tail(&r300->atom_list, &r300->atomname); \
+ } while (0)
 
 static void r300_setup_atoms(struct r300_context* r300)
 {
-- 
1.5.4.3

From 3576a26e9bd284ed94e366063b197a1f2e93fb49 Mon Sep 17 00:00:00 2001
From: nobled <nob...@dreamwidth.org>
Date: Sun, 15 Aug 2010 03:59:15 +0000
Subject: [PATCH] r300g: Fix leaks in failed context creation

This changes r300_destroy_context() so it can be called
on a partially-initialized context, and uses it when
r300_create_context() hits a fatal error.

This makes sure r300_create_context() doesn't leak memory
or neglect to call r300_update_num_contexts() when it fails.
---
 src/gallium/drivers/r300/r300_context.c |   82 ++++++++++++++++++-------------
 1 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 23b654e..25b39c5 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -99,8 +99,10 @@ static void r300_destroy_context(struct pipe_context* context)
     struct r300_context* r300 = r300_context(context);
     struct r300_atom *atom;
 
-    util_blitter_destroy(r300->blitter);
-    draw_destroy(r300->draw);
+    if (r300->blitter)
+        util_blitter_destroy(r300->blitter);
+    if (r300->draw)
+        draw_destroy(r300->draw);
 
     /* Print stats, if enabled. */
     if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) {
@@ -112,40 +114,48 @@ static void r300_destroy_context(struct pipe_context* context)
         }
     }
 
-    u_upload_destroy(r300->upload_vb);
-    u_upload_destroy(r300->upload_ib);
+    if (r300->upload_vb)
+        u_upload_destroy(r300->upload_vb);
+    if (r300->upload_ib)
+        u_upload_destroy(r300->upload_ib);
 
-    /* setup hyper-z mm */
-    if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
+    if (r300->zmask_mm)
         r300_hyperz_destroy_mm(r300);
 
-    translate_cache_destroy(r300->tran.translate_cache);
+    if (r300->tran.translate_cache)
+        translate_cache_destroy(r300->tran.translate_cache);
 
+    /* XXX: This function assumes r300->query_list was initialized */
     r300_release_referenced_objects(r300);
 
-    r300->rws->cs_destroy(r300->cs);
+    if (r300->cs)
+        r300->rws->cs_destroy(r300->cs);
 
+    /* XXX: No way to tell if this was initialized or not? */
     util_mempool_destroy(&r300->pool_transfers);
 
     r300_update_num_contexts(r300->screen, -1);
 
-    FREE(r300->aa_state.state);
-    FREE(r300->blend_color_state.state);
-    FREE(r300->clip_state.state);
-    FREE(r300->fb_state.state);
-    FREE(r300->gpu_flush.state);
-    FREE(r300->hyperz_state.state);
-    FREE(r300->invariant_state.state);
-    FREE(r300->rs_block_state.state);
-    FREE(r300->scissor_state.state);
-    FREE(r300->textures_state.state);
-    FREE(r300->vap_invariant_state.state);
-    FREE(r300->viewport_state.state);
-    FREE(r300->ztop_state.state);
-    FREE(r300->fs_constants.state);
-    FREE(r300->vs_constants.state);
-    if (!r300->screen->caps.has_tcl) {
-        FREE(r300->vertex_stream_state.state);
+    /* Free the structs allocated in r300_setup_atoms() */
+    if (r300->aa_state.state) {
+        FREE(r300->aa_state.state);
+        FREE(r300->blend_color_state.state);
+        FREE(r300->clip_state.state);
+        FREE(r300->fb_state.state);
+        FREE(r300->gpu_flush.state);
+        FREE(r300->hyperz_state.state);
+        FREE(r300->invariant_state.state);
+        FREE(r300->rs_block_state.state);
+        FREE(r300->scissor_state.state);
+        FREE(r300->textures_state.state);
+        FREE(r300->vap_invariant_state.state);
+        FREE(r300->viewport_state.state);
+        FREE(r300->ztop_state.state);
+        FREE(r300->fs_constants.state);
+        FREE(r300->vs_constants.state);
+        if (r300->vertex_stream_state.state) {
+            FREE(r300->vertex_stream_state.state);
+        }
     }
     FREE(r300);
 }
@@ -406,12 +416,16 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300->context.destroy = r300_destroy_context;
 
-    r300->cs = rws->cs_create(rws);
+    make_empty_list(&r300->query_list);
 
     util_mempool_create(&r300->pool_transfers,
                         sizeof(struct pipe_transfer), 64,
                         UTIL_MEMPOOL_SINGLETHREADED);
 
+    r300->cs = rws->cs_create(rws);
+    if (r300->cs == NULL)
+        goto fail;
+
     if (!r300screen->caps.has_tcl) {
         /* Create a Draw. This is used for SW TCL. */
         r300->draw = draw_create(&r300->context);
@@ -426,8 +440,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300_setup_atoms(r300);
 
-    make_empty_list(&r300->query_list);
-
     r300_init_blit_functions(r300);
     r300_init_flush_functions(r300);
     r300_init_query_functions(r300);
@@ -435,6 +447,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     r300_init_resource_functions(r300);
 
     r300->blitter = util_blitter_create(&r300->context);
+    if (r300->blitter == NULL)
+        goto fail;
 
     /* Render functions must be initialized after blitter. */
     r300_init_render_functions(r300);
@@ -450,15 +464,17 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 				      PIPE_BIND_INDEX_BUFFER);
 
     if (r300->upload_ib == NULL)
-        goto no_upload_ib;
+        goto fail;
 
     r300->upload_vb = u_upload_create(&r300->context,
 				      128 * 1024, 16,
 				      PIPE_BIND_VERTEX_BUFFER);
     if (r300->upload_vb == NULL)
-        goto no_upload_vb;
+        goto fail;
 
     r300->tran.translate_cache = translate_cache_create();
+    if (r300->tran.translate_cache == NULL)
+        goto fail;
 
     r300_init_states(&r300->context);
 
@@ -488,10 +504,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     return &r300->context;
 
- no_upload_ib:
-    u_upload_destroy(r300->upload_ib);
- no_upload_vb:
-    FREE(r300);
+ fail:
+    r300_destroy_context(&r300->context);
     return NULL;
 }
 
-- 
1.5.4.3

From 7a7bbef1034cb50863139385aec71ab9067e1ec4 Mon Sep 17 00:00:00 2001
From: nobled <nob...@dreamwidth.org>
Date: Sun, 15 Aug 2010 03:53:18 +0000
Subject: [PATCH] r300g: Let hyperz init fail

---
 src/gallium/drivers/r300/r300_context.c |    3 ++-
 src/gallium/drivers/r300/r300_hyperz.c  |   21 +++++++++++++++++----
 src/gallium/drivers/r300/r300_hyperz.h  |    2 +-
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 25b39c5..d783f21 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -457,7 +457,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     /* setup hyper-z mm */
     if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
-        r300_hyperz_init_mm(r300);
+        if (!r300_hyperz_init_mm(r300))
+            goto fail;
 
     r300->upload_ib = u_upload_create(&r300->context,
 				      32 * 1024, 16,
diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c
index 811b564..a471b73 100644
--- a/src/gallium/drivers/r300/r300_hyperz.c
+++ b/src/gallium/drivers/r300/r300_hyperz.c
@@ -373,23 +373,36 @@ void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf
     return;
 }
 
-void r300_hyperz_init_mm(struct r300_context *r300)
+boolean r300_hyperz_init_mm(struct r300_context *r300)
 {
     struct r300_screen* r300screen = r300->screen;
     int frag_pipes = r300screen->caps.num_frag_pipes;
 
-    if (r300screen->caps.hiz_ram)
+    r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes);
+    if (!r300->zmask_mm)
+      return FALSE;
+
+    if (r300screen->caps.hiz_ram) {
       r300->hiz_mm = u_mmInit(0, r300screen->caps.hiz_ram * frag_pipes);
+      if (!r300->hiz_mm) {
+        u_mmDestroy(r300->zmask_mm);
+        r300->zmask_mm = NULL;
+        return FALSE;
+      }
+    }
 
-    r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes);
+    return TRUE;
 }
 
 void r300_hyperz_destroy_mm(struct r300_context *r300)
 {
     struct r300_screen* r300screen = r300->screen;
 
-    if (r300screen->caps.hiz_ram)
+    if (r300screen->caps.hiz_ram) {
       u_mmDestroy(r300->hiz_mm);
+      r300->hiz_mm = NULL;
+    }
 
     u_mmDestroy(r300->zmask_mm);
+    r300->zmask_mm = NULL;
 }
diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h
index 09e1ff6..30a23ec 100644
--- a/src/gallium/drivers/r300/r300_hyperz.h
+++ b/src/gallium/drivers/r300/r300_hyperz.h
@@ -30,6 +30,6 @@ void r300_update_hyperz_state(struct r300_context* r300);
 void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf);
 void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress);
 
-void r300_hyperz_init_mm(struct r300_context *r300);
+boolean r300_hyperz_init_mm(struct r300_context *r300);
 void r300_hyperz_destroy_mm(struct r300_context *r300);
 #endif
-- 
1.5.4.3

From 3aff8298420e87923098b16201db08c208205202 Mon Sep 17 00:00:00 2001
From: nobled <nob...@dreamwidth.org>
Date: Sun, 15 Aug 2010 04:03:19 +0000
Subject: [PATCH] gallium: Check if draw_create returns null

---
 src/gallium/drivers/cell/ppu/cell_context.c |    6 ++++++
 src/gallium/drivers/i915/i915_context.c     |    7 ++++++-
 src/gallium/drivers/nv50/nv50_context.c     |    6 +++++-
 src/gallium/drivers/nvfx/nvfx_context.c     |    5 +++++
 src/gallium/drivers/r300/r300_context.c     |    2 ++
 5 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c
index 143eca8..a025869 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.c
+++ b/src/gallium/drivers/cell/ppu/cell_context.c
@@ -75,6 +75,8 @@ cell_draw_create(struct cell_context *cell)
 {
    struct draw_context *draw = draw_create(&cell->pipe);
 
+   if (!draw)
+      return NULL;
 #if 0 /* broken */
    if (getenv("GALLIUM_CELL_VS")) {
       /* plug in SPU-based vertex transformation code */
@@ -150,6 +152,10 @@ cell_create_context(struct pipe_screen *screen,
    cell_init_texture_transfer_funcs(cell);
 
    cell->draw = cell_draw_create(cell);
+   if (!cell->draw) {
+      align_free(cell);
+      return NULL;
+   }
 
    /* Create cache of fragment ops generated code */
    cell->fragment_ops_cache =
diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c
index 2beb9e3..decc046 100644
--- a/src/gallium/drivers/i915/i915_context.c
+++ b/src/gallium/drivers/i915/i915_context.c
@@ -150,7 +150,12 @@ i915_create_context(struct pipe_screen *screen, void *priv)
     * Create drawing context and plug our rendering stage into it.
     */
    i915->draw = draw_create(&i915->base);
-   assert(i915->draw);
+
+   if (!i915->draw) {
+      i915_destroy(&i915->base);
+      return NULL;
+   }
+
    if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) {
       draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915));
    } else {
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index 0874cb5..ee10a1b 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -95,7 +95,11 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
 	nv50_init_resource_functions(&nv50->pipe);
 
 	nv50->draw = draw_create(&nv50->pipe);
-	assert(nv50->draw);
+	if (!nv50->draw) {
+		nv50_destroy(&nv50->pipe);
+		return NULL;
+	}
+
 	draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
 
 	return &nv50->pipe;
diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c
index 7218abf..0ce0513 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.c
+++ b/src/gallium/drivers/nvfx/nvfx_context.c
@@ -70,6 +70,11 @@ nvfx_create(struct pipe_screen *pscreen, void *priv)
 
 	/* Create, configure, and install fallback swtnl path */
 	nvfx->draw = draw_create(&nvfx->pipe);
+	if (!nvfx->draw) {
+		nvfx_destroy(&nvfx->pipe);
+		return NULL;
+	}
+
 	draw_wide_point_threshold(nvfx->draw, 9999999.0);
 	draw_wide_line_threshold(nvfx->draw, 9999999.0);
 	draw_enable_line_stipple(nvfx->draw, FALSE);
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index d783f21..759a7ad 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -429,6 +429,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     if (!r300screen->caps.has_tcl) {
         /* Create a Draw. This is used for SW TCL. */
         r300->draw = draw_create(&r300->context);
+        if (!r300->draw)
+            goto fail;
         /* Enable our renderer. */
         draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300));
         /* Enable Draw's clipping. */
-- 
1.5.4.3

From 2b4dbbbba4b834eb0444bce1db873c17fb00101e Mon Sep 17 00:00:00 2001
From: nobled <nob...@dreamwidth.org>
Date: Mon, 16 Aug 2010 00:21:47 +0000
Subject: [PATCH] draw: Check if llvm returns null

Avoid potential segfault on non-debug builds if
llvm doesn't initialize, and just return null.
Same if draw_llvm_create() fails (either because of
memory allocation or running on a CPU without SSE2).
---
 src/gallium/auxiliary/draw/draw_context.c |    5 +++++
 src/gallium/auxiliary/draw/draw_llvm.c    |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 995b675..c0841d6 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -52,8 +52,13 @@ struct draw_context *draw_create( struct pipe_context *pipe )
 #if HAVE_LLVM
    lp_build_init();
    assert(lp_build_engine);
+   if (lp_build_engine == NULL)
+      goto fail;
+
    draw->engine = lp_build_engine;
    draw->llvm = draw_llvm_create(draw);
+   if (draw->llvm == NULL)
+      goto fail;
 #endif
 
    if (!draw_init(draw))
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 8d53601..1a218ec 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -286,6 +286,9 @@ draw_llvm_create(struct draw_context *draw)
 void
 draw_llvm_destroy(struct draw_llvm *llvm)
 {
+   if (!llvm)
+      return;
+
    LLVMDisposePassManager(llvm->pass);
 
    FREE(llvm);
-- 
1.5.4.3

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to