diff options
Diffstat (limited to 'drivers/android/binder_alloc.c')
| -rw-r--r-- | drivers/android/binder_alloc.c | 64 | 
1 files changed, 29 insertions, 35 deletions
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 55a3c3c2409f..662a2a2e2e84 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -212,8 +212,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,  		mm = alloc->mm;  	if (mm) { -		mmap_read_lock(mm); -		vma = vma_lookup(mm, alloc->vma_addr); +		mmap_write_lock(mm); +		vma = alloc->vma;  	}  	if (!vma && need_mm) { @@ -270,7 +270,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,  		trace_binder_alloc_page_end(alloc, index);  	}  	if (mm) { -		mmap_read_unlock(mm); +		mmap_write_unlock(mm);  		mmput(mm);  	}  	return 0; @@ -303,21 +303,24 @@ err_page_ptr_cleared:  	}  err_no_vma:  	if (mm) { -		mmap_read_unlock(mm); +		mmap_write_unlock(mm);  		mmput(mm);  	}  	return vma ? -ENOMEM : -ESRCH;  } +static inline void binder_alloc_set_vma(struct binder_alloc *alloc, +		struct vm_area_struct *vma) +{ +	/* pairs with smp_load_acquire in binder_alloc_get_vma() */ +	smp_store_release(&alloc->vma, vma); +} +  static inline struct vm_area_struct *binder_alloc_get_vma(  		struct binder_alloc *alloc)  { -	struct vm_area_struct *vma = NULL; - -	if (alloc->vma_addr) -		vma = vma_lookup(alloc->mm, alloc->vma_addr); - -	return vma; +	/* pairs with smp_store_release in binder_alloc_set_vma() */ +	return smp_load_acquire(&alloc->vma);  }  static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) @@ -380,15 +383,13 @@ static struct binder_buffer *binder_alloc_new_buf_locked(  	size_t size, data_offsets_size;  	int ret; -	mmap_read_lock(alloc->mm); +	/* Check binder_alloc is fully initialized */  	if (!binder_alloc_get_vma(alloc)) { -		mmap_read_unlock(alloc->mm);  		binder_alloc_debug(BINDER_DEBUG_USER_ERROR,  				   "%d: binder_alloc_buf, no vma\n",  				   alloc->pid);  		return ERR_PTR(-ESRCH);  	} -	mmap_read_unlock(alloc->mm);  	data_offsets_size = ALIGN(data_size, sizeof(void *)) +  		ALIGN(offsets_size, sizeof(void *)); @@ -778,7 +779,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,  	buffer->free = 1;  	binder_insert_free_buffer(alloc, buffer);  	alloc->free_async_space = alloc->buffer_size / 2; -	alloc->vma_addr = vma->vm_start; + +	/* Signal binder_alloc is fully initialized */ +	binder_alloc_set_vma(alloc, vma);  	return 0; @@ -808,8 +811,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)  	buffers = 0;  	mutex_lock(&alloc->mutex); -	BUG_ON(alloc->vma_addr && -	       vma_lookup(alloc->mm, alloc->vma_addr)); +	BUG_ON(alloc->vma);  	while ((n = rb_first(&alloc->allocated_buffers))) {  		buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -916,25 +918,17 @@ void binder_alloc_print_pages(struct seq_file *m,  	 * Make sure the binder_alloc is fully initialized, otherwise we might  	 * read inconsistent state.  	 */ - -	mmap_read_lock(alloc->mm); -	if (binder_alloc_get_vma(alloc) == NULL) { -		mmap_read_unlock(alloc->mm); -		goto uninitialized; -	} - -	mmap_read_unlock(alloc->mm); -	for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { -		page = &alloc->pages[i]; -		if (!page->page_ptr) -			free++; -		else if (list_empty(&page->lru)) -			active++; -		else -			lru++; +	if (binder_alloc_get_vma(alloc) != NULL) { +		for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { +			page = &alloc->pages[i]; +			if (!page->page_ptr) +				free++; +			else if (list_empty(&page->lru)) +				active++; +			else +				lru++; +		}  	} - -uninitialized:  	mutex_unlock(&alloc->mutex);  	seq_printf(m, "  pages: %d:%d:%d\n", active, lru, free);  	seq_printf(m, "  pages high watermark: %zu\n", alloc->pages_high); @@ -969,7 +963,7 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc)   */  void binder_alloc_vma_close(struct binder_alloc *alloc)  { -	alloc->vma_addr = 0; +	binder_alloc_set_vma(alloc, NULL);  }  /**  |