drivers/android/binder_alloc.c

Source file repositories/reference/linux-study-clean/drivers/android/binder_alloc.c

File Facts

System
Linux kernel
Corpus path
drivers/android/binder_alloc.c
Extension
.c
Size
38061 bytes
Lines
1410
Domain
Driver Families
Bucket
drivers/android
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (user_ptr < buffer->user_data) {
			n = n->rb_left;
		} else if (user_ptr > buffer->user_data) {
			n = n->rb_right;
		} else {
			/*
			 * Guard against user threads attempting to
			 * free the buffer when in use by kernel or
			 * after it's already been freed.
			 */
			if (!buffer->allow_user_free)
				return ERR_PTR(-EPERM);
			buffer->allow_user_free = 0;
			return buffer;
		}
	}
	return NULL;
}

/**
 * binder_alloc_prepare_to_free() - get buffer given user ptr
 * @alloc:	binder_alloc for this proc
 * @user_ptr:	User pointer to buffer data
 *
 * Validate userspace pointer to buffer data and return buffer corresponding to
 * that user pointer. Search the rb tree for buffer that matches user data
 * pointer.
 *
 * Return:	Pointer to buffer or NULL
 */
struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc,
						   unsigned long user_ptr)
{
	guard(mutex)(&alloc->mutex);
	return binder_alloc_prepare_to_free_locked(alloc, user_ptr);
}

static inline void
binder_set_installed_page(struct binder_alloc *alloc,
			  unsigned long index,
			  struct page *page)
{
	/* Pairs with acquire in binder_get_installed_page() */
	smp_store_release(&alloc->pages[index], page);
}

static inline struct page *
binder_get_installed_page(struct binder_alloc *alloc, unsigned long index)
{
	/* Pairs with release in binder_set_installed_page() */
	return smp_load_acquire(&alloc->pages[index]);
}

static void binder_lru_freelist_add(struct binder_alloc *alloc,
				    unsigned long start, unsigned long end)
{
	unsigned long page_addr;
	struct page *page;

	trace_binder_update_page_range(alloc, false, start, end);

	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
		size_t index;
		int ret;

		index = (page_addr - alloc->vm_start) / PAGE_SIZE;
		page = binder_get_installed_page(alloc, index);
		if (!page)
			continue;

		trace_binder_free_lru_start(alloc, index);

		ret = list_lru_add(alloc->freelist,
				   page_to_lru(page),
				   page_to_nid(page),
				   NULL);
		WARN_ON(!ret);

		trace_binder_free_lru_end(alloc, index);
	}
}

static inline
void binder_alloc_set_mapped(struct binder_alloc *alloc, bool state)
{
	/* pairs with smp_load_acquire in binder_alloc_is_mapped() */
	smp_store_release(&alloc->mapped, state);
}

static inline bool binder_alloc_is_mapped(struct binder_alloc *alloc)

Annotation

Implementation Notes