summarylogtreecommitdiffstats
path: root/10-fix-closure-alloc.patch
blob: a87ca39b9c1b8cefb4027a074f0cd4c980d49acb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Index: gauche-c-wrapper/src/closure_alloc.c
===================================================================
--- gauche-c-wrapper.orig/src/closure_alloc.c
+++ gauche-c-wrapper/src/closure_alloc.c
@@ -45,11 +45,15 @@ typedef struct FreeNodeRec {
 
 static FreeNode *free_list_start = NULL;
 
+static int page_size;
+
 static void expand_area()
 {
     void *area;
     FreeNode *node;
-    int page_size = getpagesize();
+
+    if (!page_size)
+      page_size = getpagesize();
 
     area =  mmap(NULL, page_size, PROT_EXEC | PROT_READ | PROT_WRITE,
                  MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -80,12 +84,16 @@ ffi_closure *closure_alloc()
     }
 
     node = free_list_start;
-    ptr = node->start + (node->n - 1)*CLOSURE_SIZE;
-    if (node->n == 1) {
+    if (node->n < 0) {
+        ptr = node->start;
         free_list_start = node->next;
         free(node);
     } else {
         --(node->n);
+	ptr = node->start + node->n*CLOSURE_SIZE;
+	if (node->n == 0) {
+            expand_area();
+	}
     }
 
     return ptr;
@@ -93,18 +101,25 @@ ffi_closure *closure_alloc()
 
 void closure_free(ffi_closure *ptr)
 {
-    FreeNode *node = free_list_start;
+    FreeNode *node;
 
-    while (node != NULL) {
-        if ((node->start + node->n*CLOSURE_SIZE) == (void*) ptr) {
-            ++(node->n);
-            return;
-        }
+    for (node = free_list_start; node; node = node->next) {
+	if (node->n < 0) {
+	    if (node->start == (void *)ptr) {
+		free_list_start = node->next;
+		free (node);
+		return;
+	    }
+	} else if (node->n < page_size / CLOSURE_SIZE
+		   && (node->start + node->n*CLOSURE_SIZE) == (void *)ptr) {
+	    ++(node->n);
+	    return;
+	}
     }
 
     node = malloc(sizeof(FreeNode));
     node->start = (void*) ptr;
-    node->n = 1;
+    node->n = -1;
     node->next = free_list_start;
     free_list_start = node;
 }