[m-rev.] diff: avoid using alloca() in Boehm GC

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Nov 4 17:34:46 AEDT 2003


Estimated hours taken: 1
Branches: main

Fix a portability problem which caused a link error when compiling with lcc.

boehm_gc/os_dep.c:
	Apply a patch from Hans Boehm to avoid the use of alloca().

Workspace: /home/ceres/fjh/mercury
Index: boehm_gc/os_dep.c
===================================================================
RCS file: /home/mercury1/repository/mercury/boehm_gc/os_dep.c,v
retrieving revision 1.29
diff -u -d -r1.29 os_dep.c
--- boehm_gc/os_dep.c	28 Oct 2003 08:48:41 -0000	1.29
+++ boehm_gc/os_dep.c	4 Nov 2003 06:16:26 -0000
@@ -185,45 +185,41 @@
 /*
  * Apply fn to a buffer containing the contents of /proc/self/maps.
  * Return the result of fn or, if we failed, 0.
+ * We currently do nothing to /proc/self/maps other than simply read
+ * it.  This code could be simplified if we could determine its size
+ * ahead of time.
  */
 
 word GC_apply_to_maps(word (*fn)(char *))
 {
     int f;
     int result;
-    int maps_size;
-    char maps_temp[32768];
-    char *maps_buf;
+    size_t maps_size = 4000;  /* Initial guess. 	*/
+    static char init_buf[1];
+    static char *maps_buf = init_buf;
+    static size_t maps_buf_sz = 1;
 
-    /* Read /proc/self/maps	*/
-        /* Note that we may not allocate, and thus can't use stdio.	*/
-        f = open("/proc/self/maps", O_RDONLY);
-        if (-1 == f) return 0;
-	/* stat() doesn't work for /proc/self/maps, so we have to
-	   read it to find out how large it is... */
-	maps_size = 0;
+    /* Read /proc/self/maps, growing maps_buf as necessary.	*/
+        /* Note that we may not allocate conventionally, and	*/
+        /* thus can't use stdio.				*/
 	do {
-	    result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
-	    if (result <= 0) return 0;
-	    maps_size += result;
-	} while (result == sizeof(maps_temp));
-
-	if (maps_size > sizeof(maps_temp)) {
-	    /* If larger than our buffer, close and re-read it. */
-	    close(f);
+	    if (maps_size >= maps_buf_sz) {
+	      /* Grow only by powers of 2, since we leak "too small" buffers. */
+	      while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
+	      maps_buf = GC_scratch_alloc(maps_buf_sz);
+	      if (maps_buf == 0) return 0;
+	    }
 	    f = open("/proc/self/maps", O_RDONLY);
 	    if (-1 == f) return 0;
-	    maps_buf = alloca(maps_size);
-	    if (NULL == maps_buf) return 0;
-	    result = GC_repeat_read(f, maps_buf, maps_size);
-	    if (result <= 0) return 0;
-	} else {
-	    /* Otherwise use the fixed size buffer */
-	    maps_buf = maps_temp;
-	}
-
-	close(f);
-        maps_buf[result] = '\0';
+	    maps_size = 0;
+	    do {
+	        result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
+	        if (result <= 0) return 0;
+	        maps_size += result;
+	    } while (result == maps_buf_sz-1);
+	    close(f);
+	} while (maps_size >= maps_buf_sz);
+        maps_buf[maps_size] = '\0';
 	
     /* Apply fn to result. */
 	return fn(maps_buf);

-- 
Fergus Henderson <fjh at 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.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list