887 |
e = pagetochar(j); |
e = pagetochar(j); |
888 |
for (p = s; p < e;) { |
for (p = s; p < e;) { |
889 |
if (get_mark_bit((int *)p)) { |
if (get_mark_bit((int *)p)) { |
890 |
p += PTR_ALIGN; |
/* SGC cont pages: cont blocks must be no smaller than |
891 |
|
sizeof(struct contblock), and must not have a sweep |
892 |
|
granularity greater than this amount (e.g. CPTR_ALIGN) if |
893 |
|
contblock leaks are to be avoided. Used to be aligned at |
894 |
|
PTR_ALIGN. CM 20030827 */ |
895 |
|
p += CPTR_ALIGN; |
896 |
continue; |
continue; |
897 |
} |
} |
898 |
q = p + PTR_ALIGN; |
q = p + CPTR_ALIGN; |
899 |
while (q < e) { |
while (q < e) { |
900 |
if (!get_mark_bit((int *)q)) { |
if (!get_mark_bit((int *)q)) { |
901 |
q += PTR_ALIGN; |
q += CPTR_ALIGN; |
902 |
continue; |
continue; |
903 |
} |
} |
904 |
break; |
break; |
905 |
} |
} |
906 |
insert_contblock(p, q - p); |
insert_contblock(p, q - p); |
907 |
p = q + PTR_ALIGN; |
p = q + CPTR_ALIGN; |
908 |
} |
} |
909 |
i = j + 1; |
i = j + 1; |
910 |
} |
} |
966 |
return count; |
return count; |
967 |
} |
} |
968 |
|
|
969 |
|
#ifdef SGC_CONT_DEBUG |
970 |
|
void |
971 |
|
overlap_check(struct contblock *t1,struct contblock *t2) { |
972 |
|
|
973 |
|
struct contblock *p; |
974 |
|
|
975 |
|
for (;t1;t1=t1->cb_link) { |
976 |
|
|
977 |
|
if (!inheap(t1)) { |
978 |
|
fprintf(stderr,"%p not in heap\n",t1); |
979 |
|
exit(1); |
980 |
|
} |
981 |
|
|
982 |
|
for (p=t2;p;p=p->cb_link) { |
983 |
|
|
984 |
|
if (!inheap(p)) { |
985 |
|
fprintf(stderr,"%p not in heap\n",t1); |
986 |
|
exit(1); |
987 |
|
} |
988 |
|
|
989 |
|
if ((p<=t1 && (void *)p+p->cb_size>(void *)t1) || |
990 |
|
(t1<=p && (void *)t1+t1->cb_size>(void *)p)) { |
991 |
|
fprintf(stderr,"Overlap %u %p %u %p\n",t1->cb_size,t1,p->cb_size,p); |
992 |
|
exit(1); |
993 |
|
} |
994 |
|
|
995 |
|
if (p==p->cb_link) { |
996 |
|
fprintf(stderr,"circle detected at %p\n",p); |
997 |
|
exit(1); |
998 |
|
} |
999 |
|
|
1000 |
|
} |
1001 |
|
|
1002 |
|
if (t1==t1->cb_link) { |
1003 |
|
fprintf(stderr,"circle detected at %p\n",t1); |
1004 |
|
exit(1); |
1005 |
|
} |
1006 |
|
|
1007 |
|
} |
1008 |
|
|
1009 |
|
} |
1010 |
|
|
1011 |
|
void |
1012 |
|
tcc(struct contblock *t) { |
1013 |
|
|
1014 |
|
for (;t;t=t->cb_link) { |
1015 |
|
|
1016 |
|
if (!inheap(t)) { |
1017 |
|
fprintf(stderr,"%p not in heap\n",t); |
1018 |
|
break; |
1019 |
|
} |
1020 |
|
|
1021 |
|
fprintf(stderr,"%u at %p\n",t->cb_size,t); |
1022 |
|
|
1023 |
|
if (t==t->cb_link) { |
1024 |
|
fprintf(stderr,"circle detected at %p\n",t); |
1025 |
|
break; |
1026 |
|
} |
1027 |
|
|
1028 |
|
} |
1029 |
|
|
1030 |
|
} |
1031 |
|
|
1032 |
|
#endif |
1033 |
|
|
1034 |
int |
int |
1035 |
sgc_start(void) { |
sgc_start(void) { |
1036 |
|
|
1055 |
{ |
{ |
1056 |
int maxp=0; |
int maxp=0; |
1057 |
int j; |
int j; |
1058 |
int minfree = tm->tm_sgc_minfree; |
/* SGC cont pages: This used to be simply set to tm_sgc_minfree, |
1059 |
|
which is a definite bug, as minfree could then be zero, |
1060 |
|
leading this type to claim SGC pages not of its type as |
1061 |
|
specified in type_map. CM 20030827*/ |
1062 |
|
int minfree = tm->tm_sgc_minfree > 0 ? tm->tm_sgc_minfree : 1 ; |
1063 |
int count; |
int count; |
1064 |
bzero(free_map,npages*sizeof(short)); |
bzero(free_map,npages*sizeof(short)); |
1065 |
f = tm->tm_free; |
f = tm->tm_free; |
1105 |
goto FIND_FREE_PAGES; |
goto FIND_FREE_PAGES; |
1106 |
} |
} |
1107 |
} |
} |
1108 |
|
|
1109 |
|
/* SGC cont pages: Here we implement the contblock page division into |
1110 |
|
SGC and non-SGC types. Unlike the other types, we need *whole* |
1111 |
|
free pages for contblock SGC, as there is no psersistent data |
1112 |
|
element (e.g. .m) on an allocated block itself which can indicate |
1113 |
|
its live status. If anything on a page which is to be marked |
1114 |
|
read-only points to a live object on an SGC cont page, it will |
1115 |
|
never be marked and will be erroneously swept. It is also possible |
1116 |
|
for dead objects to unnecessarily mark dead regions on SGC pages |
1117 |
|
and delay sweeping until the pointing type is GC'ed if SGC is |
1118 |
|
turned off for the pointing type, e.g. tm_sgc=0. (This was so by |
1119 |
|
default for a number of types, including bignums, and has now been |
1120 |
|
corrected in init_alloc in alloc.c.) We can't get around this |
1121 |
|
AFAICT, as old data on (writable) SGC pages must be marked lest it |
1122 |
|
is lost, and (old) data on now writable non-SGC pages might point |
1123 |
|
to live regions on SGC pages, yet might not themselves be reachable |
1124 |
|
from the mark origin through an unbroken chain of writable pages. |
1125 |
|
In any case, the possibility of a lot of garbage marks on contblock |
1126 |
|
pages, especially when the blocks are small as in bignums, makes |
1127 |
|
necessary the sweeping of minimal contblocks to prevent leaks. CM |
1128 |
|
20030827 */ |
1129 |
|
{ |
1130 |
|
|
1131 |
|
void *p=NULL; |
1132 |
|
unsigned i,j,k,count; |
1133 |
|
struct contblock *new_cb_pointer=NULL,*tmp_cb_pointer=NULL,**cbpp; |
1134 |
|
|
1135 |
|
tm=tm_of(t_contiguous); |
1136 |
|
|
1137 |
|
/* SGC cont pages: First count whole free pages available. CM 20030827 */ |
1138 |
|
for (cbpp=&cb_pointer,count=0;*cbpp;cbpp=&(*cbpp)->cb_link) { |
1139 |
|
p=PAGE_ROUND_UP((void *)(*cbpp)); |
1140 |
|
k=p-((void *)(*cbpp)); |
1141 |
|
if ((*cbpp)->cb_size<k || (*cbpp)->cb_size-k<PAGESIZE) |
1142 |
|
continue; |
1143 |
|
i=((*cbpp)->cb_size-k)/PAGESIZE; |
1144 |
|
count+=i; |
1145 |
|
} |
1146 |
|
count=tm->tm_sgc>count ? tm->tm_sgc - count : 0; |
1147 |
|
|
1148 |
|
if (count>0) { |
1149 |
|
/* SGC cont pages: allocate more if necessary, dumping possible |
1150 |
|
GBC freed pages onto the old contblock list. CM 20030827*/ |
1151 |
|
int z=count+1; |
1152 |
|
void *p1=alloc_contblock(z*PAGESIZE); |
1153 |
|
p=PAGE_ROUND_UP(p1); |
1154 |
|
if (p>p1) { |
1155 |
|
z--; |
1156 |
|
insert_contblock(p1,p-p1); |
1157 |
|
insert_contblock(p+z*PAGESIZE,PAGESIZE-(p-p1)); |
1158 |
|
} |
1159 |
|
tmp_cb_pointer=cb_pointer; |
1160 |
|
cb_pointer=new_cb_pointer; |
1161 |
|
/* SGC cont pages: add new pages to new contblock list. p is not |
1162 |
|
already on any list as ensured by alloc_contblock. CM |
1163 |
|
20030827 */ |
1164 |
|
insert_contblock(p,PAGESIZE*z); |
1165 |
|
new_cb_pointer=cb_pointer; |
1166 |
|
cb_pointer=tmp_cb_pointer; |
1167 |
|
for (i=0;i<z;i++) |
1168 |
|
sgc_type_map[page(p)+i]|= SGC_PAGE_FLAG; |
1169 |
|
} |
1170 |
|
|
1171 |
|
for (cbpp=&cb_pointer;*cbpp;) { |
1172 |
|
p=PAGE_ROUND_UP((void *)(*cbpp)); |
1173 |
|
k=p-((void *)(*cbpp)); |
1174 |
|
if ((*cbpp)->cb_size<k || (*cbpp)->cb_size-k<PAGESIZE) { |
1175 |
|
cbpp=&(*cbpp)->cb_link; |
1176 |
|
continue; |
1177 |
|
} |
1178 |
|
i=((*cbpp)->cb_size-k)/PAGESIZE; |
1179 |
|
i*=PAGESIZE; |
1180 |
|
j=(*cbpp)->cb_size-i-k; |
1181 |
|
/* SGC contblock pages: remove this block from old list CM 20030827 */ |
1182 |
|
*cbpp=(*cbpp)->cb_link; |
1183 |
|
/* SGC contblock pages: add fragments old list CM 20030827 */ |
1184 |
|
if (k) { |
1185 |
|
ncb--; |
1186 |
|
insert_contblock(p-k,k); |
1187 |
|
} |
1188 |
|
if (j) { |
1189 |
|
ncb--; |
1190 |
|
insert_contblock(p+i,j); |
1191 |
|
} |
1192 |
|
tmp_cb_pointer=cb_pointer; |
1193 |
|
cb_pointer=new_cb_pointer; |
1194 |
|
/* SGC contblock pages: add whole pages to new list, p p-k, and |
1195 |
|
p+i are guaranteed to be distinct when used. CM 20030827 */ |
1196 |
|
insert_contblock(p,i); |
1197 |
|
new_cb_pointer=cb_pointer; |
1198 |
|
cb_pointer=tmp_cb_pointer; |
1199 |
|
i/=PAGESIZE; |
1200 |
|
for (j=0;j<i;j++) |
1201 |
|
sgc_type_map[page(p)+j]|= SGC_PAGE_FLAG; |
1202 |
|
} |
1203 |
|
|
1204 |
|
/* SGC contblock pages: switch to new free SGC contblock list. CM |
1205 |
|
20030827 */ |
1206 |
|
old_cb_pointer=cb_pointer; |
1207 |
|
cb_pointer=new_cb_pointer; |
1208 |
|
|
1209 |
|
#ifdef SGC_CONT_DEBUG |
1210 |
|
overlap_check(old_cb_pointer,cb_pointer); |
1211 |
|
#endif |
1212 |
|
|
1213 |
|
} |
1214 |
|
|
1215 |
/* Now allocate the sgc relblock. We do this as the tail |
/* Now allocate the sgc relblock. We do this as the tail |
1216 |
end of the ordinary rb. */ |
end of the ordinary rb. */ |
1217 |
{ |
{ |
1298 |
return 0; |
return 0; |
1299 |
sgc_enabled=0; |
sgc_enabled=0; |
1300 |
rb_start = old_rb_start; |
rb_start = old_rb_start; |
1301 |
|
|
1302 |
|
/* SGC cont pages: restore contblocks, each tmp_cb_pointer coming |
1303 |
|
from the new list is guaranteed not to be on the old. Need to |
1304 |
|
grab 'next' before insert_contblock writes is. CM 20030827 */ |
1305 |
|
{ |
1306 |
|
|
1307 |
|
struct contblock *tmp_cb_pointer,*next; |
1308 |
|
if (old_cb_pointer) { |
1309 |
|
#ifdef SGC_CONT_DEBUG |
1310 |
|
overlap_check(old_cb_pointer,cb_pointer); |
1311 |
|
#endif |
1312 |
|
tmp_cb_pointer=cb_pointer; |
1313 |
|
cb_pointer=old_cb_pointer; |
1314 |
|
for (;tmp_cb_pointer; tmp_cb_pointer=next) { |
1315 |
|
next=tmp_cb_pointer->cb_link; |
1316 |
|
insert_contblock((void *)tmp_cb_pointer,tmp_cb_pointer->cb_size); |
1317 |
|
} |
1318 |
|
} |
1319 |
|
} |
1320 |
|
|
1321 |
for (i= t_start; i < t_contiguous ; i++) |
for (i= t_start; i < t_contiguous ; i++) |
1322 |
if (TM_BASE_TYPE_P(i)) { |
if (TM_BASE_TYPE_P(i)) { |
1323 |
tm=tm_of(i); |
tm=tm_of(i); |