⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 binder.c

📁 for binder and can be set as any mode
💻 C
📖 第 1 页 / 共 5 页
字号:
					cmd == BC_INCREFS_DONE ?					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",					node_ptr, node->debug_id,					cookie, node->cookie);				break;			}			if (cmd == BC_ACQUIRE_DONE) {				if (node->pending_strong_ref == 0) {					binder_user_error("binder: %d:%d "						"BC_ACQUIRE_DONE node %d has "						"no pending acquire request\n",						proc->pid, thread->pid,						node->debug_id);					break;				}				node->pending_strong_ref = 0;			} else {				if (node->pending_weak_ref == 0) {					binder_user_error("binder: %d:%d "						"BC_INCREFS_DONE node %d has "						"no pending increfs request\n",						proc->pid, thread->pid,						node->debug_id);					break;				}				node->pending_weak_ref = 0;			}			binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);			if (binder_debug_mask & BINDER_DEBUG_USER_REFS)				printk(KERN_INFO "binder: %d:%d %s node %d ls %d lw %d\n",				       proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", node->debug_id, node->local_strong_refs, node->local_weak_refs);			break;		}		case BC_ATTEMPT_ACQUIRE:			printk(KERN_ERR "binder: BC_ATTEMPT_ACQUIRE not supported\n");			return -EINVAL;		case BC_ACQUIRE_RESULT:			printk(KERN_ERR "binder: BC_ACQUIRE_RESULT not supported\n");			return -EINVAL;		case BC_FREE_BUFFER: {			void __user *data_ptr;			struct binder_buffer *buffer;			if (get_user(data_ptr, (void * __user *)ptr))				return -EFAULT;			ptr += sizeof(void *);			buffer = binder_buffer_lookup(proc, data_ptr);			if (buffer == NULL) {				binder_user_error("binder: %d:%d "					"BC_FREE_BUFFER u%p no match\n",					proc->pid, thread->pid, data_ptr);				break;			}			if (!buffer->allow_user_free) {				binder_user_error("binder: %d:%d "					"BC_FREE_BUFFER u%p matched "					"unreturned buffer\n",					proc->pid, thread->pid, data_ptr);				break;			}			if (binder_debug_mask & BINDER_DEBUG_FREE_BUFFER)				printk(KERN_INFO "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",				       proc->pid, thread->pid, data_ptr, buffer->debug_id,				       buffer->transaction ? "active" : "finished");			if (buffer->transaction) {				buffer->transaction->buffer = NULL;				buffer->transaction = NULL;			}			if (buffer->async_transaction && buffer->target_node) {				BUG_ON(!buffer->target_node->has_async_transaction);				if (list_empty(&buffer->target_node->async_todo))					buffer->target_node->has_async_transaction = 0;				else					list_move_tail(buffer->target_node->async_todo.next, &thread->todo);			}			binder_transaction_buffer_release(proc, buffer, NULL);			binder_free_buf(proc, buffer);			break;		}		case BC_TRANSACTION:		case BC_REPLY: {			struct binder_transaction_data tr;			if (copy_from_user(&tr, ptr, sizeof(tr)))				return -EFAULT;			ptr += sizeof(tr);			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);			break;		}		case BC_REGISTER_LOOPER:			if (binder_debug_mask & BINDER_DEBUG_THREADS)				printk(KERN_INFO "binder: %d:%d BC_REGISTER_LOOPER\n",				       proc->pid, thread->pid);			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {				thread->looper |= BINDER_LOOPER_STATE_INVALID;				binder_user_error("binder: %d:%d ERROR:"					" BC_REGISTER_LOOPER called "					"after BC_ENTER_LOOPER\n",					proc->pid, thread->pid);			} else if (proc->requested_threads == 0) {				thread->looper |= BINDER_LOOPER_STATE_INVALID;				binder_user_error("binder: %d:%d ERROR:"					" BC_REGISTER_LOOPER called "					"without request\n",					proc->pid, thread->pid);			} else {				proc->requested_threads--;				proc->requested_threads_started++;			}			thread->looper |= BINDER_LOOPER_STATE_REGISTERED;			break;		case BC_ENTER_LOOPER:			if (binder_debug_mask & BINDER_DEBUG_THREADS)				printk(KERN_INFO "binder: %d:%d BC_ENTER_LOOPER\n",				       proc->pid, thread->pid);			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {				thread->looper |= BINDER_LOOPER_STATE_INVALID;				binder_user_error("binder: %d:%d ERROR:"					" BC_ENTER_LOOPER called after "					"BC_REGISTER_LOOPER\n",					proc->pid, thread->pid);			}			thread->looper |= BINDER_LOOPER_STATE_ENTERED;			break;		case BC_EXIT_LOOPER:			if (binder_debug_mask & BINDER_DEBUG_THREADS)				printk(KERN_INFO "binder: %d:%d BC_EXIT_LOOPER\n",				       proc->pid, thread->pid);			thread->looper |= BINDER_LOOPER_STATE_EXITED;			break;		case BC_REQUEST_DEATH_NOTIFICATION:		case BC_CLEAR_DEATH_NOTIFICATION: {			uint32_t target;			void __user *cookie;			struct binder_ref *ref;			struct binder_ref_death *death;			if (get_user(target, (uint32_t __user *)ptr))				return -EFAULT;			ptr += sizeof(uint32_t);			if (get_user(cookie, (void __user * __user *)ptr))				return -EFAULT;			ptr += sizeof(void *);			ref = binder_get_ref(proc, target);			if (ref == NULL) {				binder_user_error("binder: %d:%d %s "					"invalid ref %d\n",					proc->pid, thread->pid,					cmd == BC_REQUEST_DEATH_NOTIFICATION ?					"BC_REQUEST_DEATH_NOTIFICATION" :					"BC_CLEAR_DEATH_NOTIFICATION",					target);				break;			}			if (binder_debug_mask & BINDER_DEBUG_DEATH_NOTIFICATION)				printk(KERN_INFO "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",				       proc->pid, thread->pid,				       cmd == BC_REQUEST_DEATH_NOTIFICATION ?				       "BC_REQUEST_DEATH_NOTIFICATION" :				       "BC_CLEAR_DEATH_NOTIFICATION",				       cookie, ref->debug_id, ref->desc,				       ref->strong, ref->weak, ref->node->debug_id);			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {				if (ref->death) {					binder_user_error("binder: %d:%"						"d BC_REQUEST_DEATH_NOTI"						"FICATION death notific"						"ation already set\n",						proc->pid, thread->pid);					break;				}				death = kzalloc(sizeof(*death), GFP_KERNEL);				if (death == NULL) {					thread->return_error = BR_ERROR;					if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)						printk(KERN_INFO "binder: %d:%d "							"BC_REQUEST_DEATH_NOTIFICATION failed\n",							proc->pid, thread->pid);					break;				}				binder_stats.obj_created[BINDER_STAT_DEATH]++;				INIT_LIST_HEAD(&death->work.entry);				death->cookie = cookie;				ref->death = death;				if (ref->node->proc == NULL) {					ref->death->work.type = BINDER_WORK_DEAD_BINDER;					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {						list_add_tail(&ref->death->work.entry, &thread->todo);					} else {						list_add_tail(&ref->death->work.entry, &proc->todo);						wake_up_interruptible(&proc->wait);					}				}			} else {				if (ref->death == NULL) {					binder_user_error("binder: %d:%"						"d BC_CLEAR_DEATH_NOTIFI"						"CATION death notificat"						"ion not active\n",						proc->pid, thread->pid);					break;				}				death = ref->death;				if (death->cookie != cookie) {					binder_user_error("binder: %d:%"						"d BC_CLEAR_DEATH_NOTIFI"						"CATION death notificat"						"ion cookie mismatch "						"%p != %p\n",						proc->pid, thread->pid,						death->cookie, cookie);					break;				}				ref->death = NULL;				if (list_empty(&death->work.entry)) {					death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {						list_add_tail(&death->work.entry, &thread->todo);					} else {						list_add_tail(&death->work.entry, &proc->todo);						wake_up_interruptible(&proc->wait);					}				} else {					BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);					death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;				}			}		} break;		case BC_DEAD_BINDER_DONE: {			struct binder_work *w;			void __user *cookie;			struct binder_ref_death *death = NULL;			if (get_user(cookie, (void __user * __user *)ptr))				return -EFAULT;			ptr += sizeof(void *);			list_for_each_entry(w, &proc->delivered_death, entry) {				struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);				if (tmp_death->cookie == cookie) {					death = tmp_death;					break;				}			}			if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)				printk(KERN_INFO "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n",				       proc->pid, thread->pid, cookie, death);			if (death == NULL) {				binder_user_error("binder: %d:%d BC_DEAD"					"_BINDER_DONE %p not found\n",					proc->pid, thread->pid, cookie);				break;			}			list_del_init(&death->work.entry);			if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {				death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;				if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {					list_add_tail(&death->work.entry, &thread->todo);				} else {					list_add_tail(&death->work.entry, &proc->todo);					wake_up_interruptible(&proc->wait);				}			}		} break;		default:			printk(KERN_ERR "binder: %d:%d unknown command %d\n", proc->pid, thread->pid, cmd);			return -EINVAL;		}		*consumed = ptr - buffer;	}	return 0;}voidbinder_stat_br(struct binder_proc *proc, struct binder_thread *thread, uint32_t cmd){	if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {		binder_stats.br[_IOC_NR(cmd)]++;		proc->stats.br[_IOC_NR(cmd)]++;		thread->stats.br[_IOC_NR(cmd)]++;	}}static intbinder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread){	return !list_empty(&proc->todo) || (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);}static intbinder_has_thread_work(struct binder_thread *thread){	return !list_empty(&thread->todo) || thread->return_error != BR_OK ||		(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);}static intbinder_thread_read(struct binder_proc *proc, struct binder_thread *thread,	void  __user *buffer, int size, signed long *consumed, int non_block){	void __user *ptr = buffer + *consumed;	void __user *end = buffer + size;	int ret = 0;	int wait_for_proc_work;	if (*consumed == 0) {		if (put_user(BR_NOOP, (uint32_t __user *)ptr))			return -EFAULT;		ptr += sizeof(uint32_t);	}retry:	wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);	if (thread->return_error != BR_OK && ptr < end) {		if (thread->return_error2 != BR_OK) {			if (put_user(thread->return_error2, (uint32_t __user *)ptr))				return -EFAULT;			ptr += sizeof(uint32_t);			if (ptr == end)				goto done;			thread->return_error2 = BR_OK;		}		if (put_user(thread->return_error, (uint32_t __user *)ptr))			return -EFAULT;		ptr += sizeof(uint32_t);		thread->return_error = BR_OK;		goto done;	}	thread->looper |= BINDER_LOOPER_STATE_WAITING;	if (wait_for_proc_work)		proc->ready_threads++;	mutex_unlock(&binder_lock);	if (wait_for_proc_work) {		if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |					BINDER_LOOPER_STATE_ENTERED))) {			binder_user_error("binder: %d:%d ERROR: Thread waiting "				"for process work before calling BC_REGISTER_"				"LOOPER or BC_ENTER_LOOPER (state %x)\n",				proc->pid, thread->pid, thread->looper);			wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);		}		binder_set_nice(proc->default_priority);		if (non_block) {			if (!binder_has_proc_work(proc, thread))				ret = -EAGAIN;		} else			ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread));	} else {		if (non_block) {			if (!binder_has_thread_work(thread))				ret = -EAGAIN;		} else			ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));	}	mutex_lock(&binder_lock);	if (wait_for_proc_work)		proc->ready_threads--;	thread->looper &= ~BINDER_LOOPER_STATE_WAITING;	if (ret)		return ret;	while (1) {		uint32_t cmd;		struct binder_transaction_data tr;		struct binder_work *w;		struct binder_transaction *t = NULL;		if (!list_empty(&thread->todo))			w = list_first_entry(&thread->todo, struct binder_work, entry);		else if (!list_empty(&proc->todo) && wait_for_proc_work)			w = list_first_entry(&proc->todo, struct binder_work, entry);		else {			if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */				goto retry;			break;		}		if (end - ptr < sizeof(tr) + 4)			break;		switch (w->type) {		case BINDER_WORK_TRANSACTION: {			t = container_of(w, struct binder_transaction, work);		} break;		case BINDER_WORK_TRANSACTION_COMPLETE: {			cmd = BR_TRANSACTION_COMPLETE;			if (put_user(cmd, (uint32_t __user *)ptr))				return -EFAULT;			ptr += sizeof(uint32_t);			binder_stat_br(proc, thread, cmd);			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION_COMPLETE)				printk(KERN_INFO "binder: %d:%d BR_TRANSACTION_COMPLETE\n",				       proc->pid, thread->pid);			list_del(&w->entry);			kfree(w);			binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++;		} break;		case BINDER_WORK_NODE: {			struct binder_node *node = container_of(w, struct binder_node, work);			uint32_t cmd = BR_NOOP;			const char *cmd_name;			int strong = node->internal_strong_refs || node->local_strong_refs;			int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;			if (weak && !node->has_weak_ref) {				cmd = BR_INCREFS;				cmd_name = "BR_INCREFS";				node->has_weak_ref = 1;				node->pending_weak_ref = 1;				node->local_weak_refs++;			} else if (strong && !node->has_strong_ref) {				cmd = BR_ACQUIRE;				cmd_name = "BR_ACQUIRE";				node->has_strong_ref = 1;				node->pending_strong_ref = 1;				node->local_strong_refs++;			} else if (!strong && node->has_strong_ref) {				cmd = BR_RELEASE;				cmd_name = "BR_RELEASE";				node->has_strong_ref = 0;			} else if (!weak && node->has_weak_ref) {				cmd = BR_DECREFS;				cmd_name = "BR_DECREFS";				node->has_weak_ref = 0;			}			if (cmd != BR_NOOP) {				if (put_user(cmd, (uint32_t __user *)ptr))					return -EFAULT;				ptr += sizeof(uint32_t);				if (put_user(node->ptr, (void * __user *)ptr))					return -EFAULT;				ptr += sizeof

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -