+ if (size < bloc->size)
+ {
+ /* Wouldn't it be useful to actually resize the bloc here? */
+ /* I think so too, but not if it's too expensive... */
+ if ((bloc->size - MEM_ROUNDUP (size) >= page_size)
+ && r_alloc_freeze_level == 0)
+ {
+ resize_bloc (bloc, MEM_ROUNDUP (size));
+ /* Never mind if this fails, just do nothing... */
+ /* It *should* be infallible! */
+ }
+ }
+ else if (size > bloc->size)
+ {
+ if (r_alloc_freeze_level)
+ {
+ bloc_ptr new_bloc;
+ new_bloc = get_bloc (MEM_ROUNDUP (size));
+ if (new_bloc)
+ {
+ new_bloc->variable = ptr;
+ *ptr = new_bloc->data;
+ bloc->variable = (POINTER *) NIL;
+ }
+ else
+ return NIL;
+ }
+ else
+ {
+ if (! resize_bloc (bloc, MEM_ROUNDUP (size)))
+ return NIL;
+ }
+ }
+ return *ptr;
+}
+
+/* Disable relocations, after making room for at least SIZE bytes
+ of non-relocatable heap if possible. The relocatable blocs are
+ guaranteed to hold still until thawed, even if this means that
+ malloc must return a null pointer. */
+
+void
+r_alloc_freeze (size)
+ long size;
+{
+ if (! r_alloc_initialized)
+ r_alloc_init ();
+
+ /* If already frozen, we can't make any more room, so don't try. */
+ if (r_alloc_freeze_level > 0)
+ size = 0;
+ /* If we can't get the amount requested, half is better than nothing. */
+ while (size > 0 && r_alloc_sbrk (size) == 0)
+ size /= 2;
+ ++r_alloc_freeze_level;
+ if (size > 0)
+ r_alloc_sbrk (-size);
+}
+
+void
+r_alloc_thaw ()
+{
+
+ if (! r_alloc_initialized)
+ r_alloc_init ();
+
+ if (--r_alloc_freeze_level < 0)
+ abort ();
+
+ /* This frees all unused blocs. It is not too inefficient, as the resize
+ and bcopy is done only once. Afterwards, all unreferenced blocs are
+ already shrunk to zero size. */
+ if (!r_alloc_freeze_level)
+ {
+ bloc_ptr *b = &first_bloc;
+ while (*b)
+ if (!(*b)->variable)
+ free_bloc (*b);
+ else
+ b = &(*b)->next;
+ }
+}