Breaking the crt1.o -> atexit() -> malloc() dependency

Tim Kientzle kientzle at
Wed Mar 5 17:12:58 PST 2008

There was some recent discussion on the commit mailing
list about how to disentangle crt1.o from malloc().

Here's a design that I think addresses all of the
issues people raised, including the POSIX requirement
that atexit() always be able to support 32 registrations.
It does it without using sbrk() or mmap(), either.

The basic idea is to lift the malloc() call up into
atexit() and have atexit_register() use statically-allocated
storage if atexit() didn't provide dynamically-allocated

This basically changes atexit() to something like this pseudocode:

int atexit(void (*function)(void))
	struct atexit *storage = malloc(sizeof(struct atexit));

	/* Note: If malloc() fails, __atexit_register will try
	 * to statically allocate, so we don't check here
	 * for malloc() failure.  */
	return __atexit_register(function, storage);

Then atexit_register either uses the block that was provided
or grabs an item from a static pool if there wasn't one:

/* 32 required by POSIX plus a few for crt1.o */
static struct atexit pool[40];

int atexit_register(void (*function)(void), struct atexit *storage)
	if (storage == NULL) {
		storage = ... next item from static pool ...
	storage.func = function;
	... add storage block to linked list ...

Avoiding free() from the low-level code is a little trickier
but I think it can be done by having the low-level code
put (dynamically-allocated) blocks back onto a free list
and having the higher-level atexit() release that list
on the next registration.  This should handle the case
of a dynamic library being repeatedly loaded and unloaded.
Of course, it's unnecessary to release the atexit storage
on program exit.

In particular, crt1.o can then call atexit_register(f, NULL)
to register its exit functions without creating a dependency on

This does require that atexit() and atexit_register() be in
separate source files, but I think it addresses all of the other
concerns people have raised.


Tim Kientzle

More information about the freebsd-current mailing list