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

📄 binder.c

📁 for binder and can be set as any mode
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (ptr < node->ptr)			p = &(*p)->rb_left;		else if (ptr > node->ptr)			p = &(*p)->rb_right;		else			return NULL;	}	node = kzalloc(sizeof(*node), GFP_KERNEL);	if (node == NULL)		return NULL;	binder_stats.obj_created[BINDER_STAT_NODE]++;	rb_link_node(&node->rb_node, parent, p);	rb_insert_color(&node->rb_node, &proc->nodes);	node->debug_id = ++binder_last_id;	node->proc = proc;	node->ptr = ptr;	node->cookie = cookie;	node->work.type = BINDER_WORK_NODE;	INIT_LIST_HEAD(&node->work.entry);	INIT_LIST_HEAD(&node->async_todo);	if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)		printk(KERN_INFO "binder: %d:%d node %d u%p c%p created\n",		       proc->pid, current->pid, node->debug_id,		       node->ptr, node->cookie);	return node;}static intbinder_inc_node(struct binder_node *node, int strong, int internal,		struct list_head *target_list){	if (strong) {		if (internal) {			if (target_list == NULL &&			    node->internal_strong_refs == 0 &&			    !(node == binder_context_mgr_node &&			    node->has_strong_ref)) {				printk(KERN_ERR "binder: invalid inc strong "					"node for %d\n", node->debug_id);				return -EINVAL;			}			node->internal_strong_refs++;		} else			node->local_strong_refs++;		if (!node->has_strong_ref && target_list) {			list_del_init(&node->work.entry);			list_add_tail(&node->work.entry, target_list);		}	} else {		if (!internal)			node->local_weak_refs++;		if (!node->has_weak_ref && list_empty(&node->work.entry)) {			if (target_list == NULL) {				printk(KERN_ERR "binder: invalid inc weak node "					"for %d\n", node->debug_id);				return -EINVAL;			}			list_add_tail(&node->work.entry, target_list);		}	}	return 0;}static intbinder_dec_node(struct binder_node *node, int strong, int internal){	if (strong) {		if (internal)			node->internal_strong_refs--;		else			node->local_strong_refs--;		if (node->local_strong_refs || node->internal_strong_refs)			return 0;	} else {		if (!internal)			node->local_weak_refs--;		if (node->local_weak_refs || !hlist_empty(&node->refs))			return 0;	}	if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {		if (list_empty(&node->work.entry)) {			list_add_tail(&node->work.entry, &node->proc->todo);			wake_up_interruptible(&node->proc->wait);		}	} else {		if (hlist_empty(&node->refs) && !node->local_strong_refs &&		    !node->local_weak_refs) {			list_del_init(&node->work.entry);			if (node->proc) {				rb_erase(&node->rb_node, &node->proc->nodes);				if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)					printk(KERN_INFO "binder: refless node %d deleted\n", node->debug_id);			} else {				hlist_del(&node->dead_node);				if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)					printk(KERN_INFO "binder: dead node %d deleted\n", node->debug_id);			}			kfree(node);			binder_stats.obj_deleted[BINDER_STAT_NODE]++;		}	}	return 0;}static struct binder_ref *binder_get_ref(struct binder_proc *proc, uint32_t desc){	struct rb_node *n = proc->refs_by_desc.rb_node;	struct binder_ref *ref;	while (n) {		ref = rb_entry(n, struct binder_ref, rb_node_desc);		if (desc < ref->desc)			n = n->rb_left;		else if (desc > ref->desc)			n = n->rb_right;		else			return ref;	}	return NULL;}static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, struct binder_node *node){	struct rb_node *n;	struct rb_node **p = &proc->refs_by_node.rb_node;	struct rb_node *parent = NULL;	struct binder_ref *ref, *new_ref;	while (*p) {		parent = *p;		ref = rb_entry(parent, struct binder_ref, rb_node_node);		if (node < ref->node)			p = &(*p)->rb_left;		else if (node > ref->node)			p = &(*p)->rb_right;		else			return ref;	}	new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);	if (new_ref == NULL)		return NULL;	binder_stats.obj_created[BINDER_STAT_REF]++;	new_ref->debug_id = ++binder_last_id;	new_ref->proc = proc;	new_ref->node = node;	rb_link_node(&new_ref->rb_node_node, parent, p);	rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);	new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;	for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {		ref = rb_entry(n, struct binder_ref, rb_node_desc);		if (ref->desc > new_ref->desc)			break;		new_ref->desc = ref->desc + 1;	}	p = &proc->refs_by_desc.rb_node;	while (*p) {		parent = *p;		ref = rb_entry(parent, struct binder_ref, rb_node_desc);		if (new_ref->desc < ref->desc)			p = &(*p)->rb_left;		else if (new_ref->desc > ref->desc)			p = &(*p)->rb_right;		else			BUG();	}	rb_link_node(&new_ref->rb_node_desc, parent, p);	rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);	if (node) {		hlist_add_head(&new_ref->node_entry, &node->refs);		if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)			printk(KERN_INFO "binder: %d new ref %d desc %d for "				"node %d\n", proc->pid, new_ref->debug_id,				new_ref->desc, node->debug_id);	} else {		if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)			printk(KERN_INFO "binder: %d new ref %d desc %d for "				"dead node\n", proc->pid, new_ref->debug_id,				new_ref->desc);	}	return new_ref;}static voidbinder_delete_ref(struct binder_ref *ref){	if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)		printk(KERN_INFO "binder: %d delete ref %d desc %d for "			"node %d\n", ref->proc->pid, ref->debug_id,			ref->desc, ref->node->debug_id);	rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);	rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);	if (ref->strong)		binder_dec_node(ref->node, 1, 1);	hlist_del(&ref->node_entry);	binder_dec_node(ref->node, 0, 1);	if (ref->death) {		if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)			printk(KERN_INFO "binder: %d delete ref %d desc %d "				"has death notification\n", ref->proc->pid,				ref->debug_id, ref->desc);		list_del(&ref->death->work.entry);		kfree(ref->death);		binder_stats.obj_deleted[BINDER_STAT_DEATH]++;	}	kfree(ref);	binder_stats.obj_deleted[BINDER_STAT_REF]++;}static intbinder_inc_ref(	struct binder_ref *ref, int strong, struct list_head *target_list){	int ret;	if (strong) {		if (ref->strong == 0) {			ret = binder_inc_node(ref->node, 1, 1, target_list);			if (ret)				return ret;		}		ref->strong++;	} else {		if (ref->weak == 0) {			ret = binder_inc_node(ref->node, 0, 1, target_list);			if (ret)				return ret;		}		ref->weak++;	}	return 0;}static intbinder_dec_ref(struct binder_ref *ref, int strong){	if (strong) {		if (ref->strong == 0) {			binder_user_error("binder: %d invalid dec strong, "					  "ref %d desc %d s %d w %d\n",					  ref->proc->pid, ref->debug_id,					  ref->desc, ref->strong, ref->weak);			return -EINVAL;		}		ref->strong--;		if (ref->strong == 0) {			int ret;			ret = binder_dec_node(ref->node, strong, 1);			if (ret)				return ret;		}	} else {		if (ref->weak == 0) {			binder_user_error("binder: %d invalid dec weak, "					  "ref %d desc %d s %d w %d\n",					  ref->proc->pid, ref->debug_id,					  ref->desc, ref->strong, ref->weak);			return -EINVAL;		}		ref->weak--;	}	if (ref->strong == 0 && ref->weak == 0)		binder_delete_ref(ref);	return 0;}static voidbinder_pop_transaction(	struct binder_thread *target_thread, struct binder_transaction *t){	if (target_thread) {		BUG_ON(target_thread->transaction_stack != t);		BUG_ON(target_thread->transaction_stack->from != target_thread);		target_thread->transaction_stack =			target_thread->transaction_stack->from_parent;		t->from = NULL;	}	t->need_reply = 0;	if (t->buffer)		t->buffer->transaction = NULL;	kfree(t);	binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++;}static voidbinder_send_failed_reply(struct binder_transaction *t, uint32_t error_code){	struct binder_thread *target_thread;	BUG_ON(t->flags & TF_ONE_WAY);	while (1) {		target_thread = t->from;		if (target_thread) {			if (target_thread->return_error != BR_OK &&			   target_thread->return_error2 == BR_OK) {				target_thread->return_error2 =					target_thread->return_error;				target_thread->return_error = BR_OK;			}			if (target_thread->return_error == BR_OK) {				if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)					printk(KERN_INFO "binder: send failed reply for transaction %d to %d:%d\n",					       t->debug_id, target_thread->proc->pid, target_thread->pid);				binder_pop_transaction(target_thread, t);				target_thread->return_error = error_code;				wake_up_interruptible(&target_thread->wait);			} else {				printk(KERN_ERR "binder: reply failed, target "					"thread, %d:%d, has error code %d "					"already\n", target_thread->proc->pid,					target_thread->pid,					target_thread->return_error);			}			return;		} else {			struct binder_transaction *next = t->from_parent;			if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)				printk(KERN_INFO "binder: send failed reply "					"for transaction %d, target dead\n",					t->debug_id);			binder_pop_transaction(target_thread, t);			if (next == NULL) {				if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)					printk(KERN_INFO "binder: reply failed,"						" no target thread at root\n");				return;			}			t = next;			if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)				printk(KERN_INFO "binder: reply failed, no targ"					"et thread -- retry %d\n", t->debug_id);		}	}}static voidbinder_transaction_buffer_release(struct binder_proc *proc,			struct binder_buffer *buffer, size_t *failed_at);static voidbinder_transaction(struct binder_proc *proc, struct binder_thread *thread,	struct binder_transaction_data *tr, int reply){	struct binder_transaction *t;	struct binder_work *tcomplete;	size_t *offp, *off_end;	struct binder_proc *target_proc;	struct binder_thread *target_thread = NULL;	struct binder_node *target_node = NULL;	struct list_head *target_list;	wait_queue_head_t *target_wait;	struct binder_transaction *in_reply_to = NULL;	struct binder_transaction_log_entry *e;	uint32_t return_error;	e = binder_transaction_log_add(&binder_transaction_log);	e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);	e->from_proc = proc->pid;	e->from_thread = thread->pid;	e->target_handle = tr->target.handle;	e->data_size = tr->data_size;	e->offsets_size = tr->offsets_size;	if (reply) {		in_reply_to = thread->transaction_stack;		if (in_reply_to == NULL) {			binder_user_error("binder: %d:%d got reply transaction "					  "with no transaction stack\n",					  proc->pid, thread->pid);			return_error = BR_FAILED_REPLY;			goto err_empty_call_stack;		}		binder_set_nice(in_reply_to->saved_priority);		if (in_reply_to->to_thread != thread) {			binder_user_error("binder: %d:%d got reply transaction "				"with bad transaction stack,"				" transaction %d has target %d:%d\n",				proc->pid, thread->pid, in_reply_to->debug_id,				in_reply_to->to_proc ?				in_reply_to->to_proc->pid : 0,				in_reply_to->to_thread ?				in_reply_to->to_thread->pid : 0);			return_error = BR_FAILED_REPLY;			in_reply_to = NULL;			goto err_bad_call_stack;		}		thread->transaction_stack = in_reply_to->to_parent;		target_thread = in_reply_to->from;		if (target_thread == NULL) {			return_error = BR_DEAD_REPLY;			goto err_dead_binder;		}		if (target_thread->transaction_stack != in_reply_to) {			binder_user_error("binder: %d:%d got reply transaction "				"with bad target transaction stack %d, "				"expected %d\n",				proc->pid, thread->pid,				target_thread->transaction_stack ?				target_thread->transaction_stack->debug_id : 0,				in_reply_to->debug_id);			return_error = BR_FAILED_REPLY;			in_reply_to = NULL;			target_thread = NULL;			goto err_dead_binder;		}		target_proc = target_thread->proc;	} else {		if (tr->target.handle) {			struct binder_ref *ref;			ref = binder_get_ref(proc, tr->target.handle);			if (ref == NULL) {				binder_user_error("binder: %d:%d got "					"transaction to invalid handle\n",					proc->pid, thread->pid);				return_error = BR_FAILED_REPLY;				goto err_invalid_target_handle;			}			target_node = ref->node;		} else {			target_node = binder_context_mgr_node;			if (target_node == NULL) {				return_error = BR_DEAD_REPLY;				goto err_no_context_mgr_node;			}		}		e->to_node = target_node->debug_id;		target_proc = target_node->proc;		if (target_proc == NULL) {			return_error = BR_DEAD_REPLY;			goto err_dead_binder;		}		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {			struct binder_transaction *tmp;			tmp = thread->transaction_stack;			while (tmp) {				if (tmp->from && tmp->from->proc == target_proc)					target_thread = tmp->from;				tmp = tmp->from_parent;

⌨️ 快捷键说明

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