@ -697,6 +697,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
binder_insert_free_buffer ( alloc , buffer ) ;
binder_insert_free_buffer ( alloc , buffer ) ;
}
}
static void binder_alloc_clear_buf ( struct binder_alloc * alloc ,
struct binder_buffer * buffer ) ;
/**
/**
* binder_alloc_free_buf ( ) - free a binder buffer
* binder_alloc_free_buf ( ) - free a binder buffer
* @ alloc : binder_alloc for this proc
* @ alloc : binder_alloc for this proc
@ -707,6 +709,18 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
void binder_alloc_free_buf ( struct binder_alloc * alloc ,
void binder_alloc_free_buf ( struct binder_alloc * alloc ,
struct binder_buffer * buffer )
struct binder_buffer * buffer )
{
{
/*
* We could eliminate the call to binder_alloc_clear_buf ( )
* from binder_alloc_deferred_release ( ) by moving this to
* binder_alloc_free_buf_locked ( ) . However , that could
* increase contention for the alloc mutex if clear_on_free
* is used frequently for large buffers . The mutex is not
* needed for correctness here .
*/
if ( buffer - > clear_on_free ) {
binder_alloc_clear_buf ( alloc , buffer ) ;
buffer - > clear_on_free = false ;
}
mutex_lock ( & alloc - > mutex ) ;
mutex_lock ( & alloc - > mutex ) ;
binder_free_buf_locked ( alloc , buffer ) ;
binder_free_buf_locked ( alloc , buffer ) ;
mutex_unlock ( & alloc - > mutex ) ;
mutex_unlock ( & alloc - > mutex ) ;
@ -799,6 +813,10 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
/* Transaction should already have been freed */
/* Transaction should already have been freed */
BUG_ON ( buffer - > transaction ) ;
BUG_ON ( buffer - > transaction ) ;
if ( buffer - > clear_on_free ) {
binder_alloc_clear_buf ( alloc , buffer ) ;
buffer - > clear_on_free = false ;
}
binder_free_buf_locked ( alloc , buffer ) ;
binder_free_buf_locked ( alloc , buffer ) ;
buffers + + ;
buffers + + ;
}
}
@ -1125,6 +1143,36 @@ static struct page *binder_alloc_get_page(struct binder_alloc *alloc,
return lru_page - > page_ptr ;
return lru_page - > page_ptr ;
}
}
/**
* binder_alloc_clear_buf ( ) - zero out buffer
* @ alloc : binder_alloc for this proc
* @ buffer : binder buffer to be cleared
*
* memset the given buffer to 0
*/
static void binder_alloc_clear_buf ( struct binder_alloc * alloc ,
struct binder_buffer * buffer )
{
size_t bytes = binder_alloc_buffer_size ( alloc , buffer ) ;
binder_size_t buffer_offset = 0 ;
while ( bytes ) {
unsigned long size ;
struct page * page ;
pgoff_t pgoff ;
void * kptr ;
page = binder_alloc_get_page ( alloc , buffer ,
buffer_offset , & pgoff ) ;
size = min_t ( size_t , bytes , PAGE_SIZE - pgoff ) ;
kptr = kmap ( page ) + pgoff ;
memset ( kptr , 0 , size ) ;
kunmap ( page ) ;
bytes - = size ;
buffer_offset + = size ;
}
}
/**
/**
* binder_alloc_copy_user_to_buffer ( ) - copy src user to tgt user
* binder_alloc_copy_user_to_buffer ( ) - copy src user to tgt user
* @ alloc : binder_alloc for this proc
* @ alloc : binder_alloc for this proc