diff options
Diffstat (limited to 'drivers/staging/android/binder.c')
-rw-r--r-- | drivers/staging/android/binder.c | 201 |
1 files changed, 152 insertions, 49 deletions
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 79e90fed27d..299d29d1dad 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c | |||
@@ -41,6 +41,8 @@ static int binder_last_id; | |||
41 | static struct proc_dir_entry *binder_proc_dir_entry_root; | 41 | static struct proc_dir_entry *binder_proc_dir_entry_root; |
42 | static struct proc_dir_entry *binder_proc_dir_entry_proc; | 42 | static struct proc_dir_entry *binder_proc_dir_entry_proc; |
43 | static struct hlist_head binder_dead_nodes; | 43 | static struct hlist_head binder_dead_nodes; |
44 | static HLIST_HEAD(binder_deferred_list); | ||
45 | static DEFINE_MUTEX(binder_deferred_lock); | ||
44 | 46 | ||
45 | static int binder_read_proc_proc( | 47 | static int binder_read_proc_proc( |
46 | char *page, char **start, off_t off, int count, int *eof, void *data); | 48 | char *page, char **start, off_t off, int count, int *eof, void *data); |
@@ -54,11 +56,7 @@ static int binder_read_proc_proc( | |||
54 | #define SZ_4M 0x400000 | 56 | #define SZ_4M 0x400000 |
55 | #endif | 57 | #endif |
56 | 58 | ||
57 | #ifndef __i386__ | ||
58 | #define FORBIDDEN_MMAP_FLAGS (VM_WRITE | VM_EXEC) | ||
59 | #else | ||
60 | #define FORBIDDEN_MMAP_FLAGS (VM_WRITE) | 59 | #define FORBIDDEN_MMAP_FLAGS (VM_WRITE) |
61 | #endif | ||
62 | 60 | ||
63 | #define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64) | 61 | #define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64) |
64 | 62 | ||
@@ -236,6 +234,12 @@ struct binder_buffer { | |||
236 | uint8_t data[0]; | 234 | uint8_t data[0]; |
237 | }; | 235 | }; |
238 | 236 | ||
237 | enum { | ||
238 | BINDER_DEFERRED_PUT_FILES = 0x01, | ||
239 | BINDER_DEFERRED_FLUSH = 0x02, | ||
240 | BINDER_DEFERRED_RELEASE = 0x04, | ||
241 | }; | ||
242 | |||
239 | struct binder_proc { | 243 | struct binder_proc { |
240 | struct hlist_node proc_node; | 244 | struct hlist_node proc_node; |
241 | struct rb_root threads; | 245 | struct rb_root threads; |
@@ -245,8 +249,11 @@ struct binder_proc { | |||
245 | int pid; | 249 | int pid; |
246 | struct vm_area_struct *vma; | 250 | struct vm_area_struct *vma; |
247 | struct task_struct *tsk; | 251 | struct task_struct *tsk; |
252 | struct files_struct *files; | ||
253 | struct hlist_node deferred_work_node; | ||
254 | int deferred_work; | ||
248 | void *buffer; | 255 | void *buffer; |
249 | size_t user_buffer_offset; | 256 | ptrdiff_t user_buffer_offset; |
250 | 257 | ||
251 | struct list_head buffers; | 258 | struct list_head buffers; |
252 | struct rb_root free_buffers; | 259 | struct rb_root free_buffers; |
@@ -310,12 +317,14 @@ struct binder_transaction { | |||
310 | uid_t sender_euid; | 317 | uid_t sender_euid; |
311 | }; | 318 | }; |
312 | 319 | ||
320 | static void binder_defer_work(struct binder_proc *proc, int defer); | ||
321 | |||
313 | /* | 322 | /* |
314 | * copied from get_unused_fd_flags | 323 | * copied from get_unused_fd_flags |
315 | */ | 324 | */ |
316 | int task_get_unused_fd_flags(struct task_struct *tsk, int flags) | 325 | int task_get_unused_fd_flags(struct binder_proc *proc, int flags) |
317 | { | 326 | { |
318 | struct files_struct *files = get_files_struct(tsk); | 327 | struct files_struct *files = proc->files; |
319 | int fd, error; | 328 | int fd, error; |
320 | struct fdtable *fdt; | 329 | struct fdtable *fdt; |
321 | unsigned long rlim_cur; | 330 | unsigned long rlim_cur; |
@@ -337,9 +346,9 @@ repeat: | |||
337 | * will limit the total number of files that can be opened. | 346 | * will limit the total number of files that can be opened. |
338 | */ | 347 | */ |
339 | rlim_cur = 0; | 348 | rlim_cur = 0; |
340 | if (lock_task_sighand(tsk, &irqs)) { | 349 | if (lock_task_sighand(proc->tsk, &irqs)) { |
341 | rlim_cur = tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur; | 350 | rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur; |
342 | unlock_task_sighand(tsk, &irqs); | 351 | unlock_task_sighand(proc->tsk, &irqs); |
343 | } | 352 | } |
344 | if (fd >= rlim_cur) | 353 | if (fd >= rlim_cur) |
345 | goto out; | 354 | goto out; |
@@ -375,7 +384,6 @@ repeat: | |||
375 | 384 | ||
376 | out: | 385 | out: |
377 | spin_unlock(&files->file_lock); | 386 | spin_unlock(&files->file_lock); |
378 | put_files_struct(files); | ||
379 | return error; | 387 | return error; |
380 | } | 388 | } |
381 | 389 | ||
@@ -383,9 +391,9 @@ out: | |||
383 | * copied from fd_install | 391 | * copied from fd_install |
384 | */ | 392 | */ |
385 | static void task_fd_install( | 393 | static void task_fd_install( |
386 | struct task_struct *tsk, unsigned int fd, struct file *file) | 394 | struct binder_proc *proc, unsigned int fd, struct file *file) |
387 | { | 395 | { |
388 | struct files_struct *files = get_files_struct(tsk); | 396 | struct files_struct *files = proc->files; |
389 | struct fdtable *fdt; | 397 | struct fdtable *fdt; |
390 | 398 | ||
391 | if (files == NULL) | 399 | if (files == NULL) |
@@ -396,7 +404,6 @@ static void task_fd_install( | |||
396 | BUG_ON(fdt->fd[fd] != NULL); | 404 | BUG_ON(fdt->fd[fd] != NULL); |
397 | rcu_assign_pointer(fdt->fd[fd], file); | 405 | rcu_assign_pointer(fdt->fd[fd], file); |
398 | spin_unlock(&files->file_lock); | 406 | spin_unlock(&files->file_lock); |
399 | put_files_struct(files); | ||
400 | } | 407 | } |
401 | 408 | ||
402 | /* | 409 | /* |
@@ -413,10 +420,10 @@ static void __put_unused_fd(struct files_struct *files, unsigned int fd) | |||
413 | /* | 420 | /* |
414 | * copied from sys_close | 421 | * copied from sys_close |
415 | */ | 422 | */ |
416 | static long task_close_fd(struct task_struct *tsk, unsigned int fd) | 423 | static long task_close_fd(struct binder_proc *proc, unsigned int fd) |
417 | { | 424 | { |
418 | struct file *filp; | 425 | struct file *filp; |
419 | struct files_struct *files = get_files_struct(tsk); | 426 | struct files_struct *files = proc->files; |
420 | struct fdtable *fdt; | 427 | struct fdtable *fdt; |
421 | int retval; | 428 | int retval; |
422 | 429 | ||
@@ -443,12 +450,10 @@ static long task_close_fd(struct task_struct *tsk, unsigned int fd) | |||
443 | retval == -ERESTART_RESTARTBLOCK)) | 450 | retval == -ERESTART_RESTARTBLOCK)) |
444 | retval = -EINTR; | 451 | retval = -EINTR; |
445 | 452 | ||
446 | put_files_struct(files); | ||
447 | return retval; | 453 | return retval; |
448 | 454 | ||
449 | out_unlock: | 455 | out_unlock: |
450 | spin_unlock(&files->file_lock); | 456 | spin_unlock(&files->file_lock); |
451 | put_files_struct(files); | ||
452 | return -EBADF; | 457 | return -EBADF; |
453 | } | 458 | } |
454 | 459 | ||
@@ -618,7 +623,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, | |||
618 | proc->pid, page_addr); | 623 | proc->pid, page_addr); |
619 | goto err_map_kernel_failed; | 624 | goto err_map_kernel_failed; |
620 | } | 625 | } |
621 | user_page_addr = (size_t)page_addr + proc->user_buffer_offset; | 626 | user_page_addr = |
627 | (uintptr_t)page_addr + proc->user_buffer_offset; | ||
622 | ret = vm_insert_page(vma, user_page_addr, page[0]); | 628 | ret = vm_insert_page(vma, user_page_addr, page[0]); |
623 | if (ret) { | 629 | if (ret) { |
624 | printk(KERN_ERR "binder: %d: binder_alloc_buf failed " | 630 | printk(KERN_ERR "binder: %d: binder_alloc_buf failed " |
@@ -639,7 +645,7 @@ free_range: | |||
639 | page_addr -= PAGE_SIZE) { | 645 | page_addr -= PAGE_SIZE) { |
640 | page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; | 646 | page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; |
641 | if (vma) | 647 | if (vma) |
642 | zap_page_range(vma, (size_t)page_addr + | 648 | zap_page_range(vma, (uintptr_t)page_addr + |
643 | proc->user_buffer_offset, PAGE_SIZE, NULL); | 649 | proc->user_buffer_offset, PAGE_SIZE, NULL); |
644 | err_vm_insert_page_failed: | 650 | err_vm_insert_page_failed: |
645 | unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); | 651 | unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); |
@@ -720,18 +726,19 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, | |||
720 | "er %p size %zd\n", proc->pid, size, buffer, buffer_size); | 726 | "er %p size %zd\n", proc->pid, size, buffer, buffer_size); |
721 | 727 | ||
722 | has_page_addr = | 728 | has_page_addr = |
723 | (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK); | 729 | (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); |
724 | if (n == NULL) { | 730 | if (n == NULL) { |
725 | if (size + sizeof(struct binder_buffer) + 4 >= buffer_size) | 731 | if (size + sizeof(struct binder_buffer) + 4 >= buffer_size) |
726 | buffer_size = size; /* no room for other buffers */ | 732 | buffer_size = size; /* no room for other buffers */ |
727 | else | 733 | else |
728 | buffer_size = size + sizeof(struct binder_buffer); | 734 | buffer_size = size + sizeof(struct binder_buffer); |
729 | } | 735 | } |
730 | end_page_addr = (void *)PAGE_ALIGN((size_t)buffer->data + buffer_size); | 736 | end_page_addr = |
737 | (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size); | ||
731 | if (end_page_addr > has_page_addr) | 738 | if (end_page_addr > has_page_addr) |
732 | end_page_addr = has_page_addr; | 739 | end_page_addr = has_page_addr; |
733 | if (binder_update_page_range(proc, 1, | 740 | if (binder_update_page_range(proc, 1, |
734 | (void *)PAGE_ALIGN((size_t)buffer->data), end_page_addr, NULL)) | 741 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) |
735 | return NULL; | 742 | return NULL; |
736 | 743 | ||
737 | rb_erase(best_fit, &proc->free_buffers); | 744 | rb_erase(best_fit, &proc->free_buffers); |
@@ -762,12 +769,12 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, | |||
762 | 769 | ||
763 | static void *buffer_start_page(struct binder_buffer *buffer) | 770 | static void *buffer_start_page(struct binder_buffer *buffer) |
764 | { | 771 | { |
765 | return (void *)((size_t)buffer & PAGE_MASK); | 772 | return (void *)((uintptr_t)buffer & PAGE_MASK); |
766 | } | 773 | } |
767 | 774 | ||
768 | static void *buffer_end_page(struct binder_buffer *buffer) | 775 | static void *buffer_end_page(struct binder_buffer *buffer) |
769 | { | 776 | { |
770 | return (void *)(((size_t)(buffer + 1) - 1) & PAGE_MASK); | 777 | return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK); |
771 | } | 778 | } |
772 | 779 | ||
773 | static void binder_delete_free_buffer( | 780 | static void binder_delete_free_buffer( |
@@ -845,8 +852,8 @@ static void binder_free_buf( | |||
845 | } | 852 | } |
846 | 853 | ||
847 | binder_update_page_range(proc, 0, | 854 | binder_update_page_range(proc, 0, |
848 | (void *)PAGE_ALIGN((size_t)buffer->data), | 855 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), |
849 | (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK), | 856 | (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), |
850 | NULL); | 857 | NULL); |
851 | rb_erase(&buffer->rb_node, &proc->allocated_buffers); | 858 | rb_erase(&buffer->rb_node, &proc->allocated_buffers); |
852 | buffer->free = 1; | 859 | buffer->free = 1; |
@@ -1345,6 +1352,17 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread, | |||
1345 | if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { | 1352 | if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { |
1346 | struct binder_transaction *tmp; | 1353 | struct binder_transaction *tmp; |
1347 | tmp = thread->transaction_stack; | 1354 | tmp = thread->transaction_stack; |
1355 | if (tmp->to_thread != thread) { | ||
1356 | binder_user_error("binder: %d:%d got new " | ||
1357 | "transaction with bad transaction stack" | ||
1358 | ", transaction %d has target %d:%d\n", | ||
1359 | proc->pid, thread->pid, tmp->debug_id, | ||
1360 | tmp->to_proc ? tmp->to_proc->pid : 0, | ||
1361 | tmp->to_thread ? | ||
1362 | tmp->to_thread->pid : 0); | ||
1363 | return_error = BR_FAILED_REPLY; | ||
1364 | goto err_bad_call_stack; | ||
1365 | } | ||
1348 | while (tmp) { | 1366 | while (tmp) { |
1349 | if (tmp->from && tmp->from->proc == target_proc) | 1367 | if (tmp->from && tmp->from->proc == target_proc) |
1350 | target_thread = tmp->from; | 1368 | target_thread = tmp->from; |
@@ -1434,10 +1452,19 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread, | |||
1434 | return_error = BR_FAILED_REPLY; | 1452 | return_error = BR_FAILED_REPLY; |
1435 | goto err_copy_data_failed; | 1453 | goto err_copy_data_failed; |
1436 | } | 1454 | } |
1455 | if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) { | ||
1456 | binder_user_error("binder: %d:%d got transaction with " | ||
1457 | "invalid offsets size, %zd\n", | ||
1458 | proc->pid, thread->pid, tr->offsets_size); | ||
1459 | return_error = BR_FAILED_REPLY; | ||
1460 | goto err_bad_offset; | ||
1461 | } | ||
1437 | off_end = (void *)offp + tr->offsets_size; | 1462 | off_end = (void *)offp + tr->offsets_size; |
1438 | for (; offp < off_end; offp++) { | 1463 | for (; offp < off_end; offp++) { |
1439 | struct flat_binder_object *fp; | 1464 | struct flat_binder_object *fp; |
1440 | if (*offp > t->buffer->data_size - sizeof(*fp)) { | 1465 | if (*offp > t->buffer->data_size - sizeof(*fp) || |
1466 | t->buffer->data_size < sizeof(*fp) || | ||
1467 | !IS_ALIGNED(*offp, sizeof(void *))) { | ||
1441 | binder_user_error("binder: %d:%d got transaction with " | 1468 | binder_user_error("binder: %d:%d got transaction with " |
1442 | "invalid offset, %zd\n", | 1469 | "invalid offset, %zd\n", |
1443 | proc->pid, thread->pid, *offp); | 1470 | proc->pid, thread->pid, *offp); |
@@ -1544,13 +1571,13 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread, | |||
1544 | return_error = BR_FAILED_REPLY; | 1571 | return_error = BR_FAILED_REPLY; |
1545 | goto err_fget_failed; | 1572 | goto err_fget_failed; |
1546 | } | 1573 | } |
1547 | target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC); | 1574 | target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC); |
1548 | if (target_fd < 0) { | 1575 | if (target_fd < 0) { |
1549 | fput(file); | 1576 | fput(file); |
1550 | return_error = BR_FAILED_REPLY; | 1577 | return_error = BR_FAILED_REPLY; |
1551 | goto err_get_unused_fd_failed; | 1578 | goto err_get_unused_fd_failed; |
1552 | } | 1579 | } |
1553 | task_fd_install(target_proc->tsk, target_fd, file); | 1580 | task_fd_install(target_proc, target_fd, file); |
1554 | if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) | 1581 | if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) |
1555 | printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd); | 1582 | printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd); |
1556 | /* TODO: fput? */ | 1583 | /* TODO: fput? */ |
@@ -1655,7 +1682,9 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer | |||
1655 | off_end = (void *)offp + buffer->offsets_size; | 1682 | off_end = (void *)offp + buffer->offsets_size; |
1656 | for (; offp < off_end; offp++) { | 1683 | for (; offp < off_end; offp++) { |
1657 | struct flat_binder_object *fp; | 1684 | struct flat_binder_object *fp; |
1658 | if (*offp > buffer->data_size - sizeof(*fp)) { | 1685 | if (*offp > buffer->data_size - sizeof(*fp) || |
1686 | buffer->data_size < sizeof(*fp) || | ||
1687 | !IS_ALIGNED(*offp, sizeof(void *))) { | ||
1659 | printk(KERN_ERR "binder: transaction release %d bad" | 1688 | printk(KERN_ERR "binder: transaction release %d bad" |
1660 | "offset %zd, size %zd\n", debug_id, *offp, buffer->data_size); | 1689 | "offset %zd, size %zd\n", debug_id, *offp, buffer->data_size); |
1661 | continue; | 1690 | continue; |
@@ -1691,7 +1720,7 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer | |||
1691 | if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) | 1720 | if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) |
1692 | printk(KERN_INFO " fd %ld\n", fp->handle); | 1721 | printk(KERN_INFO " fd %ld\n", fp->handle); |
1693 | if (failed_at) | 1722 | if (failed_at) |
1694 | task_close_fd(proc->tsk, fp->handle); | 1723 | task_close_fd(proc, fp->handle); |
1695 | break; | 1724 | break; |
1696 | 1725 | ||
1697 | default: | 1726 | default: |
@@ -2340,7 +2369,7 @@ retry: | |||
2340 | 2369 | ||
2341 | tr.data_size = t->buffer->data_size; | 2370 | tr.data_size = t->buffer->data_size; |
2342 | tr.offsets_size = t->buffer->offsets_size; | 2371 | tr.offsets_size = t->buffer->offsets_size; |
2343 | tr.data.ptr.buffer = (void *)((void *)t->buffer->data + proc->user_buffer_offset); | 2372 | tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset; |
2344 | tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); | 2373 | tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); |
2345 | 2374 | ||
2346 | if (put_user(cmd, (uint32_t __user *)ptr)) | 2375 | if (put_user(cmd, (uint32_t __user *)ptr)) |
@@ -2656,6 +2685,7 @@ static void binder_vma_open(struct vm_area_struct *vma) | |||
2656 | (unsigned long)pgprot_val(vma->vm_page_prot)); | 2685 | (unsigned long)pgprot_val(vma->vm_page_prot)); |
2657 | dump_stack(); | 2686 | dump_stack(); |
2658 | } | 2687 | } |
2688 | |||
2659 | static void binder_vma_close(struct vm_area_struct *vma) | 2689 | static void binder_vma_close(struct vm_area_struct *vma) |
2660 | { | 2690 | { |
2661 | struct binder_proc *proc = vma->vm_private_data; | 2691 | struct binder_proc *proc = vma->vm_private_data; |
@@ -2666,6 +2696,7 @@ static void binder_vma_close(struct vm_area_struct *vma) | |||
2666 | (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, | 2696 | (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, |
2667 | (unsigned long)pgprot_val(vma->vm_page_prot)); | 2697 | (unsigned long)pgprot_val(vma->vm_page_prot)); |
2668 | proc->vma = NULL; | 2698 | proc->vma = NULL; |
2699 | binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES); | ||
2669 | } | 2700 | } |
2670 | 2701 | ||
2671 | static struct vm_operations_struct binder_vm_ops = { | 2702 | static struct vm_operations_struct binder_vm_ops = { |
@@ -2698,6 +2729,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) | |||
2698 | } | 2729 | } |
2699 | vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; | 2730 | vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; |
2700 | 2731 | ||
2732 | if (proc->buffer) { | ||
2733 | ret = -EBUSY; | ||
2734 | failure_string = "already mapped"; | ||
2735 | goto err_already_mapped; | ||
2736 | } | ||
2737 | |||
2701 | area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); | 2738 | area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); |
2702 | if (area == NULL) { | 2739 | if (area == NULL) { |
2703 | ret = -ENOMEM; | 2740 | ret = -ENOMEM; |
@@ -2705,7 +2742,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) | |||
2705 | goto err_get_vm_area_failed; | 2742 | goto err_get_vm_area_failed; |
2706 | } | 2743 | } |
2707 | proc->buffer = area->addr; | 2744 | proc->buffer = area->addr; |
2708 | proc->user_buffer_offset = vma->vm_start - (size_t)proc->buffer; | 2745 | proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer; |
2709 | 2746 | ||
2710 | #ifdef CONFIG_CPU_CACHE_VIPT | 2747 | #ifdef CONFIG_CPU_CACHE_VIPT |
2711 | if (cache_is_vipt_aliasing()) { | 2748 | if (cache_is_vipt_aliasing()) { |
@@ -2738,6 +2775,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) | |||
2738 | binder_insert_free_buffer(proc, buffer); | 2775 | binder_insert_free_buffer(proc, buffer); |
2739 | proc->free_async_space = proc->buffer_size / 2; | 2776 | proc->free_async_space = proc->buffer_size / 2; |
2740 | barrier(); | 2777 | barrier(); |
2778 | proc->files = get_files_struct(current); | ||
2741 | proc->vma = vma; | 2779 | proc->vma = vma; |
2742 | 2780 | ||
2743 | /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ | 2781 | /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ |
@@ -2745,10 +2783,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) | |||
2745 | 2783 | ||
2746 | err_alloc_small_buf_failed: | 2784 | err_alloc_small_buf_failed: |
2747 | kfree(proc->pages); | 2785 | kfree(proc->pages); |
2786 | proc->pages = NULL; | ||
2748 | err_alloc_pages_failed: | 2787 | err_alloc_pages_failed: |
2749 | vfree(proc->buffer); | 2788 | vfree(proc->buffer); |
2789 | proc->buffer = NULL; | ||
2750 | err_get_vm_area_failed: | 2790 | err_get_vm_area_failed: |
2751 | mutex_unlock(&binder_lock); | 2791 | err_already_mapped: |
2752 | err_bad_arg: | 2792 | err_bad_arg: |
2753 | printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret); | 2793 | printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret); |
2754 | return ret; | 2794 | return ret; |
@@ -2780,6 +2820,7 @@ static int binder_open(struct inode *nodp, struct file *filp) | |||
2780 | if (binder_proc_dir_entry_proc) { | 2820 | if (binder_proc_dir_entry_proc) { |
2781 | char strbuf[11]; | 2821 | char strbuf[11]; |
2782 | snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); | 2822 | snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); |
2823 | remove_proc_entry(strbuf, binder_proc_dir_entry_proc); | ||
2783 | create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc); | 2824 | create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc); |
2784 | } | 2825 | } |
2785 | 2826 | ||
@@ -2788,11 +2829,17 @@ static int binder_open(struct inode *nodp, struct file *filp) | |||
2788 | 2829 | ||
2789 | static int binder_flush(struct file *filp, fl_owner_t id) | 2830 | static int binder_flush(struct file *filp, fl_owner_t id) |
2790 | { | 2831 | { |
2791 | struct rb_node *n; | ||
2792 | struct binder_proc *proc = filp->private_data; | 2832 | struct binder_proc *proc = filp->private_data; |
2793 | int wake_count = 0; | ||
2794 | 2833 | ||
2795 | mutex_lock(&binder_lock); | 2834 | binder_defer_work(proc, BINDER_DEFERRED_FLUSH); |
2835 | |||
2836 | return 0; | ||
2837 | } | ||
2838 | |||
2839 | static void binder_deferred_flush(struct binder_proc *proc) | ||
2840 | { | ||
2841 | struct rb_node *n; | ||
2842 | int wake_count = 0; | ||
2796 | for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { | 2843 | for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { |
2797 | struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); | 2844 | struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); |
2798 | thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; | 2845 | thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; |
@@ -2802,28 +2849,35 @@ static int binder_flush(struct file *filp, fl_owner_t id) | |||
2802 | } | 2849 | } |
2803 | } | 2850 | } |
2804 | wake_up_interruptible_all(&proc->wait); | 2851 | wake_up_interruptible_all(&proc->wait); |
2805 | mutex_unlock(&binder_lock); | ||
2806 | 2852 | ||
2807 | if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) | 2853 | if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) |
2808 | printk(KERN_INFO "binder_flush: %d woke %d threads\n", proc->pid, wake_count); | 2854 | printk(KERN_INFO "binder_flush: %d woke %d threads\n", proc->pid, wake_count); |
2809 | |||
2810 | return 0; | ||
2811 | } | 2855 | } |
2812 | 2856 | ||
2813 | static int binder_release(struct inode *nodp, struct file *filp) | 2857 | static int binder_release(struct inode *nodp, struct file *filp) |
2814 | { | 2858 | { |
2815 | struct hlist_node *pos; | ||
2816 | struct binder_transaction *t; | ||
2817 | struct rb_node *n; | ||
2818 | struct binder_proc *proc = filp->private_data; | 2859 | struct binder_proc *proc = filp->private_data; |
2819 | int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count; | ||
2820 | |||
2821 | if (binder_proc_dir_entry_proc) { | 2860 | if (binder_proc_dir_entry_proc) { |
2822 | char strbuf[11]; | 2861 | char strbuf[11]; |
2823 | snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); | 2862 | snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); |
2824 | remove_proc_entry(strbuf, binder_proc_dir_entry_proc); | 2863 | remove_proc_entry(strbuf, binder_proc_dir_entry_proc); |
2825 | } | 2864 | } |
2826 | mutex_lock(&binder_lock); | 2865 | |
2866 | binder_defer_work(proc, BINDER_DEFERRED_RELEASE); | ||
2867 | |||
2868 | return 0; | ||
2869 | } | ||
2870 | |||
2871 | static void binder_deferred_release(struct binder_proc *proc) | ||
2872 | { | ||
2873 | struct hlist_node *pos; | ||
2874 | struct binder_transaction *t; | ||
2875 | struct rb_node *n; | ||
2876 | int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count; | ||
2877 | |||
2878 | BUG_ON(proc->vma); | ||
2879 | BUG_ON(proc->files); | ||
2880 | |||
2827 | hlist_del(&proc->proc_node); | 2881 | hlist_del(&proc->proc_node); |
2828 | if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) { | 2882 | if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) { |
2829 | if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER) | 2883 | if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER) |
@@ -2897,7 +2951,6 @@ static int binder_release(struct inode *nodp, struct file *filp) | |||
2897 | } | 2951 | } |
2898 | 2952 | ||
2899 | binder_stats.obj_deleted[BINDER_STAT_PROC]++; | 2953 | binder_stats.obj_deleted[BINDER_STAT_PROC]++; |
2900 | mutex_unlock(&binder_lock); | ||
2901 | 2954 | ||
2902 | page_count = 0; | 2955 | page_count = 0; |
2903 | if (proc->pages) { | 2956 | if (proc->pages) { |
@@ -2921,7 +2974,57 @@ static int binder_release(struct inode *nodp, struct file *filp) | |||
2921 | proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count); | 2974 | proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count); |
2922 | 2975 | ||
2923 | kfree(proc); | 2976 | kfree(proc); |
2924 | return 0; | 2977 | } |
2978 | |||
2979 | static void binder_deferred_func(struct work_struct *work) | ||
2980 | { | ||
2981 | struct binder_proc *proc; | ||
2982 | struct files_struct *files; | ||
2983 | |||
2984 | int defer; | ||
2985 | do { | ||
2986 | mutex_lock(&binder_lock); | ||
2987 | mutex_lock(&binder_deferred_lock); | ||
2988 | if (!hlist_empty(&binder_deferred_list)) { | ||
2989 | proc = hlist_entry(binder_deferred_list.first, | ||
2990 | struct binder_proc, deferred_work_node); | ||
2991 | hlist_del_init(&proc->deferred_work_node); | ||
2992 | defer = proc->deferred_work; | ||
2993 | proc->deferred_work = 0; | ||
2994 | } else { | ||
2995 | proc = NULL; | ||
2996 | defer = 0; | ||
2997 | } | ||
2998 | mutex_unlock(&binder_deferred_lock); | ||
2999 | |||
3000 | files = NULL; | ||
3001 | if (defer & BINDER_DEFERRED_PUT_FILES) | ||
3002 | if ((files = proc->files)) | ||
3003 | proc->files = NULL; | ||
3004 | |||
3005 | if (defer & BINDER_DEFERRED_FLUSH) | ||
3006 | binder_deferred_flush(proc); | ||
3007 | |||
3008 | if (defer & BINDER_DEFERRED_RELEASE) | ||
3009 | binder_deferred_release(proc); /* frees proc */ | ||
3010 | |||
3011 | mutex_unlock(&binder_lock); | ||
3012 | if (files) | ||
3013 | put_files_struct(files); | ||
3014 | } while (proc); | ||
3015 | } | ||
3016 | static DECLARE_WORK(binder_deferred_work, binder_deferred_func); | ||
3017 | |||
3018 | static void binder_defer_work(struct binder_proc *proc, int defer) | ||
3019 | { | ||
3020 | mutex_lock(&binder_deferred_lock); | ||
3021 | proc->deferred_work |= defer; | ||
3022 | if (hlist_unhashed(&proc->deferred_work_node)) { | ||
3023 | hlist_add_head(&proc->deferred_work_node, | ||
3024 | &binder_deferred_list); | ||
3025 | schedule_work(&binder_deferred_work); | ||
3026 | } | ||
3027 | mutex_unlock(&binder_deferred_lock); | ||
2925 | } | 3028 | } |
2926 | 3029 | ||
2927 | static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t) | 3030 | static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t) |