Esempio n. 1
0
void
terminate_program(void)
{
	image_t **termList;
	ssize_t count, i;

	count = get_sorted_image_list(NULL, &termList, RFLAG_TERMINATED);
	if (count < B_OK)
		return;

	if (gInvalidImageIDs) {
		// After fork, we lazily rebuild the image IDs of all loaded images
		update_image_ids();
	}

	TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
	for (i = count; i-- > 0;) {
		image_t *image = termList[i];

		TRACE(("%ld:  term: %s\n", find_thread(NULL), image->name));

		image_event(image, IMAGE_EVENT_UNINITIALIZING);

		if (image->term_routine)
			((init_term_function)image->term_routine)(image->id);

		image_event(image, IMAGE_EVENT_UNLOADING);
	}
	TRACE(("%ld:  term done.\n", find_thread(NULL)));

	free(termList);
}
Esempio n. 2
0
image_t*
find_loaded_image_by_id(image_id id, bool ignoreDisposable)
{
	if (gInvalidImageIDs) {
		// After fork, we lazily rebuild the image IDs of all loaded images
		update_image_ids();
	}

	for (image_t* image = sLoadedImages.head; image; image = image->next) {
		if (image->id == id)
			return image;
	}

	if (ignoreDisposable)
		return NULL;

	for (image_t* image = sDisposableImages.head; image; image = image->next) {
		if (image->id == id)
			return image;
	}

	return NULL;
}
Esempio n. 3
0
status_t
unload_library(void* handle, image_id imageID, bool addOn)
{
	image_t *image;
	image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE;

	if (handle == NULL && imageID < 0)
		return B_BAD_IMAGE_ID;

	if (handle == RLD_GLOBAL_SCOPE)
		return B_OK;

	rld_lock();
		// for now, just do stupid simple global locking

	if (gInvalidImageIDs) {
		// After fork, we lazily rebuild the image IDs of all loaded images
		update_image_ids();
	}

	// we only check images that have been already initialized

	status_t status = B_BAD_IMAGE_ID;

	if (handle != NULL) {
		image = (image_t*)handle;
		put_image(image);
		status = B_OK;
	} else {
		image = find_loaded_image_by_id(imageID, true);
		if (image != NULL) {
			// unload image
			if (type == image->type) {
				put_image(image);
				status = B_OK;
			} else
				status = B_BAD_VALUE;
		}
	}

	if (status == B_OK) {
		while ((image = get_disposable_images().head) != NULL) {
			// Call the exit hooks that live in this image.
			// Note: With the Itanium ABI this shouldn't really be done this
			// way anymore, since global destructors are registered via
			// __cxa_atexit() (the ones that are registered dynamically) and the
			// termination routine should call __cxa_finalize() for the image.
			// The reason why we still do it is that hooks registered with
			// atexit() aren't associated with the image. We could find out
			// there which image the hooks lives in and register it
			// respectively, but since that would be done always, that's
			// probably more expensive than calling
			// call_atexit_hooks_for_range() only here, which happens only when
			// libraries are unloaded dynamically.
			if (gRuntimeLoader.call_atexit_hooks_for_range) {
				gRuntimeLoader.call_atexit_hooks_for_range(
					image->regions[0].vmstart, image->regions[0].vmsize);
			}

			image_event(image, IMAGE_EVENT_UNINITIALIZING);

			if (image->term_routine)
				((init_term_function)image->term_routine)(image->id);

			dequeue_disposable_image(image);
			unmap_image(image);

			image_event(image, IMAGE_EVENT_UNLOADING);

			delete_image(image);
		}
	}

	rld_unlock();
	return status;
}