diff options
Diffstat (limited to 'include/linux/trace_recursion.h')
| -rw-r--r-- | include/linux/trace_recursion.h | 49 | 
1 files changed, 9 insertions, 40 deletions
diff --git a/include/linux/trace_recursion.h b/include/linux/trace_recursion.h index a9f9c5714e65..fe95f0922526 100644 --- a/include/linux/trace_recursion.h +++ b/include/linux/trace_recursion.h @@ -16,23 +16,8 @@   *  When function tracing occurs, the following steps are made:   *   If arch does not support a ftrace feature:   *    call internal function (uses INTERNAL bits) which calls... - *   If callback is registered to the "global" list, the list - *    function is called and recursion checks the GLOBAL bits. - *    then this function calls...   *   The function callback, which can use the FTRACE bits to   *    check for recursion. - * - * Now if the arch does not support a feature, and it calls - * the global list function which calls the ftrace callback - * all three of these steps will do a recursion protection. - * There's no reason to do one if the previous caller already - * did. The recursion that we are protecting against will - * go through the same steps again. - * - * To prevent the multiple recursion checks, if a recursion - * bit is set that is higher than the MAX bit of the current - * check, then we know that the check was made by the previous - * caller, and we can skip the current check.   */  enum {  	/* Function recursion bits */ @@ -40,12 +25,14 @@ enum {  	TRACE_FTRACE_NMI_BIT,  	TRACE_FTRACE_IRQ_BIT,  	TRACE_FTRACE_SIRQ_BIT, +	TRACE_FTRACE_TRANSITION_BIT, -	/* INTERNAL_BITs must be greater than FTRACE_BITs */ +	/* Internal use recursion bits */  	TRACE_INTERNAL_BIT,  	TRACE_INTERNAL_NMI_BIT,  	TRACE_INTERNAL_IRQ_BIT,  	TRACE_INTERNAL_SIRQ_BIT, +	TRACE_INTERNAL_TRANSITION_BIT,  	TRACE_BRANCH_BIT,  /* @@ -86,12 +73,6 @@ enum {  	 */  	TRACE_GRAPH_NOTRACE_BIT, -	/* -	 * When transitioning between context, the preempt_count() may -	 * not be correct. Allow for a single recursion to cover this case. -	 */ -	TRACE_TRANSITION_BIT, -  	/* Used to prevent recursion recording from recursing. */  	TRACE_RECORD_RECURSION_BIT,  }; @@ -113,12 +94,10 @@ enum {  #define TRACE_CONTEXT_BITS	4  #define TRACE_FTRACE_START	TRACE_FTRACE_BIT -#define TRACE_FTRACE_MAX	((1 << (TRACE_FTRACE_START + TRACE_CONTEXT_BITS)) - 1)  #define TRACE_LIST_START	TRACE_INTERNAL_BIT -#define TRACE_LIST_MAX		((1 << (TRACE_LIST_START + TRACE_CONTEXT_BITS)) - 1) -#define TRACE_CONTEXT_MASK	TRACE_LIST_MAX +#define TRACE_CONTEXT_MASK	((1 << (TRACE_LIST_START + TRACE_CONTEXT_BITS)) - 1)  /*   * Used for setting context @@ -132,6 +111,7 @@ enum {  	TRACE_CTX_IRQ,  	TRACE_CTX_SOFTIRQ,  	TRACE_CTX_NORMAL, +	TRACE_CTX_TRANSITION,  };  static __always_inline int trace_get_context_bit(void) @@ -160,45 +140,34 @@ extern void ftrace_record_recursion(unsigned long ip, unsigned long parent_ip);  #endif  static __always_inline int trace_test_and_set_recursion(unsigned long ip, unsigned long pip, -							int start, int max) +							int start)  {  	unsigned int val = READ_ONCE(current->trace_recursion);  	int bit; -	/* A previous recursion check was made */ -	if ((val & TRACE_CONTEXT_MASK) > max) -		return 0; -  	bit = trace_get_context_bit() + start;  	if (unlikely(val & (1 << bit))) {  		/*  		 * It could be that preempt_count has not been updated during  		 * a switch between contexts. Allow for a single recursion.  		 */ -		bit = TRACE_TRANSITION_BIT; +		bit = TRACE_CTX_TRANSITION + start;  		if (val & (1 << bit)) {  			do_ftrace_record_recursion(ip, pip);  			return -1;  		} -	} else { -		/* Normal check passed, clear the transition to allow it again */ -		val &= ~(1 << TRACE_TRANSITION_BIT);  	}  	val |= 1 << bit;  	current->trace_recursion = val;  	barrier(); -	return bit + 1; +	return bit;  }  static __always_inline void trace_clear_recursion(int bit)  { -	if (!bit) -		return; -  	barrier(); -	bit--;  	trace_recursion_clear(bit);  } @@ -214,7 +183,7 @@ static __always_inline void trace_clear_recursion(int bit)  static __always_inline int ftrace_test_recursion_trylock(unsigned long ip,  							 unsigned long parent_ip)  { -	return trace_test_and_set_recursion(ip, parent_ip, TRACE_FTRACE_START, TRACE_FTRACE_MAX); +	return trace_test_and_set_recursion(ip, parent_ip, TRACE_FTRACE_START);  }  /**  | 
