[Gc] RE: alloca() vs lcc

Boehm, Hans hans_boehm@hp.com
Mon, 3 Nov 2003 14:09:07 -0800


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C3A257.19D117B6
Content-Type: text/plain;
	charset="iso-8859-1"

How's the attached patch?

This uses GC_scratch_alloc, which I think should be OK.  It also fixes
a subtle off-by-one subscript error, and generally tries to clean up
GC_apply_to_maps.

(By default, this code is used only for debugging, though it is needed
for other things in a few configurations.)

Hans

> -----Original Message-----
> From: Fergus Henderson [mailto:fjh@ceres.cs.mu.OZ.AU]On 
> Behalf Of Fergus
> Henderson
> Sent: Sunday, November 02, 2003 7:17 AM
> To: Boehm, Hans
> Cc: 'gc@linux.hpl.hp.com'
> Subject: alloca() vs lcc
> 
> 
> Hi,
> 
> We recently upgraded to gc-6.3alpha2 (from 6.2alpha4).
> When I try to compile the collector with lcc, which 
> previously used to work,
> we get the following link error:
> 
> ../boehm_gc/libgc.a(os_dep.o): In function `GC_apply_to_maps':
> os_dep.o(.text+0x12f): undefined reference to `alloca'
> 
> This is because lcc does not define alloca().
> Any suggestions?
> 
> The normal procedure for solving this would be to replace calls to
> alloca() with calls to malloc(), but I don't think that is safe here.
> There is a comment in GC_apply_to_maps() saying "Note that we may
> not allocate", presumably because it might cause problems in the
> case when malloc() is redirected to GC_malloc() or GC_malloc_atomic().
> 
> -- 
> Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known 
> that the pursuit
> The University of Melbourne         |  of excellence is a 
> lethal habit"
> WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words 
> of T. S. Garp.
> 


------_=_NextPart_000_01C3A257.19D117B6
Content-Type: application/octet-stream;
	name="os_dep.c.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="os_dep.c.diff"

--- os_dep.c.orig	2003-11-03 11:51:58.000000000 -0800=0A=
+++ os_dep.c	2003-11-03 14:09:36.000000000 -0800=0A=
@@ -183,45 +183,41 @@=0A=
 /*=0A=
  * Apply fn to a buffer containing the contents of /proc/self/maps.=0A=
  * Return the result of fn or, if we failed, 0.=0A=
+ * We currently do nothing to /proc/self/maps other than simply =
read=0A=
+ * it.  This code could be simplified if we could determine its =
size=0A=
+ * ahead of time.=0A=
  */=0A=
 =0A=
 word GC_apply_to_maps(word (*fn)(char *))=0A=
 {=0A=
     int f;=0A=
     int result;=0A=
-    int maps_size;=0A=
-    char maps_temp[32768];=0A=
-    char *maps_buf;=0A=
-=0A=
-    /* Read /proc/self/maps	*/=0A=
-        /* Note that we may not allocate, and thus can't use stdio.	=
*/=0A=
-        f =3D open("/proc/self/maps", O_RDONLY);=0A=
-        if (-1 =3D=3D f) return 0;=0A=
-	/* stat() doesn't work for /proc/self/maps, so we have to=0A=
-	   read it to find out how large it is... */=0A=
-	maps_size =3D 0;=0A=
+    size_t maps_size =3D 4000;  /* Initial guess. 	*/=0A=
+    static char init_buf[1];=0A=
+    static char *maps_buf =3D init_buf;=0A=
+    static size_t maps_buf_sz =3D 1;=0A=
+=0A=
+    /* Read /proc/self/maps, growing maps_buf as necessary.	*/=0A=
+        /* Note that we may not allocate conventionally, and	*/=0A=
+        /* thus can't use stdio.				*/=0A=
 	do {=0A=
-	    result =3D GC_repeat_read(f, maps_temp, sizeof(maps_temp));=0A=
-	    if (result <=3D 0) return 0;=0A=
-	    maps_size +=3D result;=0A=
-	} while (result =3D=3D sizeof(maps_temp));=0A=
-=0A=
-	if (maps_size > sizeof(maps_temp)) {=0A=
-	    /* If larger than our buffer, close and re-read it. */=0A=
-	    close(f);=0A=
+	    if (maps_size >=3D maps_buf_sz) {=0A=
+	      /* Grow only by powers of 2, since we leak "too small" buffers. =
*/=0A=
+	      while (maps_size >=3D maps_buf_sz) maps_buf_sz *=3D 2;=0A=
+	      maps_buf =3D GC_scratch_alloc(maps_buf_sz);=0A=
+	      if (maps_buf =3D=3D 0) return 0;=0A=
+	    }=0A=
 	    f =3D open("/proc/self/maps", O_RDONLY);=0A=
 	    if (-1 =3D=3D f) return 0;=0A=
-	    maps_buf =3D alloca(maps_size);=0A=
-	    if (NULL =3D=3D maps_buf) return 0;=0A=
-	    result =3D GC_repeat_read(f, maps_buf, maps_size);=0A=
-	    if (result <=3D 0) return 0;=0A=
-	} else {=0A=
-	    /* Otherwise use the fixed size buffer */=0A=
-	    maps_buf =3D maps_temp;=0A=
-	}=0A=
-=0A=
-	close(f);=0A=
-        maps_buf[result] =3D '\0';=0A=
+	    maps_size =3D 0;=0A=
+	    do {=0A=
+	        result =3D GC_repeat_read(f, maps_buf, maps_buf_sz-1);=0A=
+	        if (result <=3D 0) return 0;=0A=
+	        maps_size +=3D result;=0A=
+	    } while (result =3D=3D maps_buf_sz-1);=0A=
+	    close(f);=0A=
+	} while (maps_size >=3D maps_buf_sz);=0A=
+        maps_buf[maps_size] =3D '\0';=0A=
 	=0A=
     /* Apply fn to result. */=0A=
 	return fn(maps_buf);=0A=

------_=_NextPart_000_01C3A257.19D117B6--