mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	binder: refactor binder ref inc/dec for thread safety
Once locks are added, binder_ref's will only be accessed safely with the proc lock held. Refactor the inc/dec paths to make them atomic with the binder_get_ref* paths and node inc/dec. For example, instead of: ref = binder_get_ref(proc, handle, strong); ... binder_dec_ref(ref, strong); we now have: ret = binder_dec_ref_for_handle(proc, handle, strong, &rdata); Since the actual ref is no longer exposed to callers, a new struct binder_ref_data is introduced which can be used to return a copy of ref state. Signed-off-by: Todd Kjos <tkjos@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									7a4408c6bd
								
							
						
					
					
						commit
						372e3147df
					
				
					 2 changed files with 379 additions and 137 deletions
				
			
		| 
						 | 
				
			
			@ -291,20 +291,51 @@ struct binder_ref_death {
 | 
			
		|||
	binder_uintptr_t cookie;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct binder_ref_data - binder_ref counts and id
 | 
			
		||||
 * @debug_id:        unique ID for the ref
 | 
			
		||||
 * @desc:            unique userspace handle for ref
 | 
			
		||||
 * @strong:          strong ref count (debugging only if not locked)
 | 
			
		||||
 * @weak:            weak ref count (debugging only if not locked)
 | 
			
		||||
 *
 | 
			
		||||
 * Structure to hold ref count and ref id information. Since
 | 
			
		||||
 * the actual ref can only be accessed with a lock, this structure
 | 
			
		||||
 * is used to return information about the ref to callers of
 | 
			
		||||
 * ref inc/dec functions.
 | 
			
		||||
 */
 | 
			
		||||
struct binder_ref_data {
 | 
			
		||||
	int debug_id;
 | 
			
		||||
	uint32_t desc;
 | 
			
		||||
	int strong;
 | 
			
		||||
	int weak;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct binder_ref - struct to track references on nodes
 | 
			
		||||
 * @data:        binder_ref_data containing id, handle, and current refcounts
 | 
			
		||||
 * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
 | 
			
		||||
 * @rb_node_node: node for lookup by @node in proc's rb_tree
 | 
			
		||||
 * @node_entry:  list entry for node->refs list in target node
 | 
			
		||||
 * @proc:        binder_proc containing ref
 | 
			
		||||
 * @node:        binder_node of target node. When cleaning up a
 | 
			
		||||
 *               ref for deletion in binder_cleanup_ref, a non-NULL
 | 
			
		||||
 *               @node indicates the node must be freed
 | 
			
		||||
 * @death:       pointer to death notification (ref_death) if requested
 | 
			
		||||
 *
 | 
			
		||||
 * Structure to track references from procA to target node (on procB). This
 | 
			
		||||
 * structure is unsafe to access without holding @proc->outer_lock.
 | 
			
		||||
 */
 | 
			
		||||
struct binder_ref {
 | 
			
		||||
	/* Lookups needed: */
 | 
			
		||||
	/*   node + proc => ref (transaction) */
 | 
			
		||||
	/*   desc + proc => ref (transaction, inc/dec ref) */
 | 
			
		||||
	/*   node => refs + procs (proc exit) */
 | 
			
		||||
	int debug_id;
 | 
			
		||||
	struct binder_ref_data data;
 | 
			
		||||
	struct rb_node rb_node_desc;
 | 
			
		||||
	struct rb_node rb_node_node;
 | 
			
		||||
	struct hlist_node node_entry;
 | 
			
		||||
	struct binder_proc *proc;
 | 
			
		||||
	struct binder_node *node;
 | 
			
		||||
	uint32_t desc;
 | 
			
		||||
	int strong;
 | 
			
		||||
	int weak;
 | 
			
		||||
	struct binder_ref_death *death;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -627,11 +658,11 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc,
 | 
			
		|||
	while (n) {
 | 
			
		||||
		ref = rb_entry(n, struct binder_ref, rb_node_desc);
 | 
			
		||||
 | 
			
		||||
		if (desc < ref->desc) {
 | 
			
		||||
		if (desc < ref->data.desc) {
 | 
			
		||||
			n = n->rb_left;
 | 
			
		||||
		} else if (desc > ref->desc) {
 | 
			
		||||
		} else if (desc > ref->data.desc) {
 | 
			
		||||
			n = n->rb_right;
 | 
			
		||||
		} else if (need_strong_ref && !ref->strong) {
 | 
			
		||||
		} else if (need_strong_ref && !ref->data.strong) {
 | 
			
		||||
			binder_user_error("tried to use weak ref as strong ref\n");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -641,14 +672,33 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc,
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_get_ref_for_node() - get the ref associated with given node
 | 
			
		||||
 * @proc:	binder_proc that owns the ref
 | 
			
		||||
 * @node:	binder_node of target
 | 
			
		||||
 * @new_ref:	newly allocated binder_ref to be initialized or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Look up the ref for the given node and return it if it exists
 | 
			
		||||
 *
 | 
			
		||||
 * If it doesn't exist and the caller provides a newly allocated
 | 
			
		||||
 * ref, initialize the fields of the newly allocated ref and insert
 | 
			
		||||
 * into the given proc rb_trees and node refs list.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:	the ref for node. It is possible that another thread
 | 
			
		||||
 *		allocated/initialized the ref first in which case the
 | 
			
		||||
 *		returned ref would be different than the passed-in
 | 
			
		||||
 *		new_ref. new_ref must be kfree'd by the caller in
 | 
			
		||||
 *		this case.
 | 
			
		||||
 */
 | 
			
		||||
static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
 | 
			
		||||
						  struct binder_node *node)
 | 
			
		||||
						  struct binder_node *node,
 | 
			
		||||
						  struct binder_ref *new_ref)
 | 
			
		||||
{
 | 
			
		||||
	struct rb_node *n;
 | 
			
		||||
	struct binder_context *context = proc->context;
 | 
			
		||||
	struct rb_node **p = &proc->refs_by_node.rb_node;
 | 
			
		||||
	struct rb_node *parent = NULL;
 | 
			
		||||
	struct binder_ref *ref, *new_ref;
 | 
			
		||||
	struct binder_context *context = proc->context;
 | 
			
		||||
	struct binder_ref *ref;
 | 
			
		||||
	struct rb_node *n;
 | 
			
		||||
 | 
			
		||||
	while (*p) {
 | 
			
		||||
		parent = *p;
 | 
			
		||||
| 
						 | 
				
			
			@ -661,22 +711,22 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
 | 
			
		|||
		else
 | 
			
		||||
			return ref;
 | 
			
		||||
	}
 | 
			
		||||
	new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
 | 
			
		||||
	if (new_ref == NULL)
 | 
			
		||||
	if (!new_ref)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	binder_stats_created(BINDER_STAT_REF);
 | 
			
		||||
	new_ref->debug_id = atomic_inc_return(&binder_last_id);
 | 
			
		||||
	new_ref->data.debug_id = atomic_inc_return(&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 == context->binder_context_mgr_node) ? 0 : 1;
 | 
			
		||||
	new_ref->data.desc = (node == context->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)
 | 
			
		||||
		if (ref->data.desc > new_ref->data.desc)
 | 
			
		||||
			break;
 | 
			
		||||
		new_ref->desc = ref->desc + 1;
 | 
			
		||||
		new_ref->data.desc = ref->data.desc + 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = &proc->refs_by_desc.rb_node;
 | 
			
		||||
| 
						 | 
				
			
			@ -684,9 +734,9 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
 | 
			
		|||
		parent = *p;
 | 
			
		||||
		ref = rb_entry(parent, struct binder_ref, rb_node_desc);
 | 
			
		||||
 | 
			
		||||
		if (new_ref->desc < ref->desc)
 | 
			
		||||
		if (new_ref->data.desc < ref->data.desc)
 | 
			
		||||
			p = &(*p)->rb_left;
 | 
			
		||||
		else if (new_ref->desc > ref->desc)
 | 
			
		||||
		else if (new_ref->data.desc > ref->data.desc)
 | 
			
		||||
			p = &(*p)->rb_right;
 | 
			
		||||
		else
 | 
			
		||||
			BUG();
 | 
			
		||||
| 
						 | 
				
			
			@ -697,89 +747,267 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
 | 
			
		|||
 | 
			
		||||
	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 | 
			
		||||
		     "%d new ref %d desc %d for node %d\n",
 | 
			
		||||
		      proc->pid, new_ref->debug_id, new_ref->desc,
 | 
			
		||||
		      proc->pid, new_ref->data.debug_id, new_ref->data.desc,
 | 
			
		||||
		      node->debug_id);
 | 
			
		||||
	return new_ref;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void binder_delete_ref(struct binder_ref *ref)
 | 
			
		||||
static void binder_cleanup_ref(struct binder_ref *ref)
 | 
			
		||||
{
 | 
			
		||||
	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 | 
			
		||||
		     "%d delete ref %d desc %d for node %d\n",
 | 
			
		||||
		      ref->proc->pid, ref->debug_id, ref->desc,
 | 
			
		||||
		      ref->proc->pid, ref->data.debug_id, ref->data.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)
 | 
			
		||||
 | 
			
		||||
	if (ref->data.strong)
 | 
			
		||||
		binder_dec_node(ref->node, 1, 1);
 | 
			
		||||
 | 
			
		||||
	hlist_del(&ref->node_entry);
 | 
			
		||||
	binder_dec_node(ref->node, 0, 1);
 | 
			
		||||
 | 
			
		||||
	if (ref->death) {
 | 
			
		||||
		binder_debug(BINDER_DEBUG_DEAD_BINDER,
 | 
			
		||||
			     "%d delete ref %d desc %d has death notification\n",
 | 
			
		||||
			      ref->proc->pid, ref->debug_id, ref->desc);
 | 
			
		||||
			      ref->proc->pid, ref->data.debug_id,
 | 
			
		||||
			      ref->data.desc);
 | 
			
		||||
		list_del(&ref->death->work.entry);
 | 
			
		||||
		kfree(ref->death);
 | 
			
		||||
		binder_stats_deleted(BINDER_STAT_DEATH);
 | 
			
		||||
	}
 | 
			
		||||
	kfree(ref);
 | 
			
		||||
	binder_stats_deleted(BINDER_STAT_REF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_inc_ref() - increment the ref for given handle
 | 
			
		||||
 * @ref:         ref to be incremented
 | 
			
		||||
 * @strong:      if true, strong increment, else weak
 | 
			
		||||
 * @target_list: list to queue node work on
 | 
			
		||||
 *
 | 
			
		||||
 * Increment the ref.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0, if successful, else errno
 | 
			
		||||
 */
 | 
			
		||||
static int binder_inc_ref(struct binder_ref *ref, int strong,
 | 
			
		||||
			  struct list_head *target_list)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (strong) {
 | 
			
		||||
		if (ref->strong == 0) {
 | 
			
		||||
		if (ref->data.strong == 0) {
 | 
			
		||||
			ret = binder_inc_node(ref->node, 1, 1, target_list);
 | 
			
		||||
			if (ret)
 | 
			
		||||
				return ret;
 | 
			
		||||
		}
 | 
			
		||||
		ref->strong++;
 | 
			
		||||
		ref->data.strong++;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (ref->weak == 0) {
 | 
			
		||||
		if (ref->data.weak == 0) {
 | 
			
		||||
			ret = binder_inc_node(ref->node, 0, 1, target_list);
 | 
			
		||||
			if (ret)
 | 
			
		||||
				return ret;
 | 
			
		||||
		}
 | 
			
		||||
		ref->weak++;
 | 
			
		||||
		ref->data.weak++;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int binder_dec_ref(struct binder_ref *ref, int strong)
 | 
			
		||||
/**
 | 
			
		||||
 * binder_dec_ref() - dec the ref for given handle
 | 
			
		||||
 * @ref:	ref to be decremented
 | 
			
		||||
 * @strong:	if true, strong decrement, else weak
 | 
			
		||||
 *
 | 
			
		||||
 * Decrement the ref.
 | 
			
		||||
 *
 | 
			
		||||
 * TODO: kfree is avoided here since an upcoming patch
 | 
			
		||||
 * will put this under a lock.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: true if ref is cleaned up and ready to be freed
 | 
			
		||||
 */
 | 
			
		||||
static bool binder_dec_ref(struct binder_ref *ref, int strong)
 | 
			
		||||
{
 | 
			
		||||
	if (strong) {
 | 
			
		||||
		if (ref->strong == 0) {
 | 
			
		||||
		if (ref->data.strong == 0) {
 | 
			
		||||
			binder_user_error("%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->proc->pid, ref->data.debug_id,
 | 
			
		||||
					  ref->data.desc, ref->data.strong,
 | 
			
		||||
					  ref->data.weak);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		ref->strong--;
 | 
			
		||||
		if (ref->strong == 0) {
 | 
			
		||||
		ref->data.strong--;
 | 
			
		||||
		if (ref->data.strong == 0) {
 | 
			
		||||
			int ret;
 | 
			
		||||
 | 
			
		||||
			ret = binder_dec_node(ref->node, strong, 1);
 | 
			
		||||
			if (ret)
 | 
			
		||||
				return ret;
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (ref->weak == 0) {
 | 
			
		||||
		if (ref->data.weak == 0) {
 | 
			
		||||
			binder_user_error("%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->proc->pid, ref->data.debug_id,
 | 
			
		||||
					  ref->data.desc, ref->data.strong,
 | 
			
		||||
					  ref->data.weak);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		ref->weak--;
 | 
			
		||||
		ref->data.weak--;
 | 
			
		||||
	}
 | 
			
		||||
	if (ref->strong == 0 && ref->weak == 0)
 | 
			
		||||
		binder_delete_ref(ref);
 | 
			
		||||
	return 0;
 | 
			
		||||
	if (ref->data.strong == 0 && ref->data.weak == 0) {
 | 
			
		||||
		binder_cleanup_ref(ref);
 | 
			
		||||
		/*
 | 
			
		||||
		 * TODO: we could kfree(ref) here, but an upcoming
 | 
			
		||||
		 * patch will call this with a lock held, so we
 | 
			
		||||
		 * return an indication that the ref should be
 | 
			
		||||
		 * freed.
 | 
			
		||||
		 */
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_get_node_from_ref() - get the node from the given proc/desc
 | 
			
		||||
 * @proc:	proc containing the ref
 | 
			
		||||
 * @desc:	the handle associated with the ref
 | 
			
		||||
 * @need_strong_ref: if true, only return node if ref is strong
 | 
			
		||||
 * @rdata:	the id/refcount data for the ref
 | 
			
		||||
 *
 | 
			
		||||
 * Given a proc and ref handle, return the associated binder_node
 | 
			
		||||
 *
 | 
			
		||||
 * Return: a binder_node or NULL if not found or not strong when strong required
 | 
			
		||||
 */
 | 
			
		||||
static struct binder_node *binder_get_node_from_ref(
 | 
			
		||||
		struct binder_proc *proc,
 | 
			
		||||
		u32 desc, bool need_strong_ref,
 | 
			
		||||
		struct binder_ref_data *rdata)
 | 
			
		||||
{
 | 
			
		||||
	struct binder_node *node;
 | 
			
		||||
	struct binder_ref *ref;
 | 
			
		||||
 | 
			
		||||
	ref = binder_get_ref(proc, desc, need_strong_ref);
 | 
			
		||||
	if (!ref)
 | 
			
		||||
		goto err_no_ref;
 | 
			
		||||
	node = ref->node;
 | 
			
		||||
	if (rdata)
 | 
			
		||||
		*rdata = ref->data;
 | 
			
		||||
 | 
			
		||||
	return node;
 | 
			
		||||
 | 
			
		||||
err_no_ref:
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_free_ref() - free the binder_ref
 | 
			
		||||
 * @ref:	ref to free
 | 
			
		||||
 *
 | 
			
		||||
 * Free the binder_ref and the binder_ref_death indicated by ref->death.
 | 
			
		||||
 */
 | 
			
		||||
static void binder_free_ref(struct binder_ref *ref)
 | 
			
		||||
{
 | 
			
		||||
	kfree(ref->death);
 | 
			
		||||
	kfree(ref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_update_ref_for_handle() - inc/dec the ref for given handle
 | 
			
		||||
 * @proc:	proc containing the ref
 | 
			
		||||
 * @desc:	the handle associated with the ref
 | 
			
		||||
 * @increment:	true=inc reference, false=dec reference
 | 
			
		||||
 * @strong:	true=strong reference, false=weak reference
 | 
			
		||||
 * @rdata:	the id/refcount data for the ref
 | 
			
		||||
 *
 | 
			
		||||
 * Given a proc and ref handle, increment or decrement the ref
 | 
			
		||||
 * according to "increment" arg.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 if successful, else errno
 | 
			
		||||
 */
 | 
			
		||||
static int binder_update_ref_for_handle(struct binder_proc *proc,
 | 
			
		||||
		uint32_t desc, bool increment, bool strong,
 | 
			
		||||
		struct binder_ref_data *rdata)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct binder_ref *ref;
 | 
			
		||||
	bool delete_ref = false;
 | 
			
		||||
 | 
			
		||||
	ref = binder_get_ref(proc, desc, strong);
 | 
			
		||||
	if (!ref) {
 | 
			
		||||
		ret = -EINVAL;
 | 
			
		||||
		goto err_no_ref;
 | 
			
		||||
	}
 | 
			
		||||
	if (increment)
 | 
			
		||||
		ret = binder_inc_ref(ref, strong, NULL);
 | 
			
		||||
	else
 | 
			
		||||
		delete_ref = binder_dec_ref(ref, strong);
 | 
			
		||||
 | 
			
		||||
	if (rdata)
 | 
			
		||||
		*rdata = ref->data;
 | 
			
		||||
 | 
			
		||||
	if (delete_ref)
 | 
			
		||||
		binder_free_ref(ref);
 | 
			
		||||
	return ret;
 | 
			
		||||
 | 
			
		||||
err_no_ref:
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_dec_ref_for_handle() - dec the ref for given handle
 | 
			
		||||
 * @proc:	proc containing the ref
 | 
			
		||||
 * @desc:	the handle associated with the ref
 | 
			
		||||
 * @strong:	true=strong reference, false=weak reference
 | 
			
		||||
 * @rdata:	the id/refcount data for the ref
 | 
			
		||||
 *
 | 
			
		||||
 * Just calls binder_update_ref_for_handle() to decrement the ref.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 if successful, else errno
 | 
			
		||||
 */
 | 
			
		||||
static int binder_dec_ref_for_handle(struct binder_proc *proc,
 | 
			
		||||
		uint32_t desc, bool strong, struct binder_ref_data *rdata)
 | 
			
		||||
{
 | 
			
		||||
	return binder_update_ref_for_handle(proc, desc, false, strong, rdata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * binder_inc_ref_for_node() - increment the ref for given proc/node
 | 
			
		||||
 * @proc:	 proc containing the ref
 | 
			
		||||
 * @node:	 target node
 | 
			
		||||
 * @strong:	 true=strong reference, false=weak reference
 | 
			
		||||
 * @target_list: worklist to use if node is incremented
 | 
			
		||||
 * @rdata:	 the id/refcount data for the ref
 | 
			
		||||
 *
 | 
			
		||||
 * Given a proc and node, increment the ref. Create the ref if it
 | 
			
		||||
 * doesn't already exist
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 if successful, else errno
 | 
			
		||||
 */
 | 
			
		||||
static int binder_inc_ref_for_node(struct binder_proc *proc,
 | 
			
		||||
			struct binder_node *node,
 | 
			
		||||
			bool strong,
 | 
			
		||||
			struct list_head *target_list,
 | 
			
		||||
			struct binder_ref_data *rdata)
 | 
			
		||||
{
 | 
			
		||||
	struct binder_ref *ref;
 | 
			
		||||
	struct binder_ref *new_ref = NULL;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	ref = binder_get_ref_for_node(proc, node, NULL);
 | 
			
		||||
	if (!ref) {
 | 
			
		||||
		new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
 | 
			
		||||
		if (!new_ref)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		ref = binder_get_ref_for_node(proc, node, new_ref);
 | 
			
		||||
	}
 | 
			
		||||
	ret = binder_inc_ref(ref, strong, target_list);
 | 
			
		||||
	*rdata = ref->data;
 | 
			
		||||
	if (new_ref && ref != new_ref)
 | 
			
		||||
		/*
 | 
			
		||||
		 * Another thread created the ref first so
 | 
			
		||||
		 * free the one we allocated
 | 
			
		||||
		 */
 | 
			
		||||
		kfree(new_ref);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void binder_pop_transaction(struct binder_thread *target_thread,
 | 
			
		||||
| 
						 | 
				
			
			@ -1124,20 +1352,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 | 
			
		|||
		case BINDER_TYPE_HANDLE:
 | 
			
		||||
		case BINDER_TYPE_WEAK_HANDLE: {
 | 
			
		||||
			struct flat_binder_object *fp;
 | 
			
		||||
			struct binder_ref *ref;
 | 
			
		||||
			struct binder_ref_data rdata;
 | 
			
		||||
			int ret;
 | 
			
		||||
 | 
			
		||||
			fp = to_flat_binder_object(hdr);
 | 
			
		||||
			ref = binder_get_ref(proc, fp->handle,
 | 
			
		||||
					     hdr->type == BINDER_TYPE_HANDLE);
 | 
			
		||||
			if (ref == NULL) {
 | 
			
		||||
				pr_err("transaction release %d bad handle %d\n",
 | 
			
		||||
				 debug_id, fp->handle);
 | 
			
		||||
			ret = binder_dec_ref_for_handle(proc, fp->handle,
 | 
			
		||||
				hdr->type == BINDER_TYPE_HANDLE, &rdata);
 | 
			
		||||
 | 
			
		||||
			if (ret) {
 | 
			
		||||
				pr_err("transaction release %d bad handle %d, ret = %d\n",
 | 
			
		||||
				 debug_id, fp->handle, ret);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			binder_debug(BINDER_DEBUG_TRANSACTION,
 | 
			
		||||
				     "        ref %d desc %d (node %d)\n",
 | 
			
		||||
				     ref->debug_id, ref->desc, ref->node->debug_id);
 | 
			
		||||
			binder_dec_ref(ref, hdr->type == BINDER_TYPE_HANDLE);
 | 
			
		||||
				     "        ref %d desc %d\n",
 | 
			
		||||
				     rdata.debug_id, rdata.desc);
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case BINDER_TYPE_FD: {
 | 
			
		||||
| 
						 | 
				
			
			@ -1209,9 +1438,10 @@ static int binder_translate_binder(struct flat_binder_object *fp,
 | 
			
		|||
				   struct binder_thread *thread)
 | 
			
		||||
{
 | 
			
		||||
	struct binder_node *node;
 | 
			
		||||
	struct binder_ref *ref;
 | 
			
		||||
	struct binder_proc *proc = thread->proc;
 | 
			
		||||
	struct binder_proc *target_proc = t->to_proc;
 | 
			
		||||
	struct binder_ref_data rdata;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	node = binder_get_node(proc, fp->binder);
 | 
			
		||||
	if (!node) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1232,25 +1462,25 @@ static int binder_translate_binder(struct flat_binder_object *fp,
 | 
			
		|||
	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
 | 
			
		||||
		return -EPERM;
 | 
			
		||||
 | 
			
		||||
	ref = binder_get_ref_for_node(target_proc, node);
 | 
			
		||||
	if (!ref)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	ret = binder_inc_ref_for_node(target_proc, node,
 | 
			
		||||
			fp->hdr.type == BINDER_TYPE_BINDER,
 | 
			
		||||
			&thread->todo, &rdata);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	if (fp->hdr.type == BINDER_TYPE_BINDER)
 | 
			
		||||
		fp->hdr.type = BINDER_TYPE_HANDLE;
 | 
			
		||||
	else
 | 
			
		||||
		fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
 | 
			
		||||
	fp->binder = 0;
 | 
			
		||||
	fp->handle = ref->desc;
 | 
			
		||||
	fp->handle = rdata.desc;
 | 
			
		||||
	fp->cookie = 0;
 | 
			
		||||
	binder_inc_ref(ref, fp->hdr.type == BINDER_TYPE_HANDLE, &thread->todo);
 | 
			
		||||
 | 
			
		||||
	trace_binder_transaction_node_to_ref(t, node, ref);
 | 
			
		||||
	trace_binder_transaction_node_to_ref(t, node, &rdata);
 | 
			
		||||
	binder_debug(BINDER_DEBUG_TRANSACTION,
 | 
			
		||||
		     "        node %d u%016llx -> ref %d desc %d\n",
 | 
			
		||||
		     node->debug_id, (u64)node->ptr,
 | 
			
		||||
		     ref->debug_id, ref->desc);
 | 
			
		||||
 | 
			
		||||
		     rdata.debug_id, rdata.desc);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1258,13 +1488,14 @@ static int binder_translate_handle(struct flat_binder_object *fp,
 | 
			
		|||
				   struct binder_transaction *t,
 | 
			
		||||
				   struct binder_thread *thread)
 | 
			
		||||
{
 | 
			
		||||
	struct binder_ref *ref;
 | 
			
		||||
	struct binder_proc *proc = thread->proc;
 | 
			
		||||
	struct binder_proc *target_proc = t->to_proc;
 | 
			
		||||
	struct binder_node *node;
 | 
			
		||||
	struct binder_ref_data src_rdata;
 | 
			
		||||
 | 
			
		||||
	ref = binder_get_ref(proc, fp->handle,
 | 
			
		||||
			     fp->hdr.type == BINDER_TYPE_HANDLE);
 | 
			
		||||
	if (!ref) {
 | 
			
		||||
	node = binder_get_node_from_ref(proc, fp->handle,
 | 
			
		||||
			fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata);
 | 
			
		||||
	if (!node) {
 | 
			
		||||
		binder_user_error("%d:%d got transaction with invalid handle, %d\n",
 | 
			
		||||
				  proc->pid, thread->pid, fp->handle);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1272,37 +1503,41 @@ static int binder_translate_handle(struct flat_binder_object *fp,
 | 
			
		|||
	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
 | 
			
		||||
		return -EPERM;
 | 
			
		||||
 | 
			
		||||
	if (ref->node->proc == target_proc) {
 | 
			
		||||
	if (node->proc == target_proc) {
 | 
			
		||||
		if (fp->hdr.type == BINDER_TYPE_HANDLE)
 | 
			
		||||
			fp->hdr.type = BINDER_TYPE_BINDER;
 | 
			
		||||
		else
 | 
			
		||||
			fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
 | 
			
		||||
		fp->binder = ref->node->ptr;
 | 
			
		||||
		fp->cookie = ref->node->cookie;
 | 
			
		||||
		binder_inc_node(ref->node, fp->hdr.type == BINDER_TYPE_BINDER,
 | 
			
		||||
		fp->binder = node->ptr;
 | 
			
		||||
		fp->cookie = node->cookie;
 | 
			
		||||
		binder_inc_node(node,
 | 
			
		||||
				fp->hdr.type == BINDER_TYPE_BINDER,
 | 
			
		||||
				0, NULL);
 | 
			
		||||
		trace_binder_transaction_ref_to_node(t, ref);
 | 
			
		||||
		trace_binder_transaction_ref_to_node(t, node, &src_rdata);
 | 
			
		||||
		binder_debug(BINDER_DEBUG_TRANSACTION,
 | 
			
		||||
			     "        ref %d desc %d -> node %d u%016llx\n",
 | 
			
		||||
			     ref->debug_id, ref->desc, ref->node->debug_id,
 | 
			
		||||
			     (u64)ref->node->ptr);
 | 
			
		||||
			     src_rdata.debug_id, src_rdata.desc, node->debug_id,
 | 
			
		||||
			     (u64)node->ptr);
 | 
			
		||||
	} else {
 | 
			
		||||
		struct binder_ref *new_ref;
 | 
			
		||||
		int ret;
 | 
			
		||||
		struct binder_ref_data dest_rdata;
 | 
			
		||||
 | 
			
		||||
		new_ref = binder_get_ref_for_node(target_proc, ref->node);
 | 
			
		||||
		if (!new_ref)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		ret = binder_inc_ref_for_node(target_proc, node,
 | 
			
		||||
				fp->hdr.type == BINDER_TYPE_HANDLE,
 | 
			
		||||
				NULL, &dest_rdata);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			return ret;
 | 
			
		||||
 | 
			
		||||
		fp->binder = 0;
 | 
			
		||||
		fp->handle = new_ref->desc;
 | 
			
		||||
		fp->handle = dest_rdata.desc;
 | 
			
		||||
		fp->cookie = 0;
 | 
			
		||||
		binder_inc_ref(new_ref, fp->hdr.type == BINDER_TYPE_HANDLE,
 | 
			
		||||
			       NULL);
 | 
			
		||||
		trace_binder_transaction_ref_to_ref(t, ref, new_ref);
 | 
			
		||||
		trace_binder_transaction_ref_to_ref(t, node, &src_rdata,
 | 
			
		||||
						    &dest_rdata);
 | 
			
		||||
		binder_debug(BINDER_DEBUG_TRANSACTION,
 | 
			
		||||
			     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
 | 
			
		||||
			     ref->debug_id, ref->desc, new_ref->debug_id,
 | 
			
		||||
			     new_ref->desc, ref->node->debug_id);
 | 
			
		||||
			     src_rdata.debug_id, src_rdata.desc,
 | 
			
		||||
			     dest_rdata.debug_id, dest_rdata.desc,
 | 
			
		||||
			     node->debug_id);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2043,6 +2278,8 @@ static int binder_thread_write(struct binder_proc *proc,
 | 
			
		|||
	void __user *end = buffer + size;
 | 
			
		||||
 | 
			
		||||
	while (ptr < end && thread->return_error.cmd == BR_OK) {
 | 
			
		||||
		int ret;
 | 
			
		||||
 | 
			
		||||
		if (get_user(cmd, (uint32_t __user *)ptr))
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
		ptr += sizeof(uint32_t);
 | 
			
		||||
| 
						 | 
				
			
			@ -2058,62 +2295,61 @@ static int binder_thread_write(struct binder_proc *proc,
 | 
			
		|||
		case BC_RELEASE:
 | 
			
		||||
		case BC_DECREFS: {
 | 
			
		||||
			uint32_t target;
 | 
			
		||||
			struct binder_ref *ref = NULL;
 | 
			
		||||
			const char *debug_string;
 | 
			
		||||
			bool strong = cmd == BC_ACQUIRE || cmd == BC_RELEASE;
 | 
			
		||||
			bool increment = cmd == BC_INCREFS || cmd == BC_ACQUIRE;
 | 
			
		||||
			struct binder_ref_data rdata;
 | 
			
		||||
 | 
			
		||||
			if (get_user(target, (uint32_t __user *)ptr))
 | 
			
		||||
				return -EFAULT;
 | 
			
		||||
 | 
			
		||||
			ptr += sizeof(uint32_t);
 | 
			
		||||
			if (target == 0 &&
 | 
			
		||||
			    (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
 | 
			
		||||
			ret = -1;
 | 
			
		||||
			if (increment && !target) {
 | 
			
		||||
				struct binder_node *ctx_mgr_node;
 | 
			
		||||
 | 
			
		||||
				mutex_lock(&context->context_mgr_node_lock);
 | 
			
		||||
				ctx_mgr_node = context->binder_context_mgr_node;
 | 
			
		||||
				if (ctx_mgr_node) {
 | 
			
		||||
					ref = binder_get_ref_for_node(proc,
 | 
			
		||||
							ctx_mgr_node);
 | 
			
		||||
					if (ref && ref->desc != target) {
 | 
			
		||||
						binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
 | 
			
		||||
							proc->pid, thread->pid,
 | 
			
		||||
							ref->desc);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if (ctx_mgr_node)
 | 
			
		||||
					ret = binder_inc_ref_for_node(
 | 
			
		||||
							proc, ctx_mgr_node,
 | 
			
		||||
							strong, NULL, &rdata);
 | 
			
		||||
				mutex_unlock(&context->context_mgr_node_lock);
 | 
			
		||||
			}
 | 
			
		||||
			if (ref == NULL)
 | 
			
		||||
				ref = binder_get_ref(proc, target,
 | 
			
		||||
						     cmd == BC_ACQUIRE ||
 | 
			
		||||
						     cmd == BC_RELEASE);
 | 
			
		||||
			if (ref == NULL) {
 | 
			
		||||
				binder_user_error("%d:%d refcount change on invalid ref %d\n",
 | 
			
		||||
					proc->pid, thread->pid, target);
 | 
			
		||||
				break;
 | 
			
		||||
			if (ret)
 | 
			
		||||
				ret = binder_update_ref_for_handle(
 | 
			
		||||
						proc, target, increment, strong,
 | 
			
		||||
						&rdata);
 | 
			
		||||
			if (!ret && rdata.desc != target) {
 | 
			
		||||
				binder_user_error("%d:%d tried to acquire reference to desc %d, got %d instead\n",
 | 
			
		||||
					proc->pid, thread->pid,
 | 
			
		||||
					target, rdata.desc);
 | 
			
		||||
			}
 | 
			
		||||
			switch (cmd) {
 | 
			
		||||
			case BC_INCREFS:
 | 
			
		||||
				debug_string = "IncRefs";
 | 
			
		||||
				binder_inc_ref(ref, 0, NULL);
 | 
			
		||||
				break;
 | 
			
		||||
			case BC_ACQUIRE:
 | 
			
		||||
				debug_string = "Acquire";
 | 
			
		||||
				binder_inc_ref(ref, 1, NULL);
 | 
			
		||||
				break;
 | 
			
		||||
			case BC_RELEASE:
 | 
			
		||||
				debug_string = "Release";
 | 
			
		||||
				binder_dec_ref(ref, 1);
 | 
			
		||||
				break;
 | 
			
		||||
			case BC_DECREFS:
 | 
			
		||||
			default:
 | 
			
		||||
				debug_string = "DecRefs";
 | 
			
		||||
				binder_dec_ref(ref, 0);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			if (ret) {
 | 
			
		||||
				binder_user_error("%d:%d %s %d refcount change on invalid ref %d ret %d\n",
 | 
			
		||||
					proc->pid, thread->pid, debug_string,
 | 
			
		||||
					strong, target, ret);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			binder_debug(BINDER_DEBUG_USER_REFS,
 | 
			
		||||
				     "%d:%d %s ref %d desc %d s %d w %d for node %d\n",
 | 
			
		||||
				     proc->pid, thread->pid, debug_string, ref->debug_id,
 | 
			
		||||
				     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
 | 
			
		||||
				     "%d:%d %s ref %d desc %d s %d w %d\n",
 | 
			
		||||
				     proc->pid, thread->pid, debug_string,
 | 
			
		||||
				     rdata.debug_id, rdata.desc, rdata.strong,
 | 
			
		||||
				     rdata.weak);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case BC_INCREFS_DONE:
 | 
			
		||||
| 
						 | 
				
			
			@ -2311,8 +2547,9 @@ static int binder_thread_write(struct binder_proc *proc,
 | 
			
		|||
				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
 | 
			
		||||
				     "BC_REQUEST_DEATH_NOTIFICATION" :
 | 
			
		||||
				     "BC_CLEAR_DEATH_NOTIFICATION",
 | 
			
		||||
				     (u64)cookie, ref->debug_id, ref->desc,
 | 
			
		||||
				     ref->strong, ref->weak, ref->node->debug_id);
 | 
			
		||||
				     (u64)cookie, ref->data.debug_id,
 | 
			
		||||
				     ref->data.desc, ref->data.strong,
 | 
			
		||||
				     ref->data.weak, ref->node->debug_id);
 | 
			
		||||
 | 
			
		||||
			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
 | 
			
		||||
				if (ref->death) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3473,7 +3710,8 @@ static void binder_deferred_release(struct binder_proc *proc)
 | 
			
		|||
 | 
			
		||||
		ref = rb_entry(n, struct binder_ref, rb_node_desc);
 | 
			
		||||
		outgoing_refs++;
 | 
			
		||||
		binder_delete_ref(ref);
 | 
			
		||||
		binder_cleanup_ref(ref);
 | 
			
		||||
		binder_free_ref(ref);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	binder_release_work(&proc->todo);
 | 
			
		||||
| 
						 | 
				
			
			@ -3675,9 +3913,11 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
 | 
			
		|||
 | 
			
		||||
static void print_binder_ref(struct seq_file *m, struct binder_ref *ref)
 | 
			
		||||
{
 | 
			
		||||
	seq_printf(m, "  ref %d: desc %d %snode %d s %d w %d d %p\n",
 | 
			
		||||
		   ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
 | 
			
		||||
		   ref->node->debug_id, ref->strong, ref->weak, ref->death);
 | 
			
		||||
	seq_printf(m, "  ref %d: desc %d %snode %d s %d w %d d %pK\n",
 | 
			
		||||
		   ref->data.debug_id, ref->data.desc,
 | 
			
		||||
		   ref->node->proc ? "" : "dead ",
 | 
			
		||||
		   ref->node->debug_id, ref->data.strong,
 | 
			
		||||
		   ref->data.weak, ref->death);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void print_binder_proc(struct seq_file *m,
 | 
			
		||||
| 
						 | 
				
			
			@ -3844,8 +4084,8 @@ static void print_binder_proc_stats(struct seq_file *m,
 | 
			
		|||
		struct binder_ref *ref = rb_entry(n, struct binder_ref,
 | 
			
		||||
						  rb_node_desc);
 | 
			
		||||
		count++;
 | 
			
		||||
		strong += ref->strong;
 | 
			
		||||
		weak += ref->weak;
 | 
			
		||||
		strong += ref->data.strong;
 | 
			
		||||
		weak += ref->data.weak;
 | 
			
		||||
	}
 | 
			
		||||
	seq_printf(m, "  refs: %d s %d w %d\n", count, strong, weak);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ struct binder_buffer;
 | 
			
		|||
struct binder_node;
 | 
			
		||||
struct binder_proc;
 | 
			
		||||
struct binder_alloc;
 | 
			
		||||
struct binder_ref;
 | 
			
		||||
struct binder_ref_data;
 | 
			
		||||
struct binder_thread;
 | 
			
		||||
struct binder_transaction;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -147,8 +147,8 @@ TRACE_EVENT(binder_transaction_received,
 | 
			
		|||
 | 
			
		||||
TRACE_EVENT(binder_transaction_node_to_ref,
 | 
			
		||||
	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
 | 
			
		||||
		 struct binder_ref *ref),
 | 
			
		||||
	TP_ARGS(t, node, ref),
 | 
			
		||||
		 struct binder_ref_data *rdata),
 | 
			
		||||
	TP_ARGS(t, node, rdata),
 | 
			
		||||
 | 
			
		||||
	TP_STRUCT__entry(
 | 
			
		||||
		__field(int, debug_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -161,8 +161,8 @@ TRACE_EVENT(binder_transaction_node_to_ref,
 | 
			
		|||
		__entry->debug_id = t->debug_id;
 | 
			
		||||
		__entry->node_debug_id = node->debug_id;
 | 
			
		||||
		__entry->node_ptr = node->ptr;
 | 
			
		||||
		__entry->ref_debug_id = ref->debug_id;
 | 
			
		||||
		__entry->ref_desc = ref->desc;
 | 
			
		||||
		__entry->ref_debug_id = rdata->debug_id;
 | 
			
		||||
		__entry->ref_desc = rdata->desc;
 | 
			
		||||
	),
 | 
			
		||||
	TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d",
 | 
			
		||||
		  __entry->debug_id, __entry->node_debug_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -171,8 +171,9 @@ TRACE_EVENT(binder_transaction_node_to_ref,
 | 
			
		|||
);
 | 
			
		||||
 | 
			
		||||
TRACE_EVENT(binder_transaction_ref_to_node,
 | 
			
		||||
	TP_PROTO(struct binder_transaction *t, struct binder_ref *ref),
 | 
			
		||||
	TP_ARGS(t, ref),
 | 
			
		||||
	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
 | 
			
		||||
		 struct binder_ref_data *rdata),
 | 
			
		||||
	TP_ARGS(t, node, rdata),
 | 
			
		||||
 | 
			
		||||
	TP_STRUCT__entry(
 | 
			
		||||
		__field(int, debug_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -183,10 +184,10 @@ TRACE_EVENT(binder_transaction_ref_to_node,
 | 
			
		|||
	),
 | 
			
		||||
	TP_fast_assign(
 | 
			
		||||
		__entry->debug_id = t->debug_id;
 | 
			
		||||
		__entry->ref_debug_id = ref->debug_id;
 | 
			
		||||
		__entry->ref_desc = ref->desc;
 | 
			
		||||
		__entry->node_debug_id = ref->node->debug_id;
 | 
			
		||||
		__entry->node_ptr = ref->node->ptr;
 | 
			
		||||
		__entry->ref_debug_id = rdata->debug_id;
 | 
			
		||||
		__entry->ref_desc = rdata->desc;
 | 
			
		||||
		__entry->node_debug_id = node->debug_id;
 | 
			
		||||
		__entry->node_ptr = node->ptr;
 | 
			
		||||
	),
 | 
			
		||||
	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx",
 | 
			
		||||
		  __entry->debug_id, __entry->node_debug_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -195,9 +196,10 @@ TRACE_EVENT(binder_transaction_ref_to_node,
 | 
			
		|||
);
 | 
			
		||||
 | 
			
		||||
TRACE_EVENT(binder_transaction_ref_to_ref,
 | 
			
		||||
	TP_PROTO(struct binder_transaction *t, struct binder_ref *src_ref,
 | 
			
		||||
		 struct binder_ref *dest_ref),
 | 
			
		||||
	TP_ARGS(t, src_ref, dest_ref),
 | 
			
		||||
	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
 | 
			
		||||
		 struct binder_ref_data *src_ref,
 | 
			
		||||
		 struct binder_ref_data *dest_ref),
 | 
			
		||||
	TP_ARGS(t, node, src_ref, dest_ref),
 | 
			
		||||
 | 
			
		||||
	TP_STRUCT__entry(
 | 
			
		||||
		__field(int, debug_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +211,7 @@ TRACE_EVENT(binder_transaction_ref_to_ref,
 | 
			
		|||
	),
 | 
			
		||||
	TP_fast_assign(
 | 
			
		||||
		__entry->debug_id = t->debug_id;
 | 
			
		||||
		__entry->node_debug_id = src_ref->node->debug_id;
 | 
			
		||||
		__entry->node_debug_id = node->debug_id;
 | 
			
		||||
		__entry->src_ref_debug_id = src_ref->debug_id;
 | 
			
		||||
		__entry->src_ref_desc = src_ref->desc;
 | 
			
		||||
		__entry->dest_ref_debug_id = dest_ref->debug_id;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue