diff options
| author | Ingo Molnar <mingo@elte.hu> | 2012-01-26 14:09:19 +0400 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2012-01-26 14:09:19 +0400 | 
| commit | 96070c83b295b31912ad92d3ffb66baec2b86d50 (patch) | |
| tree | 9ee346398552b40df1a7c7a80cb366bfd6a07181 | |
| parent | 87f71ae2dd7471c1b4c94100be1f218e91dc64c3 (diff) | |
| parent | 163566f60bfe6a8176650155e2d98649b0dfabf8 (diff) | |
| download | linux-96070c83b295b31912ad92d3ffb66baec2b86d50.tar.xz | |
Merge branch 'sigtrace' of git://github.com/utrace/linux into perf/core
| -rw-r--r-- | include/trace/events/signal.h | 85 | ||||
| -rw-r--r-- | kernel/signal.c | 28 | 
2 files changed, 41 insertions, 72 deletions
diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h index 17df43464df0..39a8a430d90f 100644 --- a/include/trace/events/signal.h +++ b/include/trace/events/signal.h @@ -23,11 +23,23 @@  		}						\  	} while (0) +#ifndef TRACE_HEADER_MULTI_READ +enum { +	TRACE_SIGNAL_DELIVERED, +	TRACE_SIGNAL_IGNORED, +	TRACE_SIGNAL_ALREADY_PENDING, +	TRACE_SIGNAL_OVERFLOW_FAIL, +	TRACE_SIGNAL_LOSE_INFO, +}; +#endif +  /**   * signal_generate - called when a signal is generated   * @sig: signal number   * @info: pointer to struct siginfo   * @task: pointer to struct task_struct + * @group: shared or private + * @result: TRACE_SIGNAL_*   *   * Current process sends a 'sig' signal to 'task' process with   * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV, @@ -37,9 +49,10 @@   */  TRACE_EVENT(signal_generate, -	TP_PROTO(int sig, struct siginfo *info, struct task_struct *task), +	TP_PROTO(int sig, struct siginfo *info, struct task_struct *task, +			int group, int result), -	TP_ARGS(sig, info, task), +	TP_ARGS(sig, info, task, group, result),  	TP_STRUCT__entry(  		__field(	int,	sig			) @@ -47,6 +60,8 @@ TRACE_EVENT(signal_generate,  		__field(	int,	code			)  		__array(	char,	comm,	TASK_COMM_LEN	)  		__field(	pid_t,	pid			) +		__field(	int,	group			) +		__field(	int,	result			)  	),  	TP_fast_assign( @@ -54,11 +69,14 @@ TRACE_EVENT(signal_generate,  		TP_STORE_SIGINFO(__entry, info);  		memcpy(__entry->comm, task->comm, TASK_COMM_LEN);  		__entry->pid	= task->pid; +		__entry->group	= group; +		__entry->result	= result;  	), -	TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d", +	TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d grp=%d res=%d",  		  __entry->sig, __entry->errno, __entry->code, -		  __entry->comm, __entry->pid) +		  __entry->comm, __entry->pid, __entry->group, +		  __entry->result)  );  /** @@ -101,65 +119,6 @@ TRACE_EVENT(signal_deliver,  		  __entry->sa_handler, __entry->sa_flags)  ); -DECLARE_EVENT_CLASS(signal_queue_overflow, - -	TP_PROTO(int sig, int group, struct siginfo *info), - -	TP_ARGS(sig, group, info), - -	TP_STRUCT__entry( -		__field(	int,	sig	) -		__field(	int,	group	) -		__field(	int,	errno	) -		__field(	int,	code	) -	), - -	TP_fast_assign( -		__entry->sig	= sig; -		__entry->group	= group; -		TP_STORE_SIGINFO(__entry, info); -	), - -	TP_printk("sig=%d group=%d errno=%d code=%d", -		  __entry->sig, __entry->group, __entry->errno, __entry->code) -); - -/** - * signal_overflow_fail - called when signal queue is overflow - * @sig: signal number - * @group: signal to process group or not (bool) - * @info: pointer to struct siginfo - * - * Kernel fails to generate 'sig' signal with 'info' siginfo, because - * siginfo queue is overflow, and the signal is dropped. - * 'group' is not 0 if the signal will be sent to a process group. - * 'sig' is always one of RT signals. - */ -DEFINE_EVENT(signal_queue_overflow, signal_overflow_fail, - -	TP_PROTO(int sig, int group, struct siginfo *info), - -	TP_ARGS(sig, group, info) -); - -/** - * signal_lose_info - called when siginfo is lost - * @sig: signal number - * @group: signal to process group or not (bool) - * @info: pointer to struct siginfo - * - * Kernel generates 'sig' signal but loses 'info' siginfo, because siginfo - * queue is overflow. - * 'group' is not 0 if the signal will be sent to a process group. - * 'sig' is always one of non-RT signals. - */ -DEFINE_EVENT(signal_queue_overflow, signal_lose_info, - -	TP_PROTO(int sig, int group, struct siginfo *info), - -	TP_ARGS(sig, group, info) -); -  #endif /* _TRACE_SIGNAL_H */  /* This part must be outside protection */ diff --git a/kernel/signal.c b/kernel/signal.c index c73c4284160e..8511e39813c7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1054,13 +1054,13 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  	struct sigpending *pending;  	struct sigqueue *q;  	int override_rlimit; - -	trace_signal_generate(sig, info, t); +	int ret = 0, result;  	assert_spin_locked(&t->sighand->siglock); +	result = TRACE_SIGNAL_IGNORED;  	if (!prepare_signal(sig, t, from_ancestor_ns)) -		return 0; +		goto ret;  	pending = group ? &t->signal->shared_pending : &t->pending;  	/* @@ -1068,8 +1068,11 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  	 * exactly one non-rt signal, so that we can get more  	 * detailed information about the cause of the signal.  	 */ +	result = TRACE_SIGNAL_ALREADY_PENDING;  	if (legacy_queue(pending, sig)) -		return 0; +		goto ret; + +	result = TRACE_SIGNAL_DELIVERED;  	/*  	 * fast-pathed signals for kernel-internal things like SIGSTOP  	 * or SIGKILL. @@ -1127,14 +1130,15 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  			 * signal was rt and sent by user using something  			 * other than kill().  			 */ -			trace_signal_overflow_fail(sig, group, info); -			return -EAGAIN; +			result = TRACE_SIGNAL_OVERFLOW_FAIL; +			ret = -EAGAIN; +			goto ret;  		} else {  			/*  			 * This is a silent loss of information.  We still  			 * send the signal, but the *info bits are lost.  			 */ -			trace_signal_lose_info(sig, group, info); +			result = TRACE_SIGNAL_LOSE_INFO;  		}  	} @@ -1142,7 +1146,9 @@ out_set:  	signalfd_notify(t, sig);  	sigaddset(&pending->signal, sig);  	complete_signal(sig, t, group); -	return 0; +ret: +	trace_signal_generate(sig, info, t, group, result); +	return ret;  }  static int send_signal(int sig, struct siginfo *info, struct task_struct *t, @@ -1585,7 +1591,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  	int sig = q->info.si_signo;  	struct sigpending *pending;  	unsigned long flags; -	int ret; +	int ret, result;  	BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); @@ -1594,6 +1600,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  		goto ret;  	ret = 1; /* the signal is ignored */ +	result = TRACE_SIGNAL_IGNORED;  	if (!prepare_signal(sig, t, 0))  		goto out; @@ -1605,6 +1612,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  		 */  		BUG_ON(q->info.si_code != SI_TIMER);  		q->info.si_overrun++; +		result = TRACE_SIGNAL_ALREADY_PENDING;  		goto out;  	}  	q->info.si_overrun = 0; @@ -1614,7 +1622,9 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  	list_add_tail(&q->list, &pending->list);  	sigaddset(&pending->signal, sig);  	complete_signal(sig, t, group); +	result = TRACE_SIGNAL_DELIVERED;  out: +	trace_signal_generate(sig, &q->info, t, group, result);  	unlock_task_sighand(t, &flags);  ret:  	return ret;  | 
