Skip to contentSkip to conversation

netdev: show a process of packets

PATCH In review Koki Sanagi 15 participants 93 messages Aug 23, 2010 – Oct 26, 2010

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

v4 cover netdev: show a process of packets

Rebase to the latest net-next.

CHANGE-LOG since v3:
1) change arguments of softirq tracepoint into original one.
2) remove tracepoint of dev_kfree_skb_irq and skb_free_datagram_locked and add trace_kfree_skb before __kfree_skb instead of them.
3) add tracepoint to netif_rx and display it by netdev-times script.

These patch-set adds tracepoints to show us a process of packets. Using these tracepoints and existing points, we can get the time when packet passes through some points in transmit or receive sequence. For example, this is an output of perf script which is attached by patch 5/5.

106133.171439sec cpu=0
irq_entry(+0.000msec irq=24:eth4)

         |
  softirq_entry(+0.006msec)
         |
         |---netif_receive_skb(+0.010msec skb=f2d15900 len=100)
         |            |
         |      skb_copy_datagram_iovec(+0.039msec 10291::10291)
         |

napi_poll_exit(+0.022msec eth4)

106134.175634sec cpu=1
irq_entry(+0.000msec irq=28:eth1)

         |
         |---netif_rx(+0.009msec skb=f3ef0a00)
         |
  softirq_entry(+0.018msec)
         |
         |---netif_receive_skb(+0.021msec skb=f3ef0a00 len=84)
         |            |
         |      skb_copy_datagram_iovec(+0.033msec 0:swapper)
         |

napi_poll_exit(+0.035msec (no_device))

The above is a receive side(eth4 is NAPI. eth1 is non-NAPI). Like this, it can show receive sequence frominterrupt(irq_entry) to application (skb_copy_datagram_iovec).
This script shows one NET_RX softirq and events related to it. All relative time bases on first irq_entry which raise NET_RX softirq.

dev len Qdisc netdevice free

   eth4    74 106125.030004sec        0.006msec             0.009msec
   eth4    87 106125.041020sec        0.007msec             0.023msec
   eth4    66 106125.042291sec        0.003msec             0.012msec
   eth4    66 106125.043274sec        0.006msec             0.004msec
   eth4   850 106125.044283sec        0.007msec             0.018msec

The above is a transmit side. There are three check-time-points. Point1 is before putting a packet to Qdisc. point2 is after ndo_start_xmit in dev_hard_start_xmit. It indicates finishing putting a packet to driver. point3 is in consume_skb and kfree_skb. It indicates freeing a transmitted packet. Values of this script are, from left, device name, length of a packet, a time of point1, an interval time between point1 and point2 and an interval time between point2 and point3.

These times are useful to analyze a performance or to detect a point where packet delays. For example,
- NET_RX softirq calling is late.
- Application is late to take a packet.
- It takes much time to put a transmitting packet to driver (It may be caused by packed queue)

And also, these tracepoint help us to investigate a network driver's trouble from memory dump because ftrace records it to memory. And ftrace is so light even if always trace on. So, in a case investigating a problem which doesn't reproduce, it is useful.

Thanks,
Koki Sanagi.

#1 lore raw

PATCH v4 1/5 irq: add tracepoint to softirq_raise

From: Lai Jiangshan <[email protected]>

Add a tracepoint for tracing when softirq action is raised.

It and the existed tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)
include/linux/interrupt.h +7 -1
index a0384a4..d3e8e90 100644
@@ -18,6 +18,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <trace/events/irq.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)&nr, NULL);
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
include/trace/events/irq.h +24 -2
index 0e4cfb6..3ddda02 100644
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
 	),
 
 	TP_printk("vec=%d [action=%s]", __entry->vec,
@@ -136,6 +141,23 @@ DEFINE_EVENT(softirq, softirq_exit,
 	TP_ARGS(h, vec)
 );
 
+/**
+ * softirq_raise - called immediately when a softirq is raised
+ * @h: pointer to struct softirq_action
+ * @vec: pointer to first struct softirq_action in softirq_vec array
+ *
+ * The @h parameter contains a pointer to the softirq vector number which is
+ * raised. @vec is NULL and it means @h includes vector number not
+ * softirq_action. When used in combination with the softirq_entry tracepoint
+ * we can determine the softirq raise latency.
+ */
+DEFINE_EVENT(softirq, softirq_raise,
+
+	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+
+	TP_ARGS(h, vec)
+);
+
 #endif /*  _TRACE_IRQ_H */
 
 /* This part must be outside protection */
#74 lore raw

PATCH v4 2/5 napi: convert trace_napi_poll to TRACE_EVENT

In reply to Koki Sanagi

From: Neil Horman <[email protected]>

This patch converts trace_napi_poll from DECLARE_EVENT to TRACE_EVENT to improve the usability of napi_poll tracepoint.

          <idle>-0     [001] 241302.750777: napi_poll: napi poll on napi struct f6acc480 for device eth3
          <idle>-0     [000] 241302.852389: napi_poll: napi poll on napi struct f5d0d70c for device eth1

An original patch is below.
http://marc.info/?l=linux-kernel&m=126021713809450&w=2

And add a fix by Steven Rostedt.
http://marc.info/?l=linux-kernel&m=126150506519173&w=2

---
 include/trace/events/napi.h |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)
include/trace/events/napi.h +23 -2
index 188deca..8fe1e93 100644
@@ -6,10 +6,31 @@
 
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
+#include <linux/ftrace.h>
+
+#define NO_DEV "(no_device)"
+
+TRACE_EVENT(napi_poll,
 
-DECLARE_TRACE(napi_poll,
 	TP_PROTO(struct napi_struct *napi),
-	TP_ARGS(napi));
+
+	TP_ARGS(napi),
+
+	TP_STRUCT__entry(
+		__field(	struct napi_struct *,	napi)
+		__string(	dev_name, napi->dev ? napi->dev->name : NO_DEV)
+	),
+
+	TP_fast_assign(
+		__entry->napi = napi;
+		__assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV);
+	),
+
+	TP_printk("napi poll on napi struct %p for device %s",
+		__entry->napi, __get_str(dev_name))
+);
+
+#undef NO_DEV
 
 #endif /* _TRACE_NAPI_H_ */
 
#77 lore raw

PATCH v4 3/5 netdev: add tracepoints to netdev layer

In reply to Koki Sanagi

This patch adds tracepoint to dev_queue_xmit, dev_hard_start_xmit, netif_rx and netif_receive_skb. These tracepoints help you to monitor network driver's input/output.

          <idle>-0     [001] 112447.902030: netif_rx: dev=eth1 skbaddr=f3ef0900 len=84
          <idle>-0     [001] 112447.902039: netif_receive_skb: dev=eth1 skbaddr=f3ef0900 len=84
            sshd-6828  [000] 112447.903257: net_dev_queue: dev=eth4 skbaddr=f3fca538 len=226
            sshd-6828  [000] 112447.903260: net_dev_xmit: dev=eth4 skbaddr=f3fca538 len=226 rc=0
---
 include/trace/events/net.h |   82 ++++++++++++++++++++++++++++++++++++++++++++
 net/core/dev.c             |    6 +++
 net/core/net-traces.c      |    1 +
 3 files changed, 89 insertions(+), 0 deletions(-)
include/trace/events/net.h new file +82 -0
new file mode 100644
index 0000000..5f247f5
@@ -0,0 +1,82 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM net
+
+#if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_NET_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(net_dev_xmit,
+
+	TP_PROTO(struct sk_buff *skb,
+		 int rc),
+
+	TP_ARGS(skb, rc),
+
+	TP_STRUCT__entry(
+		__field(	void *,		skbaddr		)
+		__field(	unsigned int,	len		)
+		__field(	int,		rc		)
+		__string(	name,		skb->dev->name	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+		__entry->len = skb->len;
+		__entry->rc = rc;
+		__assign_str(name, skb->dev->name);
+	),
+
+	TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+		__get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
+);
+
+DECLARE_EVENT_CLASS(net_dev_template,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(	void *,		skbaddr		)
+		__field(	unsigned int,	len		)
+		__string(	name,		skb->dev->name	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+		__entry->len = skb->len;
+		__assign_str(name, skb->dev->name);
+	),
+
+	TP_printk("dev=%s skbaddr=%p len=%u",
+		__get_str(name), __entry->skbaddr, __entry->len)
+)
+
+DEFINE_EVENT(net_dev_template, net_dev_queue,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_receive_skb,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_rx,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+#endif /* _TRACE_NET_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
net/core/dev.c +6 -0
index 7cd5237..c9b026a 100644
@@ -128,6 +128,7 @@
 #include <linux/jhash.h>
 #include <linux/random.h>
 #include <trace/events/napi.h>
+#include <trace/events/net.h>
 #include <linux/pci.h>
 
 #include "net-sysfs.h"
@@ -1978,6 +1979,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 		}
 
 		rc = ops->ndo_start_xmit(skb, dev);
+		trace_net_dev_xmit(skb, rc);
 		if (rc == NETDEV_TX_OK)
 			txq_trans_update(txq);
 		return rc;
@@ -1998,6 +2000,7 @@ gso:
 			skb_dst_drop(nskb);
 
 		rc = ops->ndo_start_xmit(nskb, dev);
+		trace_net_dev_xmit(nskb, rc);
 		if (unlikely(rc != NETDEV_TX_OK)) {
 			if (rc & ~NETDEV_TX_MASK)
 				goto out_kfree_gso_skb;
@@ -2186,6 +2189,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 #ifdef CONFIG_NET_CLS_ACT
 	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
 #endif
+	trace_net_dev_queue(skb);
 	if (q->enqueue) {
 		rc = __dev_xmit_skb(skb, q, dev, txq);
 		goto out;
@@ -2525,6 +2529,7 @@ int netif_rx(struct sk_buff *skb)
 	if (netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
+	trace_netif_rx(skb);
 #ifdef CONFIG_RPS
 	{
 		struct rps_dev_flow voidflow, *rflow = &voidflow;
@@ -2841,6 +2846,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
 	if (!netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
+	trace_netif_receive_skb(skb);
 	if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
 		return NET_RX_SUCCESS;
 
net/core/net-traces.c +1 -0
index afa6380..7f1bb2a 100644
@@ -26,6 +26,7 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/skb.h>
+#include <trace/events/net.h>
 #include <trace/events/napi.h>
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
#80 lore raw

PATCH v4 4/5 skb: add tracepoints to freeing skb

In reply to Koki Sanagi

This patch adds tracepoint to consume_skb and add trace_kfree_skb before __kfree_skb in skb_free_datagram_locked and net_tx_action. Combinating with tracepoint on dev_hard_start_xmit, we can check how long it takes to free transmited packets. And using it, we can calculate how many packets driver had at that time. It is useful when a drop of transmited packet is a problem.

            sshd-6828  [000] 112689.258154: consume_skb: skbaddr=f2d99bb8
---
 include/trace/events/skb.h |   17 +++++++++++++++++
 net/core/datagram.c        |    1 +
 net/core/dev.c             |    2 ++
 net/core/skbuff.c          |    1 +
 4 files changed, 21 insertions(+), 0 deletions(-)
include/trace/events/skb.h +17 -0
index 4b2be6d..75ce9d5 100644
@@ -35,6 +35,23 @@ TRACE_EVENT(kfree_skb,
 		__entry->skbaddr, __entry->protocol, __entry->location)
 );
 
+TRACE_EVENT(consume_skb,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(	void *,	skbaddr	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+	),
+
+	TP_printk("skbaddr=%p", __entry->skbaddr)
+);
+
 TRACE_EVENT(skb_copy_datagram_iovec,
 
 	TP_PROTO(const struct sk_buff *skb, int len),
net/core/datagram.c +1 -0
index 251997a..282806b 100644
@@ -243,6 +243,7 @@ void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
 	unlock_sock_fast(sk, slow);
 
 	/* skb is now orphaned, can be freed outside of locked section */
+	trace_kfree_skb(skb, skb_free_datagram_locked);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(skb_free_datagram_locked);
net/core/dev.c +2 -0
index c9b026a..48f7977 100644
@@ -129,6 +129,7 @@
 #include <linux/random.h>
 #include <trace/events/napi.h>
 #include <trace/events/net.h>
+#include <trace/events/skb.h>
 #include <linux/pci.h>
 
 #include "net-sysfs.h"
@@ -2589,6 +2590,7 @@ static void net_tx_action(struct softirq_action *h)
 			clist = clist->next;
 
 			WARN_ON(atomic_read(&skb->users));
+			trace_kfree_skb(skb, net_tx_action);
 			__kfree_skb(skb);
 		}
 	}
net/core/skbuff.c +1 -0
index 99ef721..ef4ffa8 100644
@@ -466,6 +466,7 @@ void consume_skb(struct sk_buff *skb)
 		smp_rmb();
 	else if (likely(!atomic_dec_and_test(&skb->users)))
 		return;
+	trace_consume_skb(skb);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(consume_skb);
#83 lore raw

PATCH v4 5/5 perf:add a script shows a process of packet

In reply to Koki Sanagi

Add a perf script which shows a process of packets and processed time. It helps us to investigate networking or network device.

If you want to use it, install perf and record perf.data like following.

#perf trace record netdev-times [script]

If you set script, perf gathers records until it ends. If not, you must Ctrl-C to stop recording.

And if you want a report from record,

#perf trace report netdev-times [options]

If you use some options, you can limit an output.
Option is below.

tx: show only process of tx packets
rx: show only process of rx packets
dev=: show a process specified with this option
debug: work with debug mode. It shows buffer status.

For example, if you want to show a process of received packets associated with eth4,

#perf trace report netdev-times rx dev=eth4
106133.171439sec cpu=0
irq_entry(+0.000msec irq=24:eth4)

         |
  softirq_entry(+0.006msec)
         |
         |---netif_receive_skb(+0.010msec skb=f2d15900 len=100)
         |            |
         |      skb_copy_datagram_iovec(+0.039msec 10291::10291)
         |

napi_poll_exit(+0.022msec eth4)

This perf script helps us to analyze a process time of transmit/receive sequence.

---
 tools/perf/scripts/python/bin/netdev-times-record |    8 +
 tools/perf/scripts/python/bin/netdev-times-report |    5 +
 tools/perf/scripts/python/netdev-times.py         |  464 +++++++++++++++++++++
 3 files changed, 477 insertions(+), 0 deletions(-)
tools/perf/scripts/python/bin/netdev-times-record new file +8 -0
new file mode 100644
index 0000000..2b59511
@@ -0,0 +1,8 @@
+#!/bin/bash
+perf record -c 1 -f -R -a -e net:net_dev_xmit -e net:net_dev_queue	\
+		-e net:netif_receive_skb -e net:netif_rx		\
+		-e skb:consume_skb -e skb:kfree_skb			\
+		-e skb:skb_copy_datagram_iovec -e napi:napi_poll	\
+		-e irq:irq_handler_entry -e irq:irq_handler_exit	\
+		-e irq:softirq_entry -e irq:softirq_exit		\
+		-e irq:softirq_raise $@
tools/perf/scripts/python/bin/netdev-times-report new file +5 -0
new file mode 100644
index 0000000..c3d0a63
@@ -0,0 +1,5 @@
+#!/bin/bash
+# description: display a process of packet and processing time
+# args: [tx] [rx] [dev=] [debug]
+
+perf trace -s ~/libexec/perf-core/scripts/python/netdev-times.py $@
tools/perf/scripts/python/netdev-times.py new file +464 -0

464 lines not on this page · raw message

maintainer Acked-by on v4 2/5
#75 lore raw

Re: [PATCH v4 2/5] napi: convert trace_napi_poll to TRACE_EVENT

In reply to Koki Sanagi

From: Koki Sanagi <[email protected]>
Date: Mon, 23 Aug 2010 18:43:51 +0900

Quoted 8 lines

From: Neil Horman <[email protected]>

This patch converts trace_napi_poll from DECLARE_EVENT to TRACE_EVENT to improve the usability of napi_poll tracepoint.

          <idle>-0     [001] 241302.750777: napi_poll: napi poll on napi struct f6acc480 for device eth3
          <idle>-0     [000] 241302.852389: napi_poll: napi poll on napi struct f5d0d70c for device eth1
Quoted 8 lines

An original patch is below.
http://marc.info/?l=linux-kernel&m=126021713809450&w=2

And add a fix by Steven Rostedt.
http://marc.info/?l=linux-kernel&m=126150506519173&w=2

maintainer Acked-by on v4 3/5
#78 lore raw

Re: [PATCH v4 3/5] netdev: add tracepoints to netdev layer

In reply to Koki Sanagi

From: Koki Sanagi <[email protected]>
Date: Mon, 23 Aug 2010 18:45:02 +0900

Quoted 10 lines

This patch adds tracepoint to dev_queue_xmit, dev_hard_start_xmit, netif_rx and netif_receive_skb. These tracepoints help you to monitor network driver's input/output.

          <idle>-0     [001] 112447.902030: netif_rx: dev=eth1 skbaddr=f3ef0900 len=84
          <idle>-0     [001] 112447.902039: netif_receive_skb: dev=eth1 skbaddr=f3ef0900 len=84
            sshd-6828  [000] 112447.903257: net_dev_queue: dev=eth4 skbaddr=f3fca538 len=226
            sshd-6828  [000] 112447.903260: net_dev_xmit: dev=eth4 skbaddr=f3fca538 len=226 rc=0
maintainer Acked-by on v4 4/5
#81 lore raw

Re: [PATCH v4 4/5] skb: add tracepoints to freeing skb

In reply to Koki Sanagi

From: Koki Sanagi <[email protected]>
Date: Mon, 23 Aug 2010 18:46:12 +0900

Quoted 10 lines

This patch adds tracepoint to consume_skb and add trace_kfree_skb before __kfree_skb in skb_free_datagram_locked and net_tx_action. Combinating with tracepoint on dev_hard_start_xmit, we can check how long it takes to free transmited packets. And using it, we can calculate how many packets driver had at that time. It is useful when a drop of transmited packet is a problem.

            sshd-6828  [000] 112689.258154: consume_skb: skbaddr=f2d99bb8
maintainer Acked-by on the v4 series
#87 lore raw
In reply to Koki Sanagi
Quoted 65 lines · Koki Sanagi

Rebase to the latest net-next.

CHANGE-LOG since v3:
1) change arguments of softirq tracepoint into original one.
2) remove tracepoint of dev_kfree_skb_irq and skb_free_datagram_locked and add trace_kfree_skb before __kfree_skb instead of them.
3) add tracepoint to netif_rx and display it by netdev-times script.

These patch-set adds tracepoints to show us a process of packets. Using these tracepoints and existing points, we can get the time when packet passes through some points in transmit or receive sequence. For example, this is an output of perf script which is attached by patch 5/5.

106133.171439sec cpu=0
irq_entry(+0.000msec irq=24:eth4)

         |
  softirq_entry(+0.006msec)
         |
         |---netif_receive_skb(+0.010msec skb=f2d15900 len=100)
         |            |
         |      skb_copy_datagram_iovec(+0.039msec 10291::10291)
         |

napi_poll_exit(+0.022msec eth4)

106134.175634sec cpu=1
irq_entry(+0.000msec irq=28:eth1)

         |
         |---netif_rx(+0.009msec skb=f3ef0a00)
         |
  softirq_entry(+0.018msec)
         |
         |---netif_receive_skb(+0.021msec skb=f3ef0a00 len=84)
         |            |
         |      skb_copy_datagram_iovec(+0.033msec 0:swapper)
         |

napi_poll_exit(+0.035msec (no_device))

The above is a receive side(eth4 is NAPI. eth1 is non-NAPI). Like this, it can show receive sequence frominterrupt(irq_entry) to application (skb_copy_datagram_iovec).
This script shows one NET_RX softirq and events related to it. All relative time bases on first irq_entry which raise NET_RX softirq.

   dev    len      Qdisc               netdevice             free
   eth4    74 106125.030004sec        0.006msec             0.009msec
   eth4    87 106125.041020sec        0.007msec             0.023msec
   eth4    66 106125.042291sec        0.003msec             0.012msec
   eth4    66 106125.043274sec        0.006msec             0.004msec
   eth4   850 106125.044283sec        0.007msec             0.018msec

The above is a transmit side. There are three check-time-points. Point1 is before putting a packet to Qdisc. point2 is after ndo_start_xmit in dev_hard_start_xmit. It indicates finishing putting a packet to driver. point3 is in consume_skb and kfree_skb. It indicates freeing a transmitted packet. Values of this script are, from left, device name, length of a packet, a time of point1, an interval time between point1 and point2 and an interval time between point2 and point3.

These times are useful to analyze a performance or to detect a point where packet delays. For example,
- NET_RX softirq calling is late.
- Application is late to take a packet.
- It takes much time to put a transmitting packet to driver (It may be caused by packed queue)

Quoted 5 lines

And also, these tracepoint help us to investigate a network driver's trouble from memory dump because ftrace records it to memory. And ftrace is so light even if always trace on. So, in a case investigating a problem which doesn't reproduce, it is useful.

The entire series:

-- Steve

#88 lore raw
Quoted 72 lines · Steven Rostedt
Quoted 65 lines · Koki Sanagi

Rebase to the latest net-next.

CHANGE-LOG since v3:
1) change arguments of softirq tracepoint into original one.
2) remove tracepoint of dev_kfree_skb_irq and skb_free_datagram_locked and add trace_kfree_skb before __kfree_skb instead of them.
3) add tracepoint to netif_rx and display it by netdev-times script.

These patch-set adds tracepoints to show us a process of packets. Using these tracepoints and existing points, we can get the time when packet passes through some points in transmit or receive sequence. For example, this is an output of perf script which is attached by patch 5/5.

106133.171439sec cpu=0
irq_entry(+0.000msec irq=24:eth4)

         |
  softirq_entry(+0.006msec)
         |
         |---netif_receive_skb(+0.010msec skb=f2d15900 len=100)
         |            |
         |      skb_copy_datagram_iovec(+0.039msec 10291::10291)
         |

napi_poll_exit(+0.022msec eth4)

106134.175634sec cpu=1
irq_entry(+0.000msec irq=28:eth1)

         |
         |---netif_rx(+0.009msec skb=f3ef0a00)
         |
  softirq_entry(+0.018msec)
         |
         |---netif_receive_skb(+0.021msec skb=f3ef0a00 len=84)
         |            |
         |      skb_copy_datagram_iovec(+0.033msec 0:swapper)
         |

napi_poll_exit(+0.035msec (no_device))

The above is a receive side(eth4 is NAPI. eth1 is non-NAPI). Like this, it can show receive sequence frominterrupt(irq_entry) to application (skb_copy_datagram_iovec).
This script shows one NET_RX softirq and events related to it. All relative time bases on first irq_entry which raise NET_RX softirq.

   dev    len      Qdisc               netdevice             free
   eth4    74 106125.030004sec        0.006msec             0.009msec
   eth4    87 106125.041020sec        0.007msec             0.023msec
   eth4    66 106125.042291sec        0.003msec             0.012msec
   eth4    66 106125.043274sec        0.006msec             0.004msec
   eth4   850 106125.044283sec        0.007msec             0.018msec

The above is a transmit side. There are three check-time-points. Point1 is before putting a packet to Qdisc. point2 is after ndo_start_xmit in dev_hard_start_xmit. It indicates finishing putting a packet to driver. point3 is in consume_skb and kfree_skb. It indicates freeing a transmitted packet. Values of this script are, from left, device name, length of a packet, a time of point1, an interval time between point1 and point2 and an interval time between point2 and point3.

These times are useful to analyze a performance or to detect a point where packet delays. For example,
- NET_RX softirq calling is late.
- Application is late to take a packet.
- It takes much time to put a transmitting packet to driver (It may be caused by packed queue)

Quoted 5 lines

And also, these tracepoint help us to investigate a network driver's trouble from memory dump because ftrace records it to memory. And ftrace is so light even if always trace on. So, in a case investigating a problem which doesn't reproduce, it is useful.

Quoted 6 lines

The entire series:

-- Steve

Thanks many acks. and I have one question.

These patches have several component.

Patch1 is kernel component, but patch2-5 are netdev component. What tree is good to be included ?
If it is not net-next, I must rebase to another tree.

Thanks,
Koki Sanagi.

maintainer
#89 lore raw

From: Koki Sanagi <[email protected]>
Date: Fri, 03 Sep 2010 11:10:51 +0900

Quoted 7 lines

Thanks many acks. and I have one question.

These patches have several component.

Patch1 is kernel component, but patch2-5 are netdev component. What tree is good to be included ?
If it is not net-next, I must rebase to another tree.

I would prefer it goes into the tracing tree or whatever is the most appropriate for patch #1.

#90 lore raw
Quoted 5 lines · David Miller

From: Koki Sanagi <[email protected]>
Date: Fri, 03 Sep 2010 11:10:51 +0900

Quoted 2 lines

Thanks many acks. and I have one question.

Quoted 9 lines
Quoted 5 lines

These patches have several component.

Patch1 is kernel component, but patch2-5 are netdev component. What tree is good to be included ?
If it is not net-next, I must rebase to another tree.

I would prefer it goes into the tracing tree or whatever is the most appropriate for patch #1.

O.K. I'll rebase to linux-2.6-tip.

Thanks,
Koki Sanagi.

#91 lore raw
Quoted 12 lines · Koki Sanagi
Quoted 11 lines · David Miller

From: Koki Sanagi <[email protected]>
Date: Fri, 03 Sep 2010 11:10:51 +0900

Quoted 7 lines

Thanks many acks. and I have one question.

These patches have several component.

Patch1 is kernel component, but patch2-5 are netdev component. What tree is good to be included ?
If it is not net-next, I must rebase to another tree.

Quoted 5 lines
Quoted 3 lines

I would prefer it goes into the tracing tree or whatever is the most appropriate for patch #1.

O.K. I'll rebase to linux-2.6-tip.

No need, they apply very well :)

I'll push that to -tip soon.

Thanks.

#92 lore raw
Quoted 17 lines · Frederic Weisbecker
Quoted 16 lines · Koki Sanagi
Quoted 14 lines · David Miller

From: Koki Sanagi <[email protected]>
Date: Fri, 03 Sep 2010 11:10:51 +0900

Quoted 7 lines

Thanks many acks. and I have one question.

These patches have several component.

Patch1 is kernel component, but patch2-5 are netdev component. What tree is good to be included ?
If it is not net-next, I must rebase to another tree.

I would prefer it goes into the tracing tree or whatever is the most appropriate for patch #1.

Quoted 9 lines
Quoted 1 line

O.K. I'll rebase to linux-2.6-tip.

No need, they apply very well :)

I'll push that to -tip soon.

Thanks.

O.K. Thanks!

Koki Sanagi.

#2 lore raw

Re: [PATCH v4 1/5] irq: add tracepoint to softirq_raise

In reply to Koki Sanagi
Quoted 64 lines · Koki Sanagi

From: Lai Jiangshan <[email protected]>

Add a tracepoint for tracing when softirq action is raised.

It and the existed tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)
include/linux/interrupt.h +7 -1
index a0384a4..d3e8e90 100644
@@ -18,6 +18,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <trace/events/irq.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)&nr, NULL);
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
include/trace/events/irq.h +3 -1
index 0e4cfb6..3ddda02 100644
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 102

Quoted 9 lines
include/trace/events/irq.h +4 -1
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
 	),

It seems that this will break softirq_entry/exit tracepoints. __entry->vec will deref vec->action() for these two, which is not what we want.

If you can't have the same tracepoint signature for the three, just split the new one in a seperate TRACE_EVENT().

Thanks.

maintainer
#3 lore raw

Re: [PATCH v4 1/5] irq: add tracepoint to softirq_raise

Quoted 5 lines · Frederic Weisbecker
Quoted 5 lines

#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
#define show_softirq_name(val) \

(quoted diff) +0 -0
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
Quoted 13 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 102

Quoted 7 lines
include/trace/events/irq.h +4 -1
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
 	),

It seems that this will break softirq_entry/exit tracepoints. __entry->vec will deref vec->action() for these two, which is not what we want.

But for trace_softirq_entry and trace_softirq_exit, vec will not be NULL.

Quoted 3 lines

If you can't have the same tracepoint signature for the three, just split the new one in a seperate TRACE_EVENT().

It may be a bit of a hack, and questionable about adding another TRACE_EVENT(). There still is a pretty good space savings in using DEFINE_EVENT() over TRACE_EVENT() though.

-- Steve

#4 lore raw

Re: [PATCH v4 1/5] irq: add tracepoint to softirq_raise

Quoted 21 lines · Steven Rostedt
Quoted 5 lines · Frederic Weisbecker
Quoted 5 lines

#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
#define show_softirq_name(val) \

(quoted diff) +0 -0
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
Quoted 13 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 102

Quoted 7 lines
include/trace/events/irq.h +4 -1
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
 	),

It seems that this will break softirq_entry/exit tracepoints. __entry->vec will deref vec->action() for these two, which is not what we want.

Quoted 2 lines

But for trace_softirq_entry and trace_softirq_exit, vec will not be NULL.

Oh right...

/me slaps his forehead

Quoted 8 lines
Quoted 4 lines

If you can't have the same tracepoint signature for the three, just split the new one in a seperate TRACE_EVENT().

It may be a bit of a hack, and questionable about adding another TRACE_EVENT(). There still is a pretty good space savings in using DEFINE_EVENT() over TRACE_EVENT() though.

Yeah, let's keep it as is.

maintainer
#5 lore raw

Re: [PATCH v4 1/5] irq: add tracepoint to softirq_raise

In reply to Frederic Weisbecker
Quoted 10 lines · Frederic Weisbecker

include/linux/interrupt.h asmlinkage void do_softirq(void); · line 413

Quoted 10 lines

/*
* These correspond to the IORESOURCE_IRQ_* defines in

include/linux/interrupt.h +3 -1
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)&nr, NULL);

Perhaps doing:

	trace_softirq_raise((struct softirq_action *)((unsigend long)nr),
				NULL);

and ...

Quoted 24 lines
Quoted 24 lines
include/linux/interrupt.h +3 -0
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
include/trace/events/irq.h +3 -1
index 0e4cfb6..3ddda02 100644
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
Quoted 6 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 101

Quoted 6 lines
include/trace/events/irq.h +4 -1
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
			__entry->vec = (int)h;

would be better.

Quoted 10 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 102

Quoted 1 line
include/trace/events/irq.h +0 -0
 	),

It seems that this will break softirq_entry/exit tracepoints. __entry->vec will deref vec->action() for these two, which is not what we want.

If you can't have the same tracepoint signature for the three, just split the new one in a seperate TRACE_EVENT().

Doing the above will at least be a bit safer.

-- Steve

#6 lore raw

Re: [PATCH v4 1/5] irq: add tracepoint to softirq_raise

Quoted 60 lines · Steven Rostedt
Quoted 10 lines · Frederic Weisbecker

include/linux/interrupt.h asmlinkage void do_softirq(void); · line 413

Quoted 10 lines

/*
* These correspond to the IORESOURCE_IRQ_* defines in

include/linux/interrupt.h +3 -1
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)&nr, NULL);

Perhaps doing:

	trace_softirq_raise((struct softirq_action *)((unsigend long)nr),
				NULL);

and ...

Quoted 24 lines
Quoted 24 lines
include/linux/interrupt.h +3 -0
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
include/trace/events/irq.h +3 -1
index 0e4cfb6..3ddda02 100644
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
Quoted 6 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 101

Quoted 6 lines
include/trace/events/irq.h +4 -1
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
			__entry->vec = (int)h;

would be better.

Quoted 4 lines
Quoted 1 line
include/trace/events/irq.h +0 -0
 	),
Quoted 8 lines
Quoted 6 lines

It seems that this will break softirq_entry/exit tracepoints. __entry->vec will deref vec->action() for these two, which is not what we want.

If you can't have the same tracepoint signature for the three, just split the new one in a seperate TRACE_EVENT().

Doing the above will at least be a bit safer.

Agreed, I'm going to change that in the patch.

Thanks.

#7 lore raw

Re: [PATCH v4 1/5] irq: add tracepoint to softirq_raise

Quoted 68 lines · Frederic Weisbecker
Quoted 67 lines · Steven Rostedt
Quoted 10 lines · Frederic Weisbecker

include/linux/interrupt.h asmlinkage void do_softirq(void); · line 413

Quoted 10 lines

/*
* These correspond to the IORESOURCE_IRQ_* defines in

include/linux/interrupt.h +3 -1
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)&nr, NULL);

Perhaps doing:

	trace_softirq_raise((struct softirq_action *)((unsigend long)nr),
				NULL);

and ...

Quoted 24 lines
Quoted 24 lines
include/linux/interrupt.h +3 -0
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
include/trace/events/irq.h +3 -1
index 0e4cfb6..3ddda02 100644
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
Quoted 6 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 101

Quoted 6 lines
include/trace/events/irq.h +4 -1
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = *((int *)h);
			__entry->vec = (int)h;

would be better.

Quoted 10 lines

include/trace/events/irq.h DECLARE_EVENT_CLASS(softirq, · line 102

Quoted 1 line
include/trace/events/irq.h +0 -0
 	),

It seems that this will break softirq_entry/exit tracepoints. __entry->vec will deref vec->action() for these two, which is not what we want.

If you can't have the same tracepoint signature for the three, just split the new one in a seperate TRACE_EVENT().

Quoted 7 lines
Quoted 1 line

Doing the above will at least be a bit safer.

Agreed, I'm going to change that in the patch.

Thanks.

I agree.

Thanks,
Koki Sanagi.

#85 lore raw

Re: [PATCH v4 5/5] perf:add a script shows a process of packet

In reply to Koki Sanagi
Quoted 53 lines · Koki Sanagi

Add a perf script which shows a process of packets and processed time. It helps us to investigate networking or network device.

If you want to use it, install perf and record perf.data like following.

#perf trace record netdev-times [script]

If you set script, perf gathers records until it ends. If not, you must Ctrl-C to stop recording.

And if you want a report from record,

#perf trace report netdev-times [options]

If you use some options, you can limit an output.
Option is below.

tx: show only process of tx packets
rx: show only process of rx packets
dev=: show a process specified with this option
debug: work with debug mode. It shows buffer status.

For example, if you want to show a process of received packets associated with eth4,

#perf trace report netdev-times rx dev=eth4
106133.171439sec cpu=0
irq_entry(+0.000msec irq=24:eth4)

         |
  softirq_entry(+0.006msec)
         |
         |---netif_receive_skb(+0.010msec skb=f2d15900 len=100)
         |            |
         |      skb_copy_datagram_iovec(+0.039msec 10291::10291)
         |

napi_poll_exit(+0.022msec eth4)

This perf script helps us to analyze a process time of transmit/receive sequence.

---
 tools/perf/scripts/python/bin/netdev-times-record |    8 +
 tools/perf/scripts/python/bin/netdev-times-report |    5 +
 tools/perf/scripts/python/netdev-times.py         |  464 +++++++++++++++++++++
 3 files changed, 477 insertions(+), 0 deletions(-)
tools/perf/scripts/python/bin/netdev-times-record new file +0 -0
new file mode 100644
index 0000000..2b59511

tools/perf/scripts/python/bin/netdev-times-record line 2

Quoted 2 lines
tools/perf/scripts/python/bin/netdev-times-record new file +2 -0
@@ -0,0 +1,8 @@
+#!/bin/bash
+perf record -c 1 -f -R -a -e net:net_dev_xmit -e net:net_dev_queue	\

Nano-nits:

-c 1 and -R are now default settings for tracepoints and -f is not needed anymore. I've removed them.

tools/perf/scripts/python/bin/netdev-times-record line 3

Quoted 1 line
tools/perf/scripts/python/bin/netdev-times-record new file +1 -0
+all_event_list = []; # insert all tracepoint event related with this script

Ah I didn't know ";" works with python :)

tools/perf/scripts/python/bin/netdev-times-record line 7

Quoted 4 lines
tools/perf/scripts/python/bin/netdev-times-record new file +4 -0
+def trace_end():
+	# order all events in time
+	all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME],
+					    b[EINFO_IDX_TIME]))

Events already arrive in time order to the scripts.

Thnaks!

#8 lore raw

[tip:perf/core] irq: Add tracepoint to softirq_raise

In reply to Koki Sanagi
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

Cc David Miller <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>

LKML-Reference: <[email protected]>

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)
include/linux/interrupt.h +7 -1
index a0384a4..531495d 100644
@@ -18,6 +18,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <trace/events/irq.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
@@ -407,7 +408,12 @@ asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 extern void wakeup_softirqd(void);
include/trace/events/irq.h +24 -2
index 0e4cfb6..6fa7cba 100644
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\
@@ -93,7 +95,10 @@ DECLARE_EVENT_CLASS(softirq,
 	),
 
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = (int)(long)h;
 	),
 
 	TP_printk("vec=%d [action=%s]", __entry->vec,
@@ -136,6 +141,23 @@ DEFINE_EVENT(softirq, softirq_exit,
 	TP_ARGS(h, vec)
 );
 
+/**
+ * softirq_raise - called immediately when a softirq is raised
+ * @h: pointer to struct softirq_action
+ * @vec: pointer to first struct softirq_action in softirq_vec array
+ *
+ * The @h parameter contains a pointer to the softirq vector number which is
+ * raised. @vec is NULL and it means @h includes vector number not
+ * softirq_action. When used in combination with the softirq_entry tracepoint
+ * we can determine the softirq raise latency.
+ */
+DEFINE_EVENT(softirq, softirq_raise,
+
+	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+
+	TP_ARGS(h, vec)
+);
+
 #endif /*  _TRACE_IRQ_H */
 
 /* This part must be outside protection */
#76 lore raw

[tip:perf/core] napi: Convert trace_napi_poll to TRACE_EVENT

In reply to Koki Sanagi
Commit-ID:  3e4b10d7a4d2a78af64f8096dc7cdb3bebd65adb
Gitweb:     http://git.kernel.org/tip/3e4b10d7a4d2a78af64f8096dc7cdb3bebd65adb
Author:     Neil Horman <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:43:51 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:51:01 +0200

napi: Convert trace_napi_poll to TRACE_EVENT

This patch converts trace_napi_poll from DECLARE_EVENT to TRACE_EVENT to improve the usability of napi_poll tracepoint.

          <idle>-0     [001] 241302.750777: napi_poll: napi poll on napi struct f6acc480 for device eth3
          <idle>-0     [000] 241302.852389: napi_poll: napi poll on napi struct f5d0d70c for device eth1

The original patch is below:
http://marc.info/?l=linux-kernel&m=126021713809450&w=2

[ [email protected]: And add a fix by Steven Rostedt:
http://marc.info/?l=linux-kernel&m=126150506519173&w=2 ]

Cc Mathieu Desnoyers <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>

LKML-Reference: <[email protected]>

---
 include/trace/events/napi.h |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)
include/trace/events/napi.h +23 -2
index 188deca..8fe1e93 100644
@@ -6,10 +6,31 @@
 
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
+#include <linux/ftrace.h>
+
+#define NO_DEV "(no_device)"
+
+TRACE_EVENT(napi_poll,
 
-DECLARE_TRACE(napi_poll,
 	TP_PROTO(struct napi_struct *napi),
-	TP_ARGS(napi));
+
+	TP_ARGS(napi),
+
+	TP_STRUCT__entry(
+		__field(	struct napi_struct *,	napi)
+		__string(	dev_name, napi->dev ? napi->dev->name : NO_DEV)
+	),
+
+	TP_fast_assign(
+		__entry->napi = napi;
+		__assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV);
+	),
+
+	TP_printk("napi poll on napi struct %p for device %s",
+		__entry->napi, __get_str(dev_name))
+);
+
+#undef NO_DEV
 
 #endif /* _TRACE_NAPI_H_ */
 
#79 lore raw

[tip:perf/core] netdev: Add tracepoints to netdev layer

In reply to Koki Sanagi
Commit-ID:  cf66ba58b5cb8b1526e9dd2fb96ff8db048d4d44
Gitweb:     http://git.kernel.org/tip/cf66ba58b5cb8b1526e9dd2fb96ff8db048d4d44
Author:     Koki Sanagi <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:45:02 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:51:33 +0200

netdev: Add tracepoints to netdev layer

This patch adds tracepoint to dev_queue_xmit, dev_hard_start_xmit, netif_rx and netif_receive_skb. These tracepoints help you to monitor network driver's input/output.

          <idle>-0     [001] 112447.902030: netif_rx: dev=eth1 skbaddr=f3ef0900 len=84
          <idle>-0     [001] 112447.902039: netif_receive_skb: dev=eth1 skbaddr=f3ef0900 len=84
            sshd-6828  [000] 112447.903257: net_dev_queue: dev=eth4 skbaddr=f3fca538 len=226
            sshd-6828  [000] 112447.903260: net_dev_xmit: dev=eth4 skbaddr=f3fca538 len=226 rc=0
Cc Mathieu Desnoyers <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>

LKML-Reference: <[email protected]>

---
 include/trace/events/net.h |   82 ++++++++++++++++++++++++++++++++++++++++++++
 net/core/dev.c             |    6 +++
 net/core/net-traces.c      |    1 +
 3 files changed, 89 insertions(+), 0 deletions(-)
include/trace/events/net.h new file +82 -0
new file mode 100644
index 0000000..5f247f5
@@ -0,0 +1,82 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM net
+
+#if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_NET_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(net_dev_xmit,
+
+	TP_PROTO(struct sk_buff *skb,
+		 int rc),
+
+	TP_ARGS(skb, rc),
+
+	TP_STRUCT__entry(
+		__field(	void *,		skbaddr		)
+		__field(	unsigned int,	len		)
+		__field(	int,		rc		)
+		__string(	name,		skb->dev->name	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+		__entry->len = skb->len;
+		__entry->rc = rc;
+		__assign_str(name, skb->dev->name);
+	),
+
+	TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+		__get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
+);
+
+DECLARE_EVENT_CLASS(net_dev_template,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(	void *,		skbaddr		)
+		__field(	unsigned int,	len		)
+		__string(	name,		skb->dev->name	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+		__entry->len = skb->len;
+		__assign_str(name, skb->dev->name);
+	),
+
+	TP_printk("dev=%s skbaddr=%p len=%u",
+		__get_str(name), __entry->skbaddr, __entry->len)
+)
+
+DEFINE_EVENT(net_dev_template, net_dev_queue,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_receive_skb,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_rx,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+#endif /* _TRACE_NET_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
net/core/dev.c +6 -0
index 3721fbb..5a4fbc7 100644
@@ -128,6 +128,7 @@
 #include <linux/jhash.h>
 #include <linux/random.h>
 #include <trace/events/napi.h>
+#include <trace/events/net.h>
 #include <linux/pci.h>
 
 #include "net-sysfs.h"
@@ -1978,6 +1979,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 		}
 
 		rc = ops->ndo_start_xmit(skb, dev);
+		trace_net_dev_xmit(skb, rc);
 		if (rc == NETDEV_TX_OK)
 			txq_trans_update(txq);
 		return rc;
@@ -1998,6 +2000,7 @@ gso:
 			skb_dst_drop(nskb);
 
 		rc = ops->ndo_start_xmit(nskb, dev);
+		trace_net_dev_xmit(nskb, rc);
 		if (unlikely(rc != NETDEV_TX_OK)) {
 			if (rc & ~NETDEV_TX_MASK)
 				goto out_kfree_gso_skb;
@@ -2186,6 +2189,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 #ifdef CONFIG_NET_CLS_ACT
 	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
 #endif
+	trace_net_dev_queue(skb);
 	if (q->enqueue) {
 		rc = __dev_xmit_skb(skb, q, dev, txq);
 		goto out;
@@ -2512,6 +2516,7 @@ int netif_rx(struct sk_buff *skb)
 	if (netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
+	trace_netif_rx(skb);
 #ifdef CONFIG_RPS
 	{
 		struct rps_dev_flow voidflow, *rflow = &voidflow;
@@ -2828,6 +2833,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
 	if (!netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
+	trace_netif_receive_skb(skb);
 	if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
 		return NET_RX_SUCCESS;
 
net/core/net-traces.c +1 -0
index afa6380..7f1bb2a 100644
@@ -26,6 +26,7 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/skb.h>
+#include <trace/events/net.h>
 #include <trace/events/napi.h>
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
#82 lore raw

[tip:perf/core] skb: Add tracepoints to freeing skb

In reply to Koki Sanagi
Commit-ID:  07dc22e7295f25526f110d704655ff0ea7687420
Gitweb:     http://git.kernel.org/tip/07dc22e7295f25526f110d704655ff0ea7687420
Author:     Koki Sanagi <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:46:12 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:51:53 +0200

skb: Add tracepoints to freeing skb

This patch adds tracepoint to consume_skb and add trace_kfree_skb before __kfree_skb in skb_free_datagram_locked and net_tx_action. Combinating with tracepoint on dev_hard_start_xmit, we can check how long it takes to free transmitted packets. And using it, we can calculate how many packets driver had at that time. It is useful when a drop of transmitted packet is a problem.

            sshd-6828  [000] 112689.258154: consume_skb: skbaddr=f2d99bb8
Cc Mathieu Desnoyers <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>

LKML-Reference: <[email protected]>

---
 include/trace/events/skb.h |   17 +++++++++++++++++
 net/core/datagram.c        |    1 +
 net/core/dev.c             |    2 ++
 net/core/skbuff.c          |    1 +
 4 files changed, 21 insertions(+), 0 deletions(-)
include/trace/events/skb.h +17 -0
index 4b2be6d..75ce9d5 100644
@@ -35,6 +35,23 @@ TRACE_EVENT(kfree_skb,
 		__entry->skbaddr, __entry->protocol, __entry->location)
 );
 
+TRACE_EVENT(consume_skb,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(	void *,	skbaddr	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+	),
+
+	TP_printk("skbaddr=%p", __entry->skbaddr)
+);
+
 TRACE_EVENT(skb_copy_datagram_iovec,
 
 	TP_PROTO(const struct sk_buff *skb, int len),
net/core/datagram.c +1 -0
index 251997a..282806b 100644
@@ -243,6 +243,7 @@ void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
 	unlock_sock_fast(sk, slow);
 
 	/* skb is now orphaned, can be freed outside of locked section */
+	trace_kfree_skb(skb, skb_free_datagram_locked);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(skb_free_datagram_locked);
net/core/dev.c +2 -0
index 5a4fbc7..2308cce 100644
@@ -129,6 +129,7 @@
 #include <linux/random.h>
 #include <trace/events/napi.h>
 #include <trace/events/net.h>
+#include <trace/events/skb.h>
 #include <linux/pci.h>
 
 #include "net-sysfs.h"
@@ -2576,6 +2577,7 @@ static void net_tx_action(struct softirq_action *h)
 			clist = clist->next;
 
 			WARN_ON(atomic_read(&skb->users));
+			trace_kfree_skb(skb, net_tx_action);
 			__kfree_skb(skb);
 		}
 	}
net/core/skbuff.c +1 -0
index 3a2513f..12e61e3 100644
@@ -466,6 +466,7 @@ void consume_skb(struct sk_buff *skb)
 		smp_rmb();
 	else if (likely(!atomic_dec_and_test(&skb->users)))
 		return;
+	trace_consume_skb(skb);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(consume_skb);
#86 lore raw

[tip:perf/core] perf: Add a script to show packets processing

In reply to Koki Sanagi
Commit-ID:  359d5106a2ff4ffa2ba129ec8f54743c341dabfc
Gitweb:     http://git.kernel.org/tip/359d5106a2ff4ffa2ba129ec8f54743c341dabfc
Author:     Koki Sanagi <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:47:09 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 18:43:32 +0200

perf: Add a script to show packets processing

Add a perf script which shows packets processing and processed time. It helps us to investigate networking or network devices.

If you want to use it, install perf and record perf.data like following.

If you set script, perf gathers records until it ends. If not, you must Ctrl-C to stop recording.

And if you want a report from record,

If you use some options, you can limit the output. Option is below.

tx: show only tx packets processing
rx: show only rx packets processing
dev=: show processing on this device
debug: work with debug mode. It shows buffer status.

For example, if you want to show received packets processing associated with eth4,

106133.171439sec cpu=0
irq_entry(+0.000msec irq=24:eth4)

         |
  softirq_entry(+0.006msec)
         |
         |---netif_receive_skb(+0.010msec skb=f2d15900 len=100)
         |            |
         |      skb_copy_datagram_iovec(+0.039msec 10291::10291)
         |

napi_poll_exit(+0.022msec eth4)

This perf script helps us to analyze the processing time of a transmit/receive sequence.

Cc Neil Horman <[email protected]>
Cc Mathieu Desnoyers <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc Tom Zanussi <[email protected]>

LKML-Reference: <[email protected]>

---
 tools/perf/scripts/python/bin/netdev-times-record |    8 +
 tools/perf/scripts/python/bin/netdev-times-report |    5 +
 tools/perf/scripts/python/netdev-times.py         |  464 +++++++++++++++++++++
 3 files changed, 477 insertions(+), 0 deletions(-)
tools/perf/scripts/python/bin/netdev-times-record new file +8 -0
new file mode 100644
index 0000000..d931a82
@@ -0,0 +1,8 @@
+#!/bin/bash
+perf record -a -e net:net_dev_xmit -e net:net_dev_queue		\
+		-e net:netif_receive_skb -e net:netif_rx		\
+		-e skb:consume_skb -e skb:kfree_skb			\
+		-e skb:skb_copy_datagram_iovec -e napi:napi_poll	\
+		-e irq:irq_handler_entry -e irq:irq_handler_exit	\
+		-e irq:softirq_entry -e irq:softirq_exit		\
+		-e irq:softirq_raise $@
tools/perf/scripts/python/bin/netdev-times-report new file +5 -0
new file mode 100644
index 0000000..c3d0a63
@@ -0,0 +1,5 @@
+#!/bin/bash
+# description: display a process of packet and processing time
+# args: [tx] [rx] [dev=] [debug]
+
+perf trace -s ~/libexec/perf-core/scripts/python/netdev-times.py $@
tools/perf/scripts/python/netdev-times.py new file +464 -0

464 lines not on this page · raw message

#9 lore raw

[sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

In reply to tip-bot for Lai Jiangshan
Quoted 29 lines · tip-bot for Lai Jiangshan
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

Cc David Miller <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>
Quoted 8 lines

LKML-Reference: <[email protected]>

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)

FYI, this commit broke the Sparc build:

In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

                 from /home/mingo/tip/arch/sparc/include/asm/irq.h:6,
                 from /home/mingo/tip/include/linux/irqnr.h:10,
                 from /home/mingo/tip/include/linux/irq.h:22,
                 from /home/mingo/tip/include/asm-generic/hardirq.h:6,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq_32.h:11,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq.h:6,
                 from /home/mingo/tip/include/linux/hardirq.h:10,
                 from /home/mingo/tip/include/linux/ftrace_event.h:7,
                 from /home/mingo/tip/include/trace/syscall.h:6,
                 from /home/mingo/tip/include/linux/syscalls.h:76,
                 from /home/mingo/tip/init/initramfs.c:9:

/home/mingo/tip/include/linux/interrupt.h: In function '__raise_softirq_irqoff':
/home/mingo/tip/include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' /home/mingo/tip/include/linux/interrupt.h:414: error: lvalue required as left operand of assignment make[2]: *** [init/initramfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

Ingo

#10 lore raw

PATCH 1/1 irq: Fix circular headers dependency

Quoted 55 lines · Ingo Molnar
Quoted 29 lines · tip-bot for Lai Jiangshan
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

Cc David Miller <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>
Quoted 8 lines

LKML-Reference: <[email protected]>

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)

FYI, this commit broke the Sparc build:

In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

                 from /home/mingo/tip/arch/sparc/include/asm/irq.h:6,
                 from /home/mingo/tip/include/linux/irqnr.h:10,
                 from /home/mingo/tip/include/linux/irq.h:22,
                 from /home/mingo/tip/include/asm-generic/hardirq.h:6,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq_32.h:11,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq.h:6,
                 from /home/mingo/tip/include/linux/hardirq.h:10,
                 from /home/mingo/tip/include/linux/ftrace_event.h:7,
                 from /home/mingo/tip/include/trace/syscall.h:6,
                 from /home/mingo/tip/include/linux/syscalls.h:76,
                 from /home/mingo/tip/init/initramfs.c:9:
Quoted 8 lines

/home/mingo/tip/include/linux/interrupt.h: In function '__raise_softirq_irqoff':
/home/mingo/tip/include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' /home/mingo/tip/include/linux/interrupt.h:414: error: lvalue required as left operand of assignment make[2]: *** [init/initramfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

Ingo

Yeah, there is a circular dependency.
Does that fixes the issue (and if so, does that look sane)?

Thanks.

---

Quoted 1 line

From fc21eaa02d4a6f0af396af6a106587e61515cd86 Mon Sep 17 00:00:00 2001

From: Frederic Weisbecker <[email protected]>
Date: Wed, 8 Sep 2010 14:17:31 +0200
Subject: [PATCH] irq: Fix circular headers dependency

asm-generic/hardirq.h needs asm/irq.h which might include linux/interrupt.h as in the sparc 32 case. At this point we need irq_cpustat generic definitions, but those are included later in asm-generic/hardirq.h.

Then delay a bit the inclusion of irq.h from asm-generic/hardirq.h, it doesn't need to be included early.

This fixes:

In file included from arch/sparc/include/asm/irq_32.h:11,

                  from arch/sparc/include/asm/irq.h:6,
                  from include/linux/irqnr.h:10,
                  from include/linux/irq.h:22,
                  from include/asm-generic/hardirq.h:6,
                  from arch/sparc/include/asm/hardirq_32.h:11,
                  from arch/sparc/include/asm/hardirq.h:6,
                  from include/linux/hardirq.h:10,
                  from include/linux/ftrace_event.h:7,
                  from include/trace/syscall.h:6,
                  from include/linux/syscalls.h:76,
                  from init/initramfs.c:9:

include/linux/interrupt.h: In function '__raise_softirq_irqoff':
include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' include/linux/interrupt.h:414: error: lvalue required as left operand of assignment

---
 include/asm-generic/hardirq.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/asm-generic/hardirq.h +1 -1
index 62f5908..04d0a97 100644
@@ -3,13 +3,13 @@
 
 #include <linux/cache.h>
 #include <linux/threads.h>
-#include <linux/irq.h>
 
 typedef struct {
 	unsigned int __softirq_pending;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+#include <linux/irq.h>
 
 #ifndef ack_bad_irq
 static inline void ack_bad_irq(unsigned int irq)
Signature · 1 line
1.6.2.3
#11 lore raw

[tip:perf/core] irq: Fix circular headers dependency

Commit-ID:  3b8fad3e2f5f69bfd8e42d099ca8582fb2342edf
Gitweb:     http://git.kernel.org/tip/3b8fad3e2f5f69bfd8e42d099ca8582fb2342edf
Author:     Frederic Weisbecker <[email protected]>
AuthorDate: Wed, 8 Sep 2010 14:26:00 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Thu, 9 Sep 2010 21:28:58 +0200

irq: Fix circular headers dependency

asm-generic/hardirq.h needs asm/irq.h which might include linux/interrupt.h as in the sparc 32 case. At this point we need irq_cpustat generic definitions, but those are included later in asm-generic/hardirq.h.

Then delay a bit the inclusion of irq.h from asm-generic/hardirq.h, it doesn't need to be included early.

This fixes:

include/linux/interrupt.h: In function '__raise_softirq_irqoff':
include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' include/linux/interrupt.h:414: error: lvalue required as left operand of assignment

LKML-Reference: <20100908122557.GA5310@nowhere>

---
 include/asm-generic/hardirq.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/asm-generic/hardirq.h +1 -1
index 62f5908..04d0a97 100644
@@ -3,13 +3,13 @@
 
 #include <linux/cache.h>
 #include <linux/threads.h>
-#include <linux/irq.h>
 
 typedef struct {
 	unsigned int __softirq_pending;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+#include <linux/irq.h>
 
 #ifndef ack_bad_irq
 static inline void ack_bad_irq(unsigned int irq)
maintainer
#12 lore raw

Re: [sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

In reply to Ingo Molnar
Quoted 54 lines · Ingo Molnar
Quoted 29 lines · tip-bot for Lai Jiangshan
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

Cc David Miller <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>
Quoted 8 lines

LKML-Reference: <[email protected]>

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)

FYI, this commit broke the Sparc build:

In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

                 from /home/mingo/tip/arch/sparc/include/asm/irq.h:6,
                 from /home/mingo/tip/include/linux/irqnr.h:10,
                 from /home/mingo/tip/include/linux/irq.h:22,
                 from /home/mingo/tip/include/asm-generic/hardirq.h:6,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq_32.h:11,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq.h:6,
                 from /home/mingo/tip/include/linux/hardirq.h:10,
                 from /home/mingo/tip/include/linux/ftrace_event.h:7,
                 from /home/mingo/tip/include/trace/syscall.h:6,
                 from /home/mingo/tip/include/linux/syscalls.h:76,
                 from /home/mingo/tip/init/initramfs.c:9:
Quoted 6 lines

/home/mingo/tip/include/linux/interrupt.h: In function '__raise_softirq_irqoff':
/home/mingo/tip/include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' /home/mingo/tip/include/linux/interrupt.h:414: error: lvalue required as left operand of assignment make[2]: *** [init/initramfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

I could build sparc64_defconfig, but s390 is broken for me by this...

maintainer
#13 lore raw

Re: [sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

Quoted 42 lines · Peter Zijlstra
Quoted 31 lines · Ingo Molnar
Quoted 29 lines · tip-bot for Lai Jiangshan
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

Cc David Miller <[email protected]>
Cc Kaneshige Kenji <[email protected]>
Cc Izumo Taku <[email protected]>
Cc Kosaki Motohiro <[email protected]>
Cc Lai Jiangshan <[email protected]>
Cc Scott Mcmillan <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Eric Dumazet <[email protected]>
Quoted 9 lines
Quoted 8 lines

LKML-Reference: <[email protected]>

[ factorize softirq events with DECLARE_EVENT_CLASS ]
---
 include/linux/interrupt.h  |    8 +++++++-
 include/trace/events/irq.h |   26 ++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)
Quoted 1 line

I could build sparc64_defconfig, but s390 is broken for me by this...

the below makes s390 build again, not sure its completely safe for all configs though...

Heiko?

---
 arch/s390/include/asm/hardirq.h |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
(quoted diff) +0 -0

b/arch/s390/include/asm/hardirq.h
index 498bc38..9558a71 100644

arch/s390/include/asm/hardirq.h +0 -1
@@ -15,7 +15,6 @@
 #include <linux/threads.h>
 #include <linux/sched.h>
 #include <linux/cache.h>
-#include <linux/interrupt.h>
 #include <asm/lowcore.h>
 
 #define local_softirq_pending() (S390_lowcore.softirq_pending)
#14 lore raw

Re: [sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

Quoted 7 lines · Peter Zijlstra
Quoted 1 line

I could build sparc64_defconfig, but s390 is broken for me by this...

the below makes s390 build again, not sure its completely safe for all configs though...

Heiko?

We have a similar patch in our git tree to fix this issue:

http://git390.marist.edu/cgi-bin/gitweb.cgi?p=linux-2.6.git;a=commitdiff;h=b722c7e6ce9b52b58a5488aacfd90936a2720dd9

(link valid until the next rebase ;)

Quoted 18 lines
---
 arch/s390/include/asm/hardirq.h |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
arch/s390/include/asm/hardirq.h +0 -1
index 498bc38..9558a71 100644
@@ -15,7 +15,6 @@
 #include <linux/threads.h>
 #include <linux/sched.h>
 #include <linux/cache.h>
-#include <linux/interrupt.h>
 #include <asm/lowcore.h>
 
 #define local_softirq_pending() (S390_lowcore.softirq_pending)
maintainer
#15 lore raw

Re: [sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

In reply to Peter Zijlstra
Quoted 41 lines · Peter Zijlstra
Quoted 33 lines · Ingo Molnar
Quoted 9 lines · tip-bot for Lai Jiangshan
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Quoted 9 lines

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

                 from /home/mingo/tip/arch/sparc/include/asm/irq.h:6,
                 from /home/mingo/tip/include/linux/irqnr.h:10,
                 from /home/mingo/tip/include/linux/irq.h:22,
                 from /home/mingo/tip/include/asm-generic/hardirq.h:6,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq_32.h:11,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq.h:6,
                 from /home/mingo/tip/include/linux/hardirq.h:10,
                 from /home/mingo/tip/include/linux/ftrace_event.h:7,
                 from /home/mingo/tip/include/trace/syscall.h:6,
                 from /home/mingo/tip/include/linux/syscalls.h:76,
                 from /home/mingo/tip/init/initramfs.c:9:
Quoted 6 lines

/home/mingo/tip/include/linux/interrupt.h: In function '__raise_softirq_irqoff':
/home/mingo/tip/include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' /home/mingo/tip/include/linux/interrupt.h:414: error: lvalue required as left operand of assignment make[2]: *** [init/initramfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

Quoted 1 line

I could build sparc64_defconfig, but s390 is broken for me by this...

/me being very grumpy @ Lai.. ia64 is broken too!

/me goes revert this shite

#16 lore raw

Re: [sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

Quoted 42 lines · Peter Zijlstra
Quoted 41 lines · Peter Zijlstra
Quoted 39 lines · Ingo Molnar
Quoted 9 lines · tip-bot for Lai Jiangshan
Commit-ID:  2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Gitweb:     http://git.kernel.org/tip/2bf2160d8805de64308e2e7c3cd97813cb58ed2f
Author:     Lai Jiangshan <[email protected]>
AuthorDate: Mon, 23 Aug 2010 18:42:48 +0900
Committer:  Frederic Weisbecker <[email protected]>
CommitDate: Tue, 7 Sep 2010 17:49:34 +0200

irq: Add tracepoint to softirq_raise

Quoted 9 lines

Add a tracepoint for tracing when softirq action is raised.

This and the existing tracepoints complete softirq's tracepoints:
softirq_raise, softirq_entry and softirq_exit.

And when this tracepoint is used in combination with the softirq_entry tracepoint we can determine the softirq raise latency.

In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

                 from /home/mingo/tip/arch/sparc/include/asm/irq.h:6,
                 from /home/mingo/tip/include/linux/irqnr.h:10,
                 from /home/mingo/tip/include/linux/irq.h:22,
                 from /home/mingo/tip/include/asm-generic/hardirq.h:6,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq_32.h:11,
                 from /home/mingo/tip/arch/sparc/include/asm/hardirq.h:6,
                 from /home/mingo/tip/include/linux/hardirq.h:10,
                 from /home/mingo/tip/include/linux/ftrace_event.h:7,
                 from /home/mingo/tip/include/trace/syscall.h:6,
                 from /home/mingo/tip/include/linux/syscalls.h:76,
                 from /home/mingo/tip/init/initramfs.c:9:

/home/mingo/tip/include/linux/interrupt.h: In function '__raise_softirq_irqoff':
/home/mingo/tip/include/linux/interrupt.h:414: error: implicit declaration of function 'local_softirq_pending' /home/mingo/tip/include/linux/interrupt.h:414: error: lvalue required as left operand of assignment make[2]: *** [init/initramfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/mingo/tip/arch/sparc/include/asm/irq_32.h:11,

Quoted 6 lines
Quoted 1 line

I could build sparc64_defconfig, but s390 is broken for me by this...

/me being very grumpy @ Lai.. ia64 is broken too!

/me goes revert this shite

Now it is fixed.

http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h=9f081ce5da2c8af297a0a7d15a57fb4beeed374b;hp=43e3bf203456c4f06bdd6060426976ad2bed9081

maintainer
#17 lore raw

Re: [sparc build bug] Re: [tip:perf/core] irq: Add tracepoint to softirq_raise

Quoted 11 lines · Koki Sanagi
Quoted 1 line
Quoted 1 line

I could build sparc64_defconfig, but s390 is broken for me by

this...

Quoted 5 lines

/me being very grumpy @ Lai.. ia64 is broken too!

/me goes revert this shite

Now it is fixed.

http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h=9f081ce5da2c8af297a0a7d15a57fb4beeed374b;hp=43e3bf203456c4f06bdd6060426976ad2bed9081

No its not, -tip is still not buildable on s390 and ia64.

Please don't ever pull crap like this again.

#18 lore raw

PATCH 1/1 tracing: Cleanup the convoluted softirq tracepoints

In reply to Koki Sanagi

With the addition of trace_softirq_raise() the softirq tracepoint got even more convoluted. Why the tracepoints take two pointers to assign an integer is beyond my comprehension.

But adding an extra case which treats the first pointer as an unsigned long when the second pointer is NULL including the back and forth type casting is just horrible.

Convert the softirq tracepoints to take a single unsigned int argument for the softirq vector number and fix the call sites.

---
 include/linux/interrupt.h  |    2 -
 include/trace/events/irq.h |   54 ++++++++++++++++-----------------------------
 kernel/softirq.c           |   14 ++++++-----
 3 files changed, 29 insertions(+), 41 deletions(-)
include/linux/interrupt.h +1 -1
index 531495d..0ac1949 100644
@@ -410,7 +410,7 @@ extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
 static inline void __raise_softirq_irqoff(unsigned int nr)
 {
-	trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+	trace_softirq_raise(nr);
 	or_softirq_pending(1UL << nr);
 }
 
include/trace/events/irq.h +20 -34

96 lines not on this page · raw message

kernel/softirq.c +8 -6
index 07b4f1b..c0a9ea5 100644
@@ -212,18 +212,20 @@ restart:
 
 	do {
 		if (pending & 1) {
+			unsigned int vec_nr = h - softirq_vec;
 			int prev_count = preempt_count();
-			kstat_incr_softirqs_this_cpu(h - softirq_vec);
 
-			trace_softirq_entry(h, softirq_vec);
+			kstat_incr_softirqs_this_cpu(vec_nr);
+
+			trace_softirq_entry(vec_nr);
 			h->action(h);
-			trace_softirq_exit(h, softirq_vec);
+			trace_softirq_exit(vec_nr);
 			if (unlikely(prev_count != preempt_count())) {
 				printk(KERN_ERR "huh, entered softirq %td %s %p"
 				       "with preempt_count %08x,"
-				       " exited with %08x?\n", h - softirq_vec,
-				       softirq_to_name[h - softirq_vec],
-				       h->action, prev_count, preempt_count());
+				       " exited with %08x?\n", vec_nr,
+				       softirq_to_name[vec_nr], h->action,
+				       prev_count, preempt_count());
 				preempt_count() = prev_count;
 			}
 
maintainer Acked-by on v1 1/1
#19 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 5 lines · Thomas Gleixner

With the addition of trace_softirq_raise() the softirq tracepoint got even more convoluted. Why the tracepoints take two pointers to assign an integer is beyond my comprehension.

Quoted 8 lines

But adding an extra case which treats the first pointer as an unsigned long when the second pointer is NULL including the back and forth type casting is just horrible.

Convert the softirq tracepoints to take a single unsigned int argument for the softirq vector number and fix the call sites.

A much needed cleanup indeed!

reviewer Acked-by on v1 1/1
#20 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 10 lines · * Thomas Gleixner ([email protected]) wrote:

With the addition of trace_softirq_raise() the softirq tracepoint got even more convoluted. Why the tracepoints take two pointers to assign an integer is beyond my comprehension.

But adding an extra case which treats the first pointer as an unsigned long when the second pointer is NULL including the back and forth type casting is just horrible.

Convert the softirq tracepoints to take a single unsigned int argument for the softirq vector number and fix the call sites.

Well, there was originally a reason for this oddness. The in __do_softirq(), "h - softirq_ve"c computation was not needed outside of the tracepoint handler in the past, but it now seems to be required with the new inlined "kstat_incr_softirqs_this_cpu()".

So yes, thanks to this recent change, it now makes sense to pull this computation out of the tracepoints and do it unconditionally in the kernel code.

Feel free to put my:

Thanks,

Mathieu

Quoted 153 lines
---
 include/linux/interrupt.h  |    2 -
 include/trace/events/irq.h |   54 ++++++++++++++++-----------------------------
 kernel/softirq.c           |   14 ++++++-----
 3 files changed, 29 insertions(+), 41 deletions(-)
include/linux/interrupt.h +1 -1
index 531495d..0ac1949 100644
@@ -410,7 +410,7 @@ extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
 static inline void __raise_softirq_irqoff(unsigned int nr)
 {
-	trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+	trace_softirq_raise(nr);
 	or_softirq_pending(1UL << nr);
 }
 
include/trace/events/irq.h +20 -34
index 6fa7cba..1c09820 100644
@@ -86,76 +86,62 @@ TRACE_EVENT(irq_handler_exit,
 
 DECLARE_EVENT_CLASS(softirq,
 
-	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+	TP_PROTO(unsigned int vec_nr),
 
-	TP_ARGS(h, vec),
+	TP_ARGS(vec_nr),
 
 	TP_STRUCT__entry(
-		__field(	int,	vec			)
+		__field(	unsigned int,	vec	)
 	),
 
 	TP_fast_assign(
-		if (vec)
-			__entry->vec = (int)(h - vec);
-		else
-			__entry->vec = (int)(long)h;
+		__entry->vec = vec_nr;
 	),
 
-	TP_printk("vec=%d [action=%s]", __entry->vec,
+	TP_printk("vec=%u [action=%s]", __entry->vec,
 		  show_softirq_name(__entry->vec))
 );
 
 /**
  * softirq_entry - called immediately before the softirq handler
- * @h: pointer to struct softirq_action
- * @vec: pointer to first struct softirq_action in softirq_vec array
+ * @vec_nr:  softirq vector number
  *
- * The @h parameter, contains a pointer to the struct softirq_action
- * which has a pointer to the action handler that is called. By subtracting
- * the @vec pointer from the @h pointer, we can determine the softirq
- * number. Also, when used in combination with the softirq_exit tracepoint
- * we can determine the softirq latency.
+ * When used in combination with the softirq_exit tracepoint
+ * we can determine the softirq handler runtine.
  */
 DEFINE_EVENT(softirq, softirq_entry,
 
-	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+	TP_PROTO(unsigned int vec_nr),
 
-	TP_ARGS(h, vec)
+	TP_ARGS(vec_nr)
 );
 
 /**
  * softirq_exit - called immediately after the softirq handler returns
- * @h: pointer to struct softirq_action
- * @vec: pointer to first struct softirq_action in softirq_vec array
+ * @vec_nr:  softirq vector number
  *
- * The @h parameter contains a pointer to the struct softirq_action
- * that has handled the softirq. By subtracting the @vec pointer from
- * the @h pointer, we can determine the softirq number. Also, when used in
- * combination with the softirq_entry tracepoint we can determine the softirq
- * latency.
+ * When used in combination with the softirq_entry tracepoint
+ * we can determine the softirq handler runtine.
  */
 DEFINE_EVENT(softirq, softirq_exit,
 
-	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+	TP_PROTO(unsigned int vec_nr),
 
-	TP_ARGS(h, vec)
+	TP_ARGS(vec_nr)
 );
 
 /**
  * softirq_raise - called immediately when a softirq is raised
- * @h: pointer to struct softirq_action
- * @vec: pointer to first struct softirq_action in softirq_vec array
+ * @vec_nr:  softirq vector number
  *
- * The @h parameter contains a pointer to the softirq vector number which is
- * raised. @vec is NULL and it means @h includes vector number not
- * softirq_action. When used in combination with the softirq_entry tracepoint
- * we can determine the softirq raise latency.
+ * When used in combination with the softirq_entry tracepoint
+ * we can determine the softirq raise to run latency.
  */
 DEFINE_EVENT(softirq, softirq_raise,
 
-	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+	TP_PROTO(unsigned int vec_nr),
 
-	TP_ARGS(h, vec)
+	TP_ARGS(vec_nr)
 );
 
 #endif /*  _TRACE_IRQ_H */
kernel/softirq.c +8 -6
index 07b4f1b..c0a9ea5 100644
@@ -212,18 +212,20 @@ restart:
 
 	do {
 		if (pending & 1) {
+			unsigned int vec_nr = h - softirq_vec;
 			int prev_count = preempt_count();
-			kstat_incr_softirqs_this_cpu(h - softirq_vec);
 
-			trace_softirq_entry(h, softirq_vec);
+			kstat_incr_softirqs_this_cpu(vec_nr);
+
+			trace_softirq_entry(vec_nr);
 			h->action(h);
-			trace_softirq_exit(h, softirq_vec);
+			trace_softirq_exit(vec_nr);
 			if (unlikely(prev_count != preempt_count())) {
 				printk(KERN_ERR "huh, entered softirq %td %s %p"
 				       "with preempt_count %08x,"
-				       " exited with %08x?\n", h - softirq_vec,
-				       softirq_to_name[h - softirq_vec],
-				       h->action, prev_count, preempt_count());
+				       " exited with %08x?\n", vec_nr,
+				       softirq_to_name[vec_nr], h->action,
+				       prev_count, preempt_count());
 				preempt_count() = prev_count;
 			}
 
Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#21 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 9 lines · Mathieu Desnoyers
Quoted 8 lines · * Thomas Gleixner ([email protected]) wrote:

With the addition of trace_softirq_raise() the softirq tracepoint got even more convoluted. Why the tracepoints take two pointers to assign an integer is beyond my comprehension.

But adding an extra case which treats the first pointer as an unsigned long when the second pointer is NULL including the back and forth type casting is just horrible.

Quoted 7 lines
Quoted 2 lines

Convert the softirq tracepoints to take a single unsigned int argument for the softirq vector number and fix the call sites.

Well, there was originally a reason for this oddness. The in __do_softirq(), "h - softirq_ve"c computation was not needed outside of the tracepoint handler in the past, but it now seems to be required with the new inlined "kstat_incr_softirqs_this_cpu()".

Dudes, a vector computation is hardly a performance problem in that function and definitely not an excuse for designing such horrible interfaces.

Thanks,

tglx

maintainer
#22 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 5 lines · Thomas Gleixner

On Tue, 19 Oct 2010, Mathieu Desnoyers wrote:

Dudes, a vector computation is hardly a performance problem in that function and definitely not an excuse for designing such horrible interfaces.

Yes, now we can be a bit more liberal. But when these tracepoints were going in, people were watching to make sure they have practically zero impact when tracing was disabled.

Now that people are more use to tracepoints, they are more understanding to have cleaner code over that extra few more lines of machine code in the fast path.

-- Steve

#72 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 14 lines · * Thomas Gleixner ([email protected]) wrote:
Quoted 12 lines · Mathieu Desnoyers
Quoted 10 lines · * Thomas Gleixner ([email protected]) wrote:

With the addition of trace_softirq_raise() the softirq tracepoint got even more convoluted. Why the tracepoints take two pointers to assign an integer is beyond my comprehension.

But adding an extra case which treats the first pointer as an unsigned long when the second pointer is NULL including the back and forth type casting is just horrible.

Convert the softirq tracepoints to take a single unsigned int argument for the softirq vector number and fix the call sites.

Quoted 8 lines
Quoted 4 lines

Well, there was originally a reason for this oddness. The in __do_softirq(), "h - softirq_ve"c computation was not needed outside of the tracepoint handler in the past, but it now seems to be required with the new inlined "kstat_incr_softirqs_this_cpu()".

Dudes, a vector computation is hardly a performance problem in that function and definitely not an excuse for designing such horrible interfaces.

In this specific case, I think you are right. But things are not that trivial, and you know it. We have to consider:

- Extra instruction cache footprint
- Added register pressure
- Added computation overhead of the added substraction
- Frequency of code execution

for all target architectures when we add tracepoints to performance sensitive code paths. As a general policy, we try to keep these at the lowest possible level, so that all tracepoints will be compiled into distro kernels without perceivable _overall_ performance overhead. It's not something that should be looked at only on a tracepoint-by-tracepoint overhead basis, but rather by looking at the overall system degradation that adding 300 tracepoints would cause.

So I agree with you that it's a trade-off between interface cleanness and performance. When they were introduced, Tracepoint handlers were barely seen as citizen of the kernel code base, so all that mattered was to keep the "tracepoints off" case clean and fast. Now that tracepoint handlers seems to be increasingly accepted as part of the kernel code base, I agree that taking into account oddness performed in this handler becomes more important. It ends up being a question of balance between oddness inside the tracepoint handler and performance overhead in the off-case. The increased acceptance of the tracepoint code-base has shifted this balance slightly in favor of cleanness.

Thanks,

Mathieu

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#23 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 7 lines · Steven Rostedt
Quoted 5 lines · Thomas Gleixner

On Tue, 19 Oct 2010, Mathieu Desnoyers wrote:

Dudes, a vector computation is hardly a performance problem in that function and definitely not an excuse for designing such horrible interfaces.

Quoted 7 lines

Yes, now we can be a bit more liberal. But when these tracepoints were going in, people were watching to make sure they have practically zero impact when tracing was disabled.

Now that people are more use to tracepoints, they are more understanding to have cleaner code over that extra few more lines of machine code in the fast path.

The vector computation is compared to the extra tracing induced jumps probably not even measurable. Stop defending horrible coding with handwavy performance and impact arguments.

Thanks,

tglx

#24 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 17 lines · * Thomas Gleixner ([email protected]) wrote:
Quoted 7 lines · Steven Rostedt
Quoted 5 lines · Thomas Gleixner

On Tue, 19 Oct 2010, Mathieu Desnoyers wrote:

Dudes, a vector computation is hardly a performance problem in that function and definitely not an excuse for designing such horrible interfaces.

Quoted 7 lines

Yes, now we can be a bit more liberal. But when these tracepoints were going in, people were watching to make sure they have practically zero impact when tracing was disabled.

Now that people are more use to tracepoints, they are more understanding to have cleaner code over that extra few more lines of machine code in the fast path.

Quoted 5 lines

The vector computation is compared to the extra tracing induced jumps probably not even measurable. Stop defending horrible coding with handwavy performance and impact arguments.

From the moment markers and tracepoints infrastructures were merged, the

performance overhead target has been assuming we would eventually be merging "asm goto jump labels", which replace the load+test+branch with a no-op.

So compared to a 5 bytes no-op added to the fast path, this vector computation can be expected to have a higher performance impact, because skipping a no-op on modern architectures (x86 at least) adds technically zero cycles. Agreed, there is still the impact on I$, extra register pressure, some leaf functions becoming non-leaf, and added function call (which imply external side-effect, thus acting like a barrier()). But saying that all we do is to provide handwavy performance and impact arguments is a bit much.

Until the asm goto are more widely deployed and until gcc 4.5 is more widely used, there are some instrumentation sites I am relunctant to consider to instrument with tracepoints (e.g. all system call entry/exit sites). However, we should not use the cost of the current load+test+branch tracepoint behavior as an excuse for adding extra performance impact to kernel code, because when it will be replaced by asm gotos, all that will be left is the performance impact inappropriately justified as insignificant compared to the impact of the old tracepoint scheme.

Thanks,

Mathieu

Quoted 4 lines

Thanks,

tglx

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
maintainer
#71 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 3 lines · Thomas Gleixner

The vector computation is compared to the extra tracing induced jumps probably not even measurable. Stop defending horrible coding with handwavy performance and impact arguments.

Yes this was crappy code, I'm not defending it. But this code was from the original tracepoints. I just looked at when this code was added, and it was still in the time TRACE_EVENT() was in a major flux. Heck, the code resided in include/trace/irq.h and not include/trace/events/irq.h. And yes, a lot of decisions back then were put on handwaving performance and impact, and it was not just coming from us.

I admit I should have cleaned it up, but I did not want to touch it until it actually broke ;-)

-- Steve

#25 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Mathieu Desnoyers
Quoted 6 lines · Mathieu Desnoyers
Quoted 1 line · * Thomas Gleixner ([email protected]) wrote:

On Tue, 19 Oct 2010, Steven Rostedt wrote:

as an excuse for adding extra performance impact to kernel code, because when it will be replaced by asm gotos, all that will be left is the performance impact inappropriately justified as insignificant compared to the impact of the old tracepoint scheme.

Can you at one point just stop your tracing lectures and look at the facts ?

The impact of a sensible tracepoint design on the code in question before kstat_incr_softirqs_this_cpu() was added would have been a mere _FIVE_ bytes of text. But the original tracepoint code itself is _TWENTY_ bytes of text larger.

So we trade horrible code plus 20 bytes text against 5 bytes of text in the hotpath. And you tell me that these _FIVE_ bytes are impacting performance so much that it's significant.

Now with kstat_incr_softirqs_this_cpu() the impact is zero, it even removes code.

And talking about non impact of disabled trace points. The tracepoint in question which made me look at the code results in deinlining __raise_softirq_irqsoff() in net/dev/core.c. There goes your theory.

So no, you _cannot_ tell what impact a tracepoint has in reality except by looking at the assembly output.

And what scares me way more is the size of a single tracepoint in a code file.

Just adding "trace_softirq_entry(nr);" adds 88 bytes of text. So that's optimized tracing code ?

All it's supposed to do is:

    if (enabled)
	trace_foo(nr);

Replace "if (enabled)" with your favourite code patching jump label whatever magic. The above stupid version takes about 28, but the "optimized" tracing code makes that 88. Brilliant. That's inlining utter shite for no good reason. WTF is it necessary to inline all that gunk ?

Please spare me the "jump label will make this less intrusive" lecture. I'm not interested at all.

Let's instead look at some more facts:

#include <linux/interrupt.h>
#include <linux/module.h>

#include <trace/events/irq.h>

static struct softirq_action softirq_vec[NR_SOFTIRQS];

void test(struct softirq_action *h)

{
	trace_softirq_entry(h - softirq_vec);

	h->action(h);
}

Compile this code with GCC 4.5 with and without jump labels (zap the select HAVE_ARCH_JUMP_LABEL line in arch/x86/Kconfig)

So now the !jumplabel case gives us:

../build/kernel/soft.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <test>:

   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	41 55                	push   %r13
   6:	49 89 fd             	mov    %rdi,%r13
   9:	49 81 ed 00 00 00 00 	sub    $0x0,%r13
  10:	41 54                	push   %r12
  12:	49 c1 ed 03          	shr    $0x3,%r13
  16:	49 89 fc             	mov    %rdi,%r12
  19:	53                   	push   %rbx
  1a:	48 83 ec 08          	sub    $0x8,%rsp
  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
  25:	74 4d                	je     74 <test+0x74>
  27:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  2e:	00 00 
  30:	ff 80 44 e0 ff ff    	incl   -0x1fbc(%rax)
  36:	48 8b 1d 00 00 00 00 	mov    0x0(%rip),%rbx        # 3d <test+0x3d>
  3d:	48 85 db             	test   %rbx,%rbx
  40:	74 13                	je     55 <test+0x55>
  42:	48 8b 7b 08          	mov    0x8(%rbx),%rdi
  46:	44 89 ee             	mov    %r13d,%esi
  49:	ff 13                	callq  *(%rbx)
  4b:	48 83 c3 10          	add    $0x10,%rbx
  4f:	48 83 3b 00          	cmpq   $0x0,(%rbx)
  53:	eb eb                	jmp    40 <test+0x40>
  55:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  5c:	00 00 
  5e:	ff 88 44 e0 ff ff    	decl   -0x1fbc(%rax)
  64:	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
  6b:	a8 08                	test   $0x8,%al
  6d:	74 05                	je     74 <test+0x74>
  6f:	e8 00 00 00 00       	callq  74 <test+0x74>
  74:	4c 89 e7             	mov    %r12,%rdi
  77:	41 ff 14 24          	callq  *(%r12)
  7b:	58                   	pop    %rax
  7c:	5b                   	pop    %rbx
  7d:	41 5c                	pop    %r12
  7f:	41 5d                	pop    %r13

81: c9 leaveq
82: c3 retq

The jumplabel=y case gives:

../build/kernel/soft.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <test>:

   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	41 55                	push   %r13
   6:	49 89 fd             	mov    %rdi,%r13
   9:	49 81 ed 00 00 00 00 	sub    $0x0,%r13
  10:	41 54                	push   %r12
  12:	49 c1 ed 03          	shr    $0x3,%r13
  16:	49 89 fc             	mov    %rdi,%r12
  19:	53                   	push   %rbx
  1a:	48 83 ec 08          	sub    $0x8,%rsp
  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
  23:	eb 4d                	jmp    72 <test+0x72>
  25:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  2c:	00 00 
  2e:	ff 80 44 e0 ff ff    	incl   -0x1fbc(%rax)
  34:	48 8b 1d 00 00 00 00 	mov    0x0(%rip),%rbx        # 3b <test+0x3b>
  3b:	48 85 db             	test   %rbx,%rbx
  3e:	74 13                	je     53 <test+0x53>
  40:	48 8b 7b 08          	mov    0x8(%rbx),%rdi
  44:	44 89 ee             	mov    %r13d,%esi
  47:	ff 13                	callq  *(%rbx)
  49:	48 83 c3 10          	add    $0x10,%rbx
  4d:	48 83 3b 00          	cmpq   $0x0,(%rbx)
  51:	eb eb                	jmp    3e <test+0x3e>
  53:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  5a:	00 00 
  5c:	ff 88 44 e0 ff ff    	decl   -0x1fbc(%rax)
  62:	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
  69:	a8 08                	test   $0x8,%al
  6b:	74 05                	je     72 <test+0x72>
  6d:	e8 00 00 00 00       	callq  72 <test+0x72>
  72:	4c 89 e7             	mov    %r12,%rdi
  75:	41 ff 14 24          	callq  *(%r12)
  79:	58                   	pop    %rax
  7a:	5b                   	pop    %rbx
  7b:	41 5c                	pop    %r12
  7d:	41 5d                	pop    %r13

7f: c9 leaveq
80: c3 retq

So that saves _TWO_ bytes of text and replaces:

-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:	74 4d                	je     74 <test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
+  23:	eb 4d                	jmp    72 <test+0x72>

So it trades a conditional vs. two jumps ? WTF ??

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

Did you guys ever look at the assembly output of that insane shite you are advertising with lengthy explanations ?

Obviously _NOT_

Come back when you can show me a clean imlementation of all this crap which reproduces with my jumplabel enabled stock compiler. And please just send me a patch w/o the blurb.

And sane looks like:

jmpq 2f <---- This gets noped out
1:

    mov    %r12,%rdi
    callq  *(%r12)
    [whatever cleanup it takes ]
    leaveq 
    retq   

2f:
[tracing gunk]
jmp 1b

And further I want to see the tracing gunk in a minimal size so the net/core/dev.c deinlining does not happen.

Thanks,

tglx

P.S.: It might be helpful and polite if you'd take off your tracing
blinkers from time to time.

maintainer
#26 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 1 line · Thomas Gleixner

Let's instead look at some more facts:

Sure, this is where it gets fun :-)

Quoted 6 lines

#include <linux/interrupt.h>
#include <linux/module.h>

#include <trace/events/irq.h>

Quoted 8 lines

static struct softirq_action softirq_vec[NR_SOFTIRQS];

void test(struct softirq_action *h)

{
	trace_softirq_entry(h - softirq_vec);

	h->action(h);
}

Since I don't have your patch yet, I used the original:

void test(struct softirq_action *h)

{
        trace_softirq_entry(h, softirq_vec);
        h->action(h);
}
Quoted 104 lines

Compile this code with GCC 4.5 with and without jump labels (zap the select HAVE_ARCH_JUMP_LABEL line in arch/x86/Kconfig)

So now the !jumplabel case gives us:

../build/kernel/soft.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <test>:

   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	41 55                	push   %r13
   6:	49 89 fd             	mov    %rdi,%r13
   9:	49 81 ed 00 00 00 00 	sub    $0x0,%r13
  10:	41 54                	push   %r12
  12:	49 c1 ed 03          	shr    $0x3,%r13
  16:	49 89 fc             	mov    %rdi,%r12
  19:	53                   	push   %rbx
  1a:	48 83 ec 08          	sub    $0x8,%rsp
  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
  25:	74 4d                	je     74 <test+0x74>
  27:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  2e:	00 00 
  30:	ff 80 44 e0 ff ff    	incl   -0x1fbc(%rax)
  36:	48 8b 1d 00 00 00 00 	mov    0x0(%rip),%rbx        # 3d <test+0x3d>
  3d:	48 85 db             	test   %rbx,%rbx
  40:	74 13                	je     55 <test+0x55>
  42:	48 8b 7b 08          	mov    0x8(%rbx),%rdi
  46:	44 89 ee             	mov    %r13d,%esi
  49:	ff 13                	callq  *(%rbx)
  4b:	48 83 c3 10          	add    $0x10,%rbx
  4f:	48 83 3b 00          	cmpq   $0x0,(%rbx)
  53:	eb eb                	jmp    40 <test+0x40>
  55:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  5c:	00 00 
  5e:	ff 88 44 e0 ff ff    	decl   -0x1fbc(%rax)
  64:	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
  6b:	a8 08                	test   $0x8,%al
  6d:	74 05                	je     74 <test+0x74>
  6f:	e8 00 00 00 00       	callq  74 <test+0x74>
  74:	4c 89 e7             	mov    %r12,%rdi
  77:	41 ff 14 24          	callq  *(%r12)
  7b:	58                   	pop    %rax
  7c:	5b                   	pop    %rbx
  7d:	41 5c                	pop    %r12
  7f:	41 5d                	pop    %r13

81: c9 leaveq
82: c3 retq

The jumplabel=y case gives:

../build/kernel/soft.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <test>:

   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	41 55                	push   %r13
   6:	49 89 fd             	mov    %rdi,%r13
   9:	49 81 ed 00 00 00 00 	sub    $0x0,%r13
  10:	41 54                	push   %r12
  12:	49 c1 ed 03          	shr    $0x3,%r13
  16:	49 89 fc             	mov    %rdi,%r12
  19:	53                   	push   %rbx
  1a:	48 83 ec 08          	sub    $0x8,%rsp
  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
  23:	eb 4d                	jmp    72 <test+0x72>
  25:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  2c:	00 00 
  2e:	ff 80 44 e0 ff ff    	incl   -0x1fbc(%rax)
  34:	48 8b 1d 00 00 00 00 	mov    0x0(%rip),%rbx        # 3b <test+0x3b>
  3b:	48 85 db             	test   %rbx,%rbx
  3e:	74 13                	je     53 <test+0x53>
  40:	48 8b 7b 08          	mov    0x8(%rbx),%rdi
  44:	44 89 ee             	mov    %r13d,%esi
  47:	ff 13                	callq  *(%rbx)
  49:	48 83 c3 10          	add    $0x10,%rbx
  4d:	48 83 3b 00          	cmpq   $0x0,(%rbx)
  51:	eb eb                	jmp    3e <test+0x3e>
  53:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  5a:	00 00 
  5c:	ff 88 44 e0 ff ff    	decl   -0x1fbc(%rax)
  62:	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
  69:	a8 08                	test   $0x8,%al
  6b:	74 05                	je     72 <test+0x72>
  6d:	e8 00 00 00 00       	callq  72 <test+0x72>
  72:	4c 89 e7             	mov    %r12,%rdi
  75:	41 ff 14 24          	callq  *(%r12)
  79:	58                   	pop    %rax
  7a:	5b                   	pop    %rbx
  7b:	41 5c                	pop    %r12
  7d:	41 5d                	pop    %r13

7f: c9 leaveq
80: c3 retq

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:	74 4d                	je     74 <test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
+  23:	eb 4d                	jmp    72 <test+0x72>
Quoted 1 line

So it trades a conditional vs. two jumps ? WTF ??

Well, the one jmpq is noped out, and the jmp is non conditional. I've always thought a non conditional jmp was faster than a conditional one, since there's no need to go into the branch prediction logic. The CPU can simply skip to the code to jump next. Of counse, this pollutes the I$.

Quoted 3 lines

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

Because you do the h - softvec in the tracepoint parameter? I got a different result:

Here's the diff. I did a cut -c10- to get rid of the line numbers so I have a better diff. There's still differences due to jump locations, but those are easy to figure out:

I diffed nojump vs jump. The '-' is with nojump, the '+' is with jumps.

tmp/s1 renamed from tmp/s2 +4 -7
@@ -1,38 +1,33 @@
-00026f0 <test>:
+00027a0 <test>:
 	55                   	push   %rbp
 	48 89 e5             	mov    %rsp,%rbp
-	48 83 ec 10          	sub    $0x10,%rsp
-	48 89 1c 24          	mov    %rbx,(%rsp)
-	4c 89 64 24 08       	mov    %r12,0x8(%rsp)
-	e8 00 00 00 00       	callq  2706 <test+0x16>
+	41 54                	push   %r12
+	53                   	push   %rbx
+	e8 00 00 00 00       	callq  27ac <test+0xc>
 R_X86_64_PC32	mcount-0x4
-	8b 15 00 00 00 00    	mov    0x0(%rip),%edx        # 270c <test+0x1c>
-R_X86_64_PC32	__tracepoint_softirq_entry+0x4
 	48 89 fb             	mov    %rdi,%rbx
 

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

-	85 d2                	test   %edx,%edx
-	75 10                	jne    2723 <test+0x33>
+	e9 00 00 00 00       	jmpq   27b4 <test+0x14>

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

There's the difference with this code. We replaced a test and jump conditional with a single jump that will later be nop'd out.

 	48 89 df             	mov    %rbx,%rdi
 	ff 13                	callq  *(%rbx)
-	48 8b 1c 24          	mov    (%rsp),%rbx
-	4c 8b 64 24 08       	mov    0x8(%rsp),%r12
+	5b                   	pop    %rbx
+	41 5c                	pop    %r12
 	c9                   	leaveq 
 	c3                   	retq

^^^^^^^^^^^^^^^^^^^
end of the fast path, below is the code that does the tracepoint.

+ 66 90 xchg %ax,%ax
65 48 8b 04 25 00 00 mov %gs:0x0,%rax
00 00
R_X86_64_32S kernel_stack

 	83 80 44 e0 ff ff 01 	addl   $0x1,-0x1fbc(%rax)
-	e8 00 00 00 00       	callq  2738 <test+0x48>
+	e8 00 00 00 00       	callq  27d5 <test+0x35>
 R_X86_64_PC32	debug_lockdep_rcu_enabled-0x4
 	85 c0                	test   %eax,%eax
-	74 09                	je     2745 <test+0x55>
-	80 3d 00 00 00 00 00 	cmpb   $0x0,0x0(%rip)        # 2743 <test+0x53>
-R_X86_64_PC32	.bss-0x1
-	74 53                	je     2798 <test+0xa8>
-	4c 8b 25 00 00 00 00 	mov    0x0(%rip),%r12        # 274c <test+0x5c>
+	75 57                	jne    2830 <test+0x90>
+	4c 8b 25 00 00 00 00 	mov    0x0(%rip),%r12        # 27e0 <test+0x40>
 R_X86_64_PC32	__tracepoint_softirq_entry+0x1c
 	4d 85 e4             	test   %r12,%r12
-	74 22                	je     2773 <test+0x83>
+	74 29                	je     280e <test+0x6e>
 	49 8b 04 24          	mov    (%r12),%rax
+	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)
 	49 8b 7c 24 08       	mov    0x8(%r12),%rdi
 	49 83 c4 10          	add    $0x10,%r12
 	48 c7 c2 00 00 00 00 	mov    $0x0,%rdx
@@ -41,49 +36,52 @@
 	ff d0                	callq  *%rax
 	49 8b 04 24          	mov    (%r12),%rax
 	48 85 c0             	test   %rax,%rax
-	75 e2                	jne    2755 <test+0x65>
+	75 e2                	jne    27f0 <test+0x50>
 	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
 	00 00 
 R_X86_64_32S	kernel_stack
 	83 a8 44 e0 ff ff 01 	subl   $0x1,-0x1fbc(%rax)
 	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
 	a8 08                	test   $0x8,%al
-	74 85                	je     2713 <test+0x23>
-	e8 00 00 00 00       	callq  2793 <test+0xa3>
+	74 8b                	je     27b4 <test+0x14>
+	e8 00 00 00 00       	callq  282e <test+0x8e>

R_X86_64_PC32 preempt_schedule-0x4
- e9 7b ff ff ff jmpq 2713 <test+0x23>
- 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
- 00

-	e8 00 00 00 00       	callq  27a5 <test+0xb5>
+	eb 84                	jmp    27b4 <test+0x14>
+	80 3d 00 00 00 00 00 	cmpb   $0x0,0x0(%rip)        # 2837 <test+0x97>
+R_X86_64_PC32	.bss-0x1
+	75 a0                	jne    27d9 <test+0x39>
+	e8 00 00 00 00       	callq  283e <test+0x9e>
 R_X86_64_PC32	debug_lockdep_rcu_enabled-0x4
 	85 c0                	test   %eax,%eax
-	74 9c                	je     2745 <test+0x55>
-	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 27b0 <test+0xc0>
-R_X86_64_PC32	debug_locks-0x5
-	75 3f                	jne    27f1 <test+0x101>
+	74 97                	je     27d9 <test+0x39>
+	8b 35 00 00 00 00    	mov    0x0(%rip),%esi        # 2848 <test+0xa8>
+R_X86_64_PC32	debug_locks-0x4
+	85 f6                	test   %esi,%esi
+	75 44                	jne    2890 <test+0xf0>
 	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
 	00 00 
 R_X86_64_32S	kernel_stack
-	83 b8 44 e0 ff ff 00 	cmpl   $0x0,-0x1fbc(%rax)
-	75 81                	jne    2745 <test+0x55>
+	8b 88 44 e0 ff ff    	mov    -0x1fbc(%rax),%ecx
+	85 c9                	test   %ecx,%ecx
+	0f 85 76 ff ff ff    	jne    27d9 <test+0x39>
 	ff 14 25 00 00 00 00 	callq  *0x0
 R_X86_64_32S	pv_irq_ops
 	f6 c4 02             	test   $0x2,%ah
-	0f 84 71 ff ff ff    	je     2745 <test+0x55>
+	0f 84 66 ff ff ff    	je     27d9 <test+0x39>
 	be 7c 00 00 00       	mov    $0x7c,%esi
 	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
 R_X86_64_32S	.rodata.str1.1
-	c6 05 00 00 00 00 01 	movb   $0x1,0x0(%rip)        # 27e7 <test+0xf7>
+	c6 05 00 00 00 00 01 	movb   $0x1,0x0(%rip)        # 2886 <test+0xe6>
 R_X86_64_PC32	.bss-0x1
-	e8 00 00 00 00       	callq  27ec <test+0xfc>
+	e8 00 00 00 00       	callq  288b <test+0xeb>
 R_X86_64_PC32	lockdep_rcu_dereference-0x4
-	e9 54 ff ff ff       	jmpq   2745 <test+0x55>
+	e9 49 ff ff ff       	jmpq   27d9 <test+0x39>
 	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
 R_X86_64_32S	rcu_sched_lock_map
-	e8 00 00 00 00       	callq  27fd <test+0x10d>
+	e8 00 00 00 00       	callq  289c <test+0xfc>
 R_X86_64_PC32	lock_is_held-0x4
 	85 c0                	test   %eax,%eax
-	0f 85 40 ff ff ff    	jne    2745 <test+0x55>
-	eb ab                	jmp    27b2 <test+0xc2>
-	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
-	00 00 
+	0f 85 35 ff ff ff    	jne    27d9 <test+0x39>
+	eb a6                	jmp    284c <test+0xac>
+	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)

+ 00 00 00

Quoted 8 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

Did you guys ever look at the assembly output of that insane shite you are advertising with lengthy explanations ?

Obviously _NOT_

Perhaps so, but as Peter Zijlsta has said, compiling with gcc is a random number generator. Your mileage may vary.

Quoted 15 lines

Come back when you can show me a clean imlementation of all this crap which reproduces with my jumplabel enabled stock compiler. And please just send me a patch w/o the blurb.

And sane looks like:

jmpq 2f <---- This gets noped out
1:

    mov    %r12,%rdi
    callq  *(%r12)
    [whatever cleanup it takes ]
    leaveq 
    retq   
Quoted 3 lines

2f:
[tracing gunk]
jmp 1b

The above looks like what I have.

-- Steve

Quoted 10 lines

And further I want to see the tracing gunk in a minimal size so the net/core/dev.c deinlining does not happen.

Thanks,

tglx

P.S.: It might be helpful and polite if you'd take off your tracing
blinkers from time to time.

#27 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 11 lines · Steven Rostedt
Quoted 8 lines · Thomas Gleixner

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:	74 4d                	je     74 <test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
+  23:	eb 4d                	jmp    72 <test+0x72>

So it trades a conditional vs. two jumps ? WTF ??

Well, the one jmpq is noped out, and the jmp is non conditional. I've

What are you smoking ?

In case the trace point is enabled the jmpq is there, so it jumps to 23 and jumps from there to 72.

In case the trace point is disabled the jmpq is noped out, so it jumps to 72 directly.

Quoted 1 line

always thought a non conditional jmp was faster than a conditional one,

I always thought, that at least some of the stuff which comes from tracing folks makes some sense.

Quoted 3 lines

since there's no need to go into the branch prediction logic. The CPU can simply skip to the code to jump next. Of counse, this pollutes the I$.

We might consult Mathieu for further useless blurb on how CPUs work around broken code.

Thanks,

tglx

#57 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner

On 10/19/2010 12:49 PM, Thomas Gleixner wrote:
[...]

Quoted 11 lines

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25<test+0x25>
-  25:	74 4d                	je     74<test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23<test+0x23>
+  23:	eb 4d                	jmp    72<test+0x72>

So it trades a conditional vs. two jumps ? WTF ??

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

The 'asm goto' construct in GCC-4.5 is deficient in this area.

GCC assumes that all exit paths from an 'asm goto' are equally likely, so the tracing (or dynamic printk etc.) code is assumed to be hot and is emitted inline. Since they are inline like this, there are all these jumps around them and they pollute the I-Cache.

I was looking at fixing it, but I think a true general purpose fix would require enhancing GCC's grammar to allow specifying of the 'likelyness' of each exit path from 'asm goto'.

David Daney

Quoted 42 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

Did you guys ever look at the assembly output of that insane shite you are advertising with lengthy explanations ?

Obviously _NOT_

Come back when you can show me a clean imlementation of all this crap which reproduces with my jumplabel enabled stock compiler. And please just send me a patch w/o the blurb.

And sane looks like:

jmpq 2f<---- This gets noped out
1:

     mov    %r12,%rdi
     callq  *(%r12)
     [whatever cleanup it takes ]
     leaveq
     retq

2f:
[tracing gunk]
jmp 1b

And further I want to see the tracing gunk in a minimal size so the net/core/dev.c deinlining does not happen.

Thanks,

tglx

P.S.: It might be helpful and polite if you'd take off your tracing
blinkers from time to time.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

maintainer
#28 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 9 lines · Thomas Gleixner
Quoted 8 lines · Steven Rostedt
Quoted 7 lines · Thomas Gleixner

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:	74 4d                	je     74 <test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
+  23:	eb 4d                	jmp    72 <test+0x72>
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

So it trades a conditional vs. two jumps ? WTF ??

Well, the one jmpq is noped out, and the jmp is non conditional. I've

What are you smoking ?

What? Are you saying that conditional jumps are just as fast as non conditional ones?

Quoted 3 lines

In case the trace point is enabled the jmpq is there, so it jumps to 23 and jumps from there to 72.

No, when we dynamically enable the tracepoint, it will jump to 25, not
23. That's what the goto part is about. We add the do_trace label to the table, and we make it point to that location. If we did it as you say, then tracepoints would never be enabled.

This is not unlike what we do with the function tracer. The original code points to mcount which simply is:

mcount:
retq

And when we enable the callers, we have it jump to a different function.

Quoted 3 lines

In case the trace point is disabled the jmpq is noped out, so it jumps to 72 directly.

That is correct.

Quoted 5 lines
Quoted 2 lines

always thought a non conditional jmp was faster than a conditional one,

I always thought, that at least some of the stuff which comes from tracing folks makes some sense.

Is it still not making sense?

Quoted 7 lines
Quoted 4 lines

since there's no need to go into the branch prediction logic. The CPU can simply skip to the code to jump next. Of counse, this pollutes the I$.

We might consult Mathieu for further useless blurb on how CPUs work around broken code.

The code worked fine before, it just was not very pretty.

But it seemed that gcc for you inlined the code in the wrong spot. Perhaps it's not a good idea to have the something like h - softirq_vec in the parameter of the tracepoint. Not saying that your change is not worth it. It is, because h - softirq_vec is used by others now too.

-- Steve

#61 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 168 lines · Thomas Gleixner
Quoted 5 lines
Quoted 1 line · Steven Rostedt

as an excuse for adding extra performance impact to kernel code, because when it will be replaced by asm gotos, all that will be left is the performance impact inappropriately justified as insignificant compared to the impact of the old tracepoint scheme.

Can you at one point just stop your tracing lectures and look at the facts ?

The impact of a sensible tracepoint design on the code in question before kstat_incr_softirqs_this_cpu() was added would have been a mere _FIVE_ bytes of text. But the original tracepoint code itself is _TWENTY_ bytes of text larger.

So we trade horrible code plus 20 bytes text against 5 bytes of text in the hotpath. And you tell me that these _FIVE_ bytes are impacting performance so much that it's significant.

Now with kstat_incr_softirqs_this_cpu() the impact is zero, it even removes code.

And talking about non impact of disabled trace points. The tracepoint in question which made me look at the code results in deinlining __raise_softirq_irqsoff() in net/dev/core.c. There goes your theory.

So no, you _cannot_ tell what impact a tracepoint has in reality except by looking at the assembly output.

And what scares me way more is the size of a single tracepoint in a code file.

Just adding "trace_softirq_entry(nr);" adds 88 bytes of text. So that's optimized tracing code ?

All it's supposed to do is:

    if (enabled)
	trace_foo(nr);

Replace "if (enabled)" with your favourite code patching jump label whatever magic. The above stupid version takes about 28, but the "optimized" tracing code makes that 88. Brilliant. That's inlining utter shite for no good reason. WTF is it necessary to inline all that gunk ?

Please spare me the "jump label will make this less intrusive" lecture. I'm not interested at all.

Let's instead look at some more facts:

#include <linux/interrupt.h>
#include <linux/module.h>

#include <trace/events/irq.h>

static struct softirq_action softirq_vec[NR_SOFTIRQS];

void test(struct softirq_action *h)

{
	trace_softirq_entry(h - softirq_vec);

	h->action(h);
}

Compile this code with GCC 4.5 with and without jump labels (zap the select HAVE_ARCH_JUMP_LABEL line in arch/x86/Kconfig)

So now the !jumplabel case gives us:

../build/kernel/soft.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <test>:

   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	41 55                	push   %r13
   6:	49 89 fd             	mov    %rdi,%r13
   9:	49 81 ed 00 00 00 00 	sub    $0x0,%r13
  10:	41 54                	push   %r12
  12:	49 c1 ed 03          	shr    $0x3,%r13
  16:	49 89 fc             	mov    %rdi,%r12
  19:	53                   	push   %rbx
  1a:	48 83 ec 08          	sub    $0x8,%rsp
  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
  25:	74 4d                	je     74 <test+0x74>
  27:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  2e:	00 00 
  30:	ff 80 44 e0 ff ff    	incl   -0x1fbc(%rax)
  36:	48 8b 1d 00 00 00 00 	mov    0x0(%rip),%rbx        # 3d <test+0x3d>
  3d:	48 85 db             	test   %rbx,%rbx
  40:	74 13                	je     55 <test+0x55>
  42:	48 8b 7b 08          	mov    0x8(%rbx),%rdi
  46:	44 89 ee             	mov    %r13d,%esi
  49:	ff 13                	callq  *(%rbx)
  4b:	48 83 c3 10          	add    $0x10,%rbx
  4f:	48 83 3b 00          	cmpq   $0x0,(%rbx)
  53:	eb eb                	jmp    40 <test+0x40>
  55:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  5c:	00 00 
  5e:	ff 88 44 e0 ff ff    	decl   -0x1fbc(%rax)
  64:	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
  6b:	a8 08                	test   $0x8,%al
  6d:	74 05                	je     74 <test+0x74>
  6f:	e8 00 00 00 00       	callq  74 <test+0x74>
  74:	4c 89 e7             	mov    %r12,%rdi
  77:	41 ff 14 24          	callq  *(%r12)
  7b:	58                   	pop    %rax
  7c:	5b                   	pop    %rbx
  7d:	41 5c                	pop    %r12
  7f:	41 5d                	pop    %r13

81: c9 leaveq
82: c3 retq

The jumplabel=y case gives:

../build/kernel/soft.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <test>:

   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	41 55                	push   %r13
   6:	49 89 fd             	mov    %rdi,%r13
   9:	49 81 ed 00 00 00 00 	sub    $0x0,%r13
  10:	41 54                	push   %r12
  12:	49 c1 ed 03          	shr    $0x3,%r13
  16:	49 89 fc             	mov    %rdi,%r12
  19:	53                   	push   %rbx
  1a:	48 83 ec 08          	sub    $0x8,%rsp
  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
  23:	eb 4d                	jmp    72 <test+0x72>
  25:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  2c:	00 00 
  2e:	ff 80 44 e0 ff ff    	incl   -0x1fbc(%rax)
  34:	48 8b 1d 00 00 00 00 	mov    0x0(%rip),%rbx        # 3b <test+0x3b>
  3b:	48 85 db             	test   %rbx,%rbx
  3e:	74 13                	je     53 <test+0x53>
  40:	48 8b 7b 08          	mov    0x8(%rbx),%rdi
  44:	44 89 ee             	mov    %r13d,%esi
  47:	ff 13                	callq  *(%rbx)
  49:	48 83 c3 10          	add    $0x10,%rbx
  4d:	48 83 3b 00          	cmpq   $0x0,(%rbx)
  51:	eb eb                	jmp    3e <test+0x3e>
  53:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
  5a:	00 00 
  5c:	ff 88 44 e0 ff ff    	decl   -0x1fbc(%rax)
  62:	48 8b 80 38 e0 ff ff 	mov    -0x1fc8(%rax),%rax
  69:	a8 08                	test   $0x8,%al
  6b:	74 05                	je     72 <test+0x72>
  6d:	e8 00 00 00 00       	callq  72 <test+0x72>
  72:	4c 89 e7             	mov    %r12,%rdi
  75:	41 ff 14 24          	callq  *(%r12)
  79:	58                   	pop    %rax
  7a:	5b                   	pop    %rbx
  7b:	41 5c                	pop    %r12
  7d:	41 5d                	pop    %r13

7f: c9 leaveq
80: c3 retq

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:	74 4d                	je     74 <test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
+  23:	eb 4d                	jmp    72 <test+0x72>
Quoted 2 lines

So it trades a conditional vs. two jumps ? WTF ??

right, so the 'jmpq' on boot on x86 gets patched with 5 byte no-op sequence. So in the disabled case we have no-op followed by a jump around the disabled code.

Quoted 3 lines

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

yes, that is the plan. gcc does not yet support hot/cold labels...once it does the second jump will go away and the entire tracepoint code will be moved to a 'cold' section. It's not quite completely optimal yet, but we are getting there.

Quoted 3 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

The 'jmpq' in the enabled case is patched with a jmpq to the body of the tracepoint itself.

Quoted 19 lines

Did you guys ever look at the assembly output of that insane shite you are advertising with lengthy explanations ?

Obviously _NOT_

Come back when you can show me a clean imlementation of all this crap which reproduces with my jumplabel enabled stock compiler. And please just send me a patch w/o the blurb.

And sane looks like:

jmpq 2f <---- This gets noped out
1:

    mov    %r12,%rdi
    callq  *(%r12)
    [whatever cleanup it takes ]
    leaveq 
    retq   
Quoted 4 lines

2f:
[tracing gunk]
jmp 1b

yes, this is what the code should look like when we get support for hot/cold labels. I've discussed this support with gcc folk, and its the next step here. So yes, this is exacatly where we are headed.

thanks,

-Jason

#58 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to David Daney
Quoted 21 lines · David Daney

On 10/19/2010 12:49 PM, Thomas Gleixner wrote:
[...]

Quoted 11 lines

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25<test+0x25>
-  25:	74 4d                	je     74<test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23<test+0x23>
+  23:	eb 4d                	jmp    72<test+0x72>

So it trades a conditional vs. two jumps ? WTF ??

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

The 'asm goto' construct in GCC-4.5 is deficient in this area.

GCC assumes that all exit paths from an 'asm goto' are equally likely, so the tracing (or dynamic printk etc.) code is assumed to be hot and is emitted inline. Since they are inline like this, there are all these jumps around them and they pollute the I-Cache.

Quoted 6 lines

I was looking at fixing it, but I think a true general purpose fix would require enhancing GCC's grammar to allow specifying of the 'likelyness' of each exit path from 'asm goto'.

David Daney

right, the next step is adding support for hot/cold labels, so the tracing code will be annotaed with a 'cold' label. Thus, not adding the 'jmp' above on line '23', and in fact moving the tracing code out-of-line. Maybe I haven't been clear on this.

thanks,

-Jason

#59 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 26 lines · Jason Baron
Quoted 25 lines · David Daney

On 10/19/2010 12:49 PM, Thomas Gleixner wrote:
[...]

Quoted 11 lines

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25<test+0x25>
-  25:	74 4d                	je     74<test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23<test+0x23>
+  23:	eb 4d                	jmp    72<test+0x72>

So it trades a conditional vs. two jumps ? WTF ??

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

The 'asm goto' construct in GCC-4.5 is deficient in this area.

GCC assumes that all exit paths from an 'asm goto' are equally likely, so the tracing (or dynamic printk etc.) code is assumed to be hot and is emitted inline. Since they are inline like this, there are all these jumps around them and they pollute the I-Cache.

I was looking at fixing it, but I think a true general purpose fix would require enhancing GCC's grammar to allow specifying of the 'likelyness' of each exit path from 'asm goto'.

Quoted 8 lines
Quoted 2 lines

David Daney

right, the next step is adding support for hot/cold labels, so the tracing code will be annotaed with a 'cold' label. Thus, not adding the 'jmp' above on line '23', and in fact moving the tracing code out-of-line. Maybe I haven't been clear on this.

Ok, so is anybody working on doing that? GCC-4.6 stage 1 (the time when a change like this could be merged) closes in 8 days.

It is unfortunate that we have this shiny new feature that can't really be used because the infrastructure is only half baked.

David Daney

#55 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 4 lines · Steven Rostedt

On Tue, 2010-10-19 at 21:49 +0200, Thomas Gleixner wrote:

Because you do the h - softvec in the tracepoint parameter? I got a different result:

I guess some serious whacking is due.

The compiler adds two jumps when the parameter changes due to
(h -softvec) instead of (h, softvec) ????

Dude, you can't be serious.

If you would have asked about the compiler version I'm using and told me about the compiler version you are using, then I could take that answer somehow serious.

It still would miss the "Uhhhh, your compiler creates crap code" alert, because that double jump is seriously broken and braindead.

And I tell you more about this. You are going to piss off a lot of users of distro compilers because they will set CC_HAVE_ASM_GOTO happily and create the code I posted. Which will break the tracer no matter what.

So you tracer maniacs happily played with some experimental compiler stuff w/o even testing your crap against something which ships with distros or is the reference 4.5 compiler on kernel.org ?

I prefer you sending a patch to disable this, until it's sorted out, unless you want me to add some really outrageous changelog to the patch I'm going to put into tip tomorrow night, ok ?

Thanks,

tglx

maintainer
#60 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to David Daney
Quoted 14 lines · David Daney

On 10/19/2010 12:49 PM, Thomas Gleixner wrote:
[...]

Quoted 11 lines

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25<test+0x25>
-  25:	74 4d                	je     74<test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23<test+0x23>
+  23:	eb 4d                	jmp    72<test+0x72>

So it trades a conditional vs. two jumps ? WTF ??

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

Quoted 7 lines

The 'asm goto' construct in GCC-4.5 is deficient in this area.

GCC assumes that all exit paths from an 'asm goto' are equally likely, so the tracing (or dynamic printk etc.) code is assumed to be hot and is emitted inline. Since they are inline like this, there are all these jumps around them and they pollute the I-Cache.

Interesting. I thought the driving force for asm goto was for tracepoints, as the documentation seems to reference them. One would think that the default would have been to make it the unlikely case, as it may be the only user of that code so far.

Quoted 3 lines

I was looking at fixing it, but I think a true general purpose fix would require enhancing GCC's grammar to allow specifying of the 'likelyness' of each exit path from 'asm goto'.

That would be nice.

Thanks,

-- Steve

#29 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 6 lines · Steven Rostedt

But it seemed that gcc for you inlined the code in the wrong spot. Perhaps it's not a good idea to have the something like h - softirq_vec in the parameter of the tracepoint. Not saying that your change is not worth it. It is, because h - softirq_vec is used by others now too.

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

The second thing that I found when implementing static_cpu_has() was that it is actually better to encapsulate the asm goto in a small inline which returns bool (true/false) -- gcc will happily optimize out the variable and only see it as a flow of control thing. I would be very curious if that wouldn't make gcc generate better code in cases like that.

gcc 4.5.0 has a bug in that there must be a flowthrough case in the asm goto (you can't have it unconditionally branch one way or the other), so that should be the likely case and accordingly it should be annotated likely() so that gcc doesn't reorder. I suspect in the end one ends up with code like this:

static __always_inline __pure bool __switch_point(...)

{
	asm goto("1: " JUMP_LABEL_INITIAL_NOP
		 /* ... patching stuff */
		: : : : t_jump);
	return false;
t_jump:
	return true;
}

#define SWITCH_POINT(x) unlikely(__switch_point(x))

I *suspect* this will resolve the need for hot/cold labels just fine.

-hpa

#62 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Jason Baron
Quoted 9 lines · Jason Baron
Quoted 4 lines · Thomas Gleixner
Quoted 1 line
Quoted 1 line · Steven Rostedt

So it trades a conditional vs. two jumps ? WTF ??

right, so the 'jmpq' on boot on x86 gets patched with 5 byte no-op sequence. So in the disabled case we have no-op followed by a jump around the disabled code.

And that's supposed to be useful ? We do _NOT_ want to jump around disabled stuff. The noped out case should fall through into the non traced code. Otherwise that whole jumplabel thing is completely useless.

Quoted 8 lines
Quoted 3 lines

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

yes, that is the plan. gcc does not yet support hot/cold labels...once it does the second jump will go away and the entire tracepoint code will be moved to a 'cold' section. It's not quite completely optimal yet, but we are getting there.

Then do not advertise it as the brilliant solution for all tracing matters.

Quoted 6 lines
Quoted 3 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

The 'jmpq' in the enabled case is patched with a jmpq to the body of the tracepoint itself.

Brilliant.

Quoted 19 lines
Quoted 19 lines

Did you guys ever look at the assembly output of that insane shite you are advertising with lengthy explanations ?

Obviously _NOT_

Come back when you can show me a clean imlementation of all this crap which reproduces with my jumplabel enabled stock compiler. And please just send me a patch w/o the blurb.

And sane looks like:

jmpq 2f <---- This gets noped out
1:

    mov    %r12,%rdi
    callq  *(%r12)
    [whatever cleanup it takes ]
    leaveq 
    retq   
Quoted 8 lines
Quoted 4 lines

2f:
[tracing gunk]
jmp 1b

yes, this is what the code should look like when we get support for hot/cold labels. I've discussed this support with gcc folk, and its the next step here. So yes, this is exacatly where we are headed.

So and at the same time the whole tracing crowd tells me, that this is already a done deal. See previous advertisments from DrTracing. I'm seriously grumpy about this especially in the context of a patch which fixes one of the worst interfaces I've seen in years.

Thanks,

tglx

#49 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 58 lines · Steven Rostedt
Quoted 9 lines · Thomas Gleixner
Quoted 8 lines · Steven Rostedt
Quoted 7 lines · Thomas Gleixner

So that saves _TWO_ bytes of text and replaces:

(quoted diff) +2 -2
-  1e:	83 3d 00 00 00 00 00 	cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:	74 4d                	je     74 <test+0x74>
+  1e:	e9 00 00 00 00       	jmpq   23 <test+0x23>
+  23:	eb 4d                	jmp    72 <test+0x72>
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

So it trades a conditional vs. two jumps ? WTF ??

Well, the one jmpq is noped out, and the jmp is non conditional. I've

What are you smoking ?

What? Are you saying that conditional jumps are just as fast as non conditional ones?

Quoted 3 lines

In case the trace point is enabled the jmpq is there, so it jumps to 23 and jumps from there to 72.

No, when we dynamically enable the tracepoint, it will jump to 25, not
23. That's what the goto part is about. We add the do_trace label to the table, and we make it point to that location. If we did it as you say, then tracepoints would never be enabled.

This is not unlike what we do with the function tracer. The original code points to mcount which simply is:

mcount:
retq

And when we enable the callers, we have it jump to a different function.

Quoted 3 lines

In case the trace point is disabled the jmpq is noped out, so it jumps to 72 directly.

That is correct.

Quoted 5 lines
Quoted 2 lines

always thought a non conditional jmp was faster than a conditional one,

I always thought, that at least some of the stuff which comes from tracing folks makes some sense.

Is it still not making sense?

Quoted 7 lines
Quoted 4 lines

since there's no need to go into the branch prediction logic. The CPU can simply skip to the code to jump next. Of counse, this pollutes the I$.

We might consult Mathieu for further useless blurb on how CPUs work around broken code.

Quoted 6 lines

The code worked fine before, it just was not very pretty.

But it seemed that gcc for you inlined the code in the wrong spot. Perhaps it's not a good idea to have the something like h - softirq_vec in the parameter of the tracepoint. Not saying that your change is not worth it. It is, because h - softirq_vec is used by others now too.

Crap, crap, crap. This has nothing to do with the arguments of that trace point, it's a compiler problem and you are just hoping that GCC will do the right thing.

That's the complete wrong assumption and as Jason confirmed GCC is not up to it at all.

hpa just posted code which does the _RIGHT_ _THING_ independent of any compiler madness and you tracer folks just missed it.

Your jump label optimization made code even worse for todays common compilers. Just admit it and fix that mess you created or simply disable it.

Thanks,

tglx

maintainer
#56 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 8 lines · Thomas Gleixner
Quoted 4 lines · Steven Rostedt

On Tue, 2010-10-19 at 21:49 +0200, Thomas Gleixner wrote:

Because you do the h - softvec in the tracepoint parameter? I got a different result:

I guess some serious whacking is due.

Quoted 8 lines

The compiler adds two jumps when the parameter changes due to
(h -softvec) instead of (h, softvec) ????

Dude, you can't be serious.

If you would have asked about the compiler version I'm using and told me about the compiler version you are using, then I could take that answer somehow serious.

Heh, gcc has always been of a black magic for what it decided. But, anyway, I'm using a self built version (vanilla from gcc.gnu.org) of 4.5.1. What are you using?

Quoted 9 lines

It still would miss the "Uhhhh, your compiler creates crap code" alert, because that double jump is seriously broken and braindead.

And I tell you more about this. You are going to piss off a lot of users of distro compilers because they will set CC_HAVE_ASM_GOTO happily and create the code I posted. Which will break the tracer no matter what.

Quoted 7 lines

So you tracer maniacs happily played with some experimental compiler stuff w/o even testing your crap against something which ships with distros or is the reference 4.5 compiler on kernel.org ?

I prefer you sending a patch to disable this, until it's sorted out, unless you want me to add some really outrageous changelog to the patch I'm going to put into tip tomorrow night, ok ?

Then lets just compare the crap versions you posted.

Review

Quoted 4 lines
(quoted diff) +2 -2
-  1e:        83 3d 00 00 00 00 00    cmpl   $0x0,0x0(%rip)        # 25 <test+0x25>
-  25:        74 4d                   je     74 <test+0x74>
+  1e:        e9 00 00 00 00          jmpq   23 <test+0x23>
+  23:        eb 4d                   jmp    72 <test+0x72>

Yes, gcc replaced a cmp and conditional jump with two unconditional jumps. One of these jumps on boot up will be converted to a nop. Thus the jump label code just converted a compare and conditional jump with a nop and a non conditional jump.

This still sounds like a win to me, although we can do better. I guess those poor sobs using a distro kernel compiled with a distro gcc that has CC_HAVE_ASM_GOTO enabled will still be doing better than if it was doing the if (enable) code.

-- Steve

#63 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 9 lines · Thomas Gleixner
Quoted 6 lines · Jason Baron
Quoted 3 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

The 'jmpq' in the enabled case is patched with a jmpq to the body of the tracepoint itself.

Brilliant.

IOW, We now jump around the jump which jumps around the disabled code.

Thanks,

tglx

maintainer
#30 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to H. Peter Anvin
Quoted 8 lines · H. Peter Anvin
Quoted 6 lines · Steven Rostedt

But it seemed that gcc for you inlined the code in the wrong spot. Perhaps it's not a good idea to have the something like h - softirq_vec in the parameter of the tracepoint. Not saying that your change is not worth it. It is, because h - softirq_vec is used by others now too.

Quoted 6 lines

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

Good question. Safety? Jason?

This is the initial jumps and are converted on boot up to a better nop.

Quoted 23 lines

The second thing that I found when implementing static_cpu_has() was that it is actually better to encapsulate the asm goto in a small inline which returns bool (true/false) -- gcc will happily optimize out the variable and only see it as a flow of control thing. I would be very curious if that wouldn't make gcc generate better code in cases like that.

gcc 4.5.0 has a bug in that there must be a flowthrough case in the asm goto (you can't have it unconditionally branch one way or the other), so that should be the likely case and accordingly it should be annotated likely() so that gcc doesn't reorder. I suspect in the end one ends up with code like this:

static __always_inline __pure bool __switch_point(...)

{
	asm goto("1: " JUMP_LABEL_INITIAL_NOP
		 /* ... patching stuff */
		: : : : t_jump);
	return false;
t_jump:
	return true;
}
Quoted 3 lines

#define SWITCH_POINT(x) unlikely(__switch_point(x))

I *suspect* this will resolve the need for hot/cold labels just fine.

Interesting, we could try this.

Thanks!

-- Steve

#31 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 10 lines · Steven Rostedt
Quoted 10 lines

static __always_inline __pure bool __switch_point(...)

{
	asm goto("1: " JUMP_LABEL_INITIAL_NOP
		 /* ... patching stuff */
		: : : : t_jump);
	return false;
t_jump:
	return true;
}
Quoted 5 lines
Quoted 3 lines

#define SWITCH_POINT(x) unlikely(__switch_point(x))

I *suspect* this will resolve the need for hot/cold labels just fine.

Interesting, we could try this.

Due to not actually having a sane key type the above is not easy to implement, but I tried:

#define _SWITCH_POINT(x)\

({                                                              \
        __label__ jl_enabled;                                   \
        bool ret = true;                                        \
        JUMP_LABEL(x, jl_enabled);                              \
        ret = false;                                            \
jl_enabled:                                                     \

ret; })

#define SWITCH_POINT(x) unlikely(_SWITCH_POINT(x))

#define COND_STMT(key, stmt)                                    \
do {                                                            \
        if (SWITCH_POINT(key)) {                                \
                stmt;                                           \
        }                                                       \

} while (0)

and that's still generating these double jumps.

#35 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 11 lines · Steven Rostedt
Quoted 10 lines · H. Peter Anvin
Quoted 6 lines · Steven Rostedt

But it seemed that gcc for you inlined the code in the wrong spot. Perhaps it's not a good idea to have the something like h - softirq_vec in the parameter of the tracepoint. Not saying that your change is not worth it. It is, because h - softirq_vec is used by others now too.

OK, first of all, there are some serious WTFs here:

Quoted 9 lines
Quoted 4 lines
# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

Good question. Safety? Jason?

This is the initial jumps and are converted on boot up to a better nop.

But it makes absolutely no sense to insert an instruction that suboptimal and then convert it. Start out with a reasonable, universally acceptable, instruction, e.g. LEA on 32 bits and NOPL on 64 bits.

Quoted 23 lines
Quoted 23 lines

The second thing that I found when implementing static_cpu_has() was that it is actually better to encapsulate the asm goto in a small inline which returns bool (true/false) -- gcc will happily optimize out the variable and only see it as a flow of control thing. I would be very curious if that wouldn't make gcc generate better code in cases like that.

gcc 4.5.0 has a bug in that there must be a flowthrough case in the asm goto (you can't have it unconditionally branch one way or the other), so that should be the likely case and accordingly it should be annotated likely() so that gcc doesn't reorder. I suspect in the end one ends up with code like this:

static __always_inline __pure bool __switch_point(...)

{
	asm goto("1: " JUMP_LABEL_INITIAL_NOP
		 /* ... patching stuff */
		: : : : t_jump);
	return false;
t_jump:
	return true;
}
Quoted 6 lines
Quoted 3 lines

#define SWITCH_POINT(x) unlikely(__switch_point(x))

I *suspect* this will resolve the need for hot/cold labels just fine.

Interesting, we could try this.

It of course also have the nice property that it syntactically looks exactly like any other C conditional.

-hpa

maintainer
#50 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 2 lines · Thomas Gleixner

hpa just posted code which does the _RIGHT_ _THING_ independent of any compiler madness and you tracer folks just missed it.

Thomas,

Can you try this patch and see if it makes the object code better?

-- Steve

include/linux/tracepoint.h +7 -2
index a4a90b6..6264bd3 100644
@@ -144,14 +144,19 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
  */
 #define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
 	extern struct tracepoint __tracepoint_##name;			\
-	static inline void trace_##name(proto)				\
+	static __always_inline int __trace_##name(proto)		\
 	{								\
 		JUMP_LABEL(&__tracepoint_##name.state, do_trace);	\
-		return;							\
+		return 0;						\
 do_trace:								\
 			__DO_TRACE(&__tracepoint_##name,		\
 				TP_PROTO(data_proto),			\
 				TP_ARGS(data_args));			\
+			return 1;					\
+	}								\
+	static inline void trace_##name(proto)				\
+	{								\
+		unlikely(__trace_##name(args));				\
 	}								\
 	static inline int						\
 	register_trace_##name(void (*probe)(data_proto), void *data)	\
#67 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 20 lines · Thomas Gleixner
Quoted 9 lines · Jason Baron
Quoted 4 lines · Thomas Gleixner
Quoted 1 line
Quoted 1 line · Steven Rostedt

So it trades a conditional vs. two jumps ? WTF ??

right, so the 'jmpq' on boot on x86 gets patched with 5 byte no-op sequence. So in the disabled case we have no-op followed by a jump around the disabled code.

And that's supposed to be useful ? We do _NOT_ want to jump around disabled stuff. The noped out case should fall through into the non traced code. Otherwise that whole jumplabel thing is completely useless.

Quoted 4 lines
Quoted 3 lines

I thought that jumplabel magic was supposed to get rid of the jump over the tracing code ? In fact it adds another jump. Whatfor ?

Quoted 8 lines
Quoted 4 lines

yes, that is the plan. gcc does not yet support hot/cold labels...once it does the second jump will go away and the entire tracepoint code will be moved to a 'cold' section. It's not quite completely optimal yet, but we are getting there.

Then do not advertise it as the brilliant solution for all tracing matters.

I'm not sure I did, the documentation says that we have nop followed by a jmp:

+The new code is a 'nopl' followed by a 'jmp'. Thus:
+
+nopl - 0f 1f 44 00 00 - 5 bytes
+jmp - eb 3e - 2 bytes

http://marc.info/?l=linux-kernel&m=128717355231182&w=2`

Quoted 37 lines
Quoted 6 lines
Quoted 3 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

The 'jmpq' in the enabled case is patched with a jmpq to the body of the tracepoint itself.

Brilliant.

Quoted 19 lines
Quoted 19 lines

Did you guys ever look at the assembly output of that insane shite you are advertising with lengthy explanations ?

Obviously _NOT_

Come back when you can show me a clean imlementation of all this crap which reproduces with my jumplabel enabled stock compiler. And please just send me a patch w/o the blurb.

And sane looks like:

jmpq 2f <---- This gets noped out
1:

    mov    %r12,%rdi
    callq  *(%r12)
    [whatever cleanup it takes ]
    leaveq 
    retq   
Quoted 8 lines
Quoted 4 lines

2f:
[tracing gunk]
jmp 1b

yes, this is what the code should look like when we get support for hot/cold labels. I've discussed this support with gcc folk, and its the next step here. So yes, this is exacatly where we are headed.

Quoted 8 lines

So and at the same time the whole tracing crowd tells me, that this is already a done deal. See previous advertisments from DrTracing. I'm seriously grumpy about this especially in the context of a patch which fixes one of the worst interfaces I've seen in years.

Thanks,

tglx

sorry if I mislead anybody about the current state of of 'jump labels'. But we have the same goal in mind, and a clear path to get there. If you don't agree with the approach - I'm all ears. And you are right - the code is not where it should be yet.

thanks,

-Jason

#36 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to H. Peter Anvin
Quoted 8 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 6 lines · Steven Rostedt

But it seemed that gcc for you inlined the code in the wrong spot. Perhaps it's not a good idea to have the something like h - softirq_vec in the parameter of the tracepoint. Not saying that your change is not worth it. It is, because h - softirq_vec is used by others now too.

Quoted 6 lines

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

This code is dynamically patched at boot time (and module load time) with a better nop, just like the function tracer does.

Quoted 23 lines

The second thing that I found when implementing static_cpu_has() was that it is actually better to encapsulate the asm goto in a small inline which returns bool (true/false) -- gcc will happily optimize out the variable and only see it as a flow of control thing. I would be very curious if that wouldn't make gcc generate better code in cases like that.

gcc 4.5.0 has a bug in that there must be a flowthrough case in the asm goto (you can't have it unconditionally branch one way or the other), so that should be the likely case and accordingly it should be annotated likely() so that gcc doesn't reorder. I suspect in the end one ends up with code like this:

static __always_inline __pure bool __switch_point(...)

{
	asm goto("1: " JUMP_LABEL_INITIAL_NOP
		 /* ... patching stuff */
		: : : : t_jump);
	return false;
t_jump:
	return true;
}
Quoted 3 lines

#define SWITCH_POINT(x) unlikely(__switch_point(x))

I *suspect* this will resolve the need for hot/cold labels just fine.

Thanks for the hint! We'll make sure to try it out. Having the ability to force gcc to put the tracepoint in an unlikely branch is deeply needed here.

I'm a bit curious about the nop vs jump overhead comparison you are referring to. It is an instruction latency benchmark or throughput benchmark ?

Intel's manual "Intel 64 and IA-32 Architectures Optimization Reference Manual"

http://www.intel.com/Assets/PDF/manual/248966.pdf

Page C-33 (or 577 in the pdf)

"7. Selection of conditional jump instructions should be based on the
recommendation of section Section 3.4.1, “Branch Prediction Optimization,” to improve the predictability of branches. When branches are predicted successfully, the latency of jcc is effectively zero."

So it mentions "jcc", but not jmp. Is there any reason for jmp to have a higher latency than jcc ?

In this manual, the latency of predicted jcc is therefore 0 cycle, and its throughput is 0.5 cycle/insn.

NOP (page C-29) is stated to have a latency of 0.5 to 1 cycle/insn (depending on the exact HW), and throughput of 0.5 cycle/insn.

However, I have not found "jmp" explicitly in this listing.

So if we were executing tracepoints in a maze of jumps, we could argue that instruction throughput is the most important there. However, if we expect the common case to be surrounded by some non-ALU instructions, latency tends to become the most important criterion.

But I feel I might be missing something important that distinguish "jcc" from "jmp".

Thanks,

Mathieu

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#68 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Jason Baron

Review

Quoted 9 lines · Jason Baron

I'm not sure I did, the documentation says that we have nop followed by a jmp:

(quoted diff) +4 -0
+The new code is a 'nopl' followed by a 'jmp'. Thus:
+
+nopl - 0f 1f 44 00 00 - 5 bytes
+jmp  - eb 3e          - 2 bytes

There is no excuse for needing the second jump here, obviously...

-hpa

#37 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Mathieu Desnoyers
Quoted 11 lines · Mathieu Desnoyers
Quoted 7 lines

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

This code is dynamically patched at boot time (and module load time) with a better nop, just like the function tracer does.

That's just ridiculous... start out with something sane and you at least have the chance of not having to patch it.

Quoted 22 lines

Intel's manual "Intel 64 and IA-32 Architectures Optimization Reference Manual"

http://www.intel.com/Assets/PDF/manual/248966.pdf

Page C-33 (or 577 in the pdf)

"7. Selection of conditional jump instructions should be based on the
recommendation of section Section 3.4.1, “Branch Prediction Optimization,” to improve the predictability of branches. When branches are predicted successfully, the latency of jcc is effectively zero."

So it mentions "jcc", but not jmp. Is there any reason for jmp to have a higher latency than jcc ?

In this manual, the latency of predicted jcc is therefore 0 cycle, and its throughput is 0.5 cycle/insn.

NOP (page C-29) is stated to have a latency of 0.5 to 1 cycle/insn (depending on the exact HW), and throughput of 0.5 cycle/insn.

However, I have not found "jmp" explicitly in this listing.

Quoted 7 lines

So if we were executing tracepoints in a maze of jumps, we could argue that instruction throughput is the most important there. However, if we expect the common case to be surrounded by some non-ALU instructions, latency tends to become the most important criterion.

But I feel I might be missing something important that distinguish "jcc" from "jmp".

NOP has a latency of 0.5-1.0 cycle/insns, *but has no consumers*.

JMP/Jcc does have a consumer -- the IP -- and actually measuring shows that it is much, much worse than NOP and other dummy instructions.

-hpa

maintainer
#69 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to H. Peter Anvin
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Jason Baron

I'm not sure I did, the documentation says that we have nop followed by a jmp:

Quoted 7 lines

Review

Quoted 5 lines
(quoted diff) +4 -0
+The new code is a 'nopl' followed by a 'jmp'. Thus:
+
+nopl - 0f 1f 44 00 00 - 5 bytes
+jmp  - eb 3e          - 2 bytes

There is no excuse for needing the second jump here, obviously...

Now the trick is to tell gcc that.

-- Steve

#70 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 5 lines · Steven Rostedt
Quoted 2 lines

There is no excuse for needing the second jump here, obviously...

Now the trick is to tell gcc that.

Yes.

-hpa

maintainer
#38 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to H. Peter Anvin
Quoted 9 lines · H. Peter Anvin
Quoted 8 lines · Mathieu Desnoyers
Quoted 7 lines

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

Quoted 6 lines
Quoted 3 lines

This code is dynamically patched at boot time (and module load time) with a better nop, just like the function tracer does.

That's just ridiculous... start out with something sane and you at least have the chance of not having to patch it.

Yep we can fix this. Jason?

Quoted 5 lines
Quoted 5 lines

So if we were executing tracepoints in a maze of jumps, we could argue that instruction throughput is the most important there. However, if we expect the common case to be surrounded by some non-ALU instructions, latency tends to become the most important criterion.

Quoted 7 lines
Quoted 2 lines

But I feel I might be missing something important that distinguish "jcc" from "jmp".

NOP has a latency of 0.5-1.0 cycle/insns, *but has no consumers*.

JMP/Jcc does have a consumer -- the IP -- and actually measuring shows that it is much, much worse than NOP and other dummy instructions.

But how does JMP vs Jcc compare?

-- Steve

#39 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 6 lines · Steven Rostedt
Quoted 3 lines

JMP/Jcc does have a consumer -- the IP -- and actually measuring shows that it is much, much worse than NOP and other dummy instructions.

But how does JMP vs Jcc compare?

*As far as I know* they're the same, except of course that a direct JMP never mispredicts.

-hpa

#32 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Peter Zijlstra
Quoted 20 lines · Peter Zijlstra

Due to not actually having a sane key type the above is not easy to implement, but I tried:

#define _SWITCH_POINT(x)\

({                                                              \
        __label__ jl_enabled;                                   \
        bool ret = true;                                        \
        JUMP_LABEL(x, jl_enabled);                              \
        ret = false;                                            \
jl_enabled:                                                     \

ret; })

#define SWITCH_POINT(x) unlikely(_SWITCH_POINT(x))

#define COND_STMT(key, stmt)                                    \
do {                                                            \
        if (SWITCH_POINT(key)) {                                \
                stmt;                                           \
        }                                                       \
Quoted 5 lines

} while (0)

and that's still generating these double jumps.

I just experimented with it, and the ({...}) construct doesn't work, because it looks like a merged flow of control to gcc.

Replacing the ({ ... }) with an inline does indeed remove the double jumps.

include/linux/jump_label.h +0 -0
index b67cb18..2ff829d 100644
@@ -61,12 +61,22 @@ static inline int jump_label_text_reserved(void

*start, void *end)

#endif

+static __always_inline __pure bool _SWITCH_POINT(void *x) +{
+ asm goto("# SWITCH_POINT %0\n\t"

+                ".byte 0x66,0x66,0x66,0x66,0x90\n"
+                "1:"
+                : : "i" (x) : : jl_enabled);

+ return false;
+jl_enabled:
+ return true;
+}
+
+#define SWITCH_POINT(x) unlikely(_SWITCH_POINT(x))
+

 #define COND_STMT(key, stmt)                                   \
 do {                                                           \
-       __label__ jl_enabled;                                   \
-       JUMP_LABEL(key, jl_enabled);                            \
-       if (0) {                                                \
-jl_enabled:                                                    \
+       if (SWITCH_POINT(key)) {                                \
                stmt;                                           \
        }                                                       \

} while (0)

The key here seems to be to not use the JUMP_LABEL macro as implemented; I have utterly failed to make JUMP_LABEL() do the right thing.

-hpa

maintainer
#33 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 2 lines · H. Peter Anvin

The key here seems to be to not use the JUMP_LABEL macro as implemented; I have utterly failed to make JUMP_LABEL() do the right thing.

What happens if you remove the do { } while (0) from JUMP_LABEL, since it now just makes it into a asm()

-- Steve

#34 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to H. Peter Anvin
Quoted 67 lines · H. Peter Anvin
Quoted 20 lines · Peter Zijlstra

Due to not actually having a sane key type the above is not easy to implement, but I tried:

#define _SWITCH_POINT(x)\

({                                                              \
        __label__ jl_enabled;                                   \
        bool ret = true;                                        \
        JUMP_LABEL(x, jl_enabled);                              \
        ret = false;                                            \
jl_enabled:                                                     \

ret; })

#define SWITCH_POINT(x) unlikely(_SWITCH_POINT(x))

#define COND_STMT(key, stmt)                                    \
do {                                                            \
        if (SWITCH_POINT(key)) {                                \
                stmt;                                           \
        }                                                       \
Quoted 5 lines

} while (0)

and that's still generating these double jumps.

I just experimented with it, and the ({...}) construct doesn't work, because it looks like a merged flow of control to gcc.

Replacing the ({ ... }) with an inline does indeed remove the double jumps.

include/linux/jump_label.h +14 -4
index b67cb18..2ff829d 100644
@@ -61,12 +61,22 @@ static inline int jump_label_text_reserved(void
 *start, void *end)
 
 #endif
 
+static __always_inline __pure bool _SWITCH_POINT(void *x)
+{
+       asm goto("# SWITCH_POINT %0\n\t"
+                ".byte 0x66,0x66,0x66,0x66,0x90\n"
+                "1:"
+                : : "i" (x) : : jl_enabled);
+       return false;
+jl_enabled:
+       return true;
+}
+
+#define SWITCH_POINT(x)        unlikely(_SWITCH_POINT(x))
+
 #define COND_STMT(key, stmt)                                   \
 do {                                                           \
-       __label__ jl_enabled;                                   \
-       JUMP_LABEL(key, jl_enabled);                            \
-       if (0) {                                                \
-jl_enabled:                                                    \
+       if (SWITCH_POINT(key)) {                                \
                stmt;                                           \
        }                                                       \

} while (0)

Quoted 3 lines

The key here seems to be to not use the JUMP_LABEL macro as implemented; I have utterly failed to make JUMP_LABEL() do the right thing.

ok, I tried this out for the tracepoint code, but I still seem to be getting the double jump.

patch:

include/linux/jump_label.h +14 -4
index 1947a12..7bc2537 100644
@@ -66,12 +66,22 @@ static inline void jump_label_unlock(void) {}
 
 #endif
 
+static __always_inline __pure bool _SWITCH_POINT(void *x)
+{
+	asm goto("# SWITCH_POINT %0\n\t"
+		 ".byte 0x66,0x66,0x66,0x66,0x90\n"
+		 "1:"
+		 : : "i" (x) : : jl_enabled);
+	return false;
+jl_enabled:
+	return true;
+}
+
+#define SWITCH_POINT(x)        unlikely(_SWITCH_POINT(x))
+
 #define COND_STMT(key, stmt)					\
 do {								\
-	__label__ jl_enabled;					\
-	JUMP_LABEL(key, jl_enabled);				\
-	if (0) {						\
-jl_enabled:							\
+	if (SWITCH_POINT(key)) {                                \
 		stmt;						\
 	}							\
 } while (0)
include/linux/tracepoint.h +1 -6
index a4a90b6..1f8d14f 100644
@@ -146,12 +146,7 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
 	extern struct tracepoint __tracepoint_##name;			\
 	static inline void trace_##name(proto)				\
 	{								\
-		JUMP_LABEL(&__tracepoint_##name.state, do_trace);	\
-		return;							\
-do_trace:								\
-			__DO_TRACE(&__tracepoint_##name,		\
-				TP_PROTO(data_proto),			\
-				TP_ARGS(data_args));			\
+		COND_STMT(&__tracepoint_##name.state, __DO_TRACE(&__tracepoint_##name, TP_PROTO(data_proto), TP_ARGS(data_args)));						     \
 	}								\
 	static inline int						\
 	register_trace_##name(void (*probe)(data_proto), void *data)	\

disassemly:

ffffffff810360a6 <set_task_cpu>:

ffffffff810360a6:       55                      push   %rbp
ffffffff810360a7:       48 89 e5                mov    %rsp,%rbp
ffffffff810360aa:       41 55                   push   %r13
ffffffff810360ac:       41 54                   push   %r12
ffffffff810360ae:       41 89 f4                mov    %esi,%r12d
ffffffff810360b1:       53                      push   %rbx
ffffffff810360b2:       48 89 fb                mov    %rdi,%rbx
ffffffff810360b5:       48 81 ec b8 00 00 00    sub    $0xb8,%rsp
ffffffff810360bc:       66 66 66 66 90          data32 data32 data32
xchg %ax,%ax
ffffffff810360c1:       eb 19                   jmp    ffffffff810360dc
<set_task_cpu+0x36>
ffffffff810360c3:       49 8b 7d 08             mov    0x8(%r13),%rdi
ffffffff810360c7:       44 89 e2                mov    %r12d,%edx
ffffffff810360ca:       48 89 de                mov    %rbx,%rsi
ffffffff810360cd:       41 ff 55 00             callq  *0x0(%r13)
ffffffff810360d1:       49 83 c5 10             add    $0x10,%r13
ffffffff810360d5:       49 83 7d 00 00          cmpq   $0x0,0x0(%r13)
ffffffff810360da:       eb 6c                   jmp    ffffffff81036148
<set_task_cpu+0xa2>
ffffffff810360dc:       48 8b 43 08             mov    0x8(%rbx),%rax
ffffffff810360e0:       44 39 60 18             cmp    %r12d,0x18(%rax)
ffffffff810360e4:       74 37                   je     ffffffff8103611d
<set_task_cpu+0x77>
ffffffff810360e6:       48 ff 83 98 00 00 00    incq   0x98(%rbx)
ffffffff810360ed:       e9 00 00 00 00          jmpq   ffffffff810360f2
<set_task_cpu+0x4c>
ffffffff810360f2:       eb 29                   jmp    ffffffff8103611d
<set_task_cpu+0x77>
ffffffff810360f4:       4c 8d ad 30 ff ff ff    lea    -0xd0(%rbp),%r13
ffffffff810360fb:       4c 89 ef                mov    %r13,%rdi
ffffffff810360fe:       e8 c7 94 ff ff          callq  ffffffff8102f5ca
<perf_fetch_caller_regs>
ffffffff81036103:       45 31 c0                xor    %r8d,%r8d
ffffffff81036106:       4c 89 e9                mov    %r13,%rcx
ffffffff81036109:       ba 01 00 00 00          mov    $0x1,%edx
ffffffff8103610e:       be 01 00 00 00          mov    $0x1,%esi
ffffffff81036113:       bf 04 00 00 00          mov    $0x4,%edi
ffffffff81036118:       e8 67 19 07 00          callq  ffffffff810a7a84
<__perf_sw_event>
ffffffff8103611d:       44 89 e6                mov    %r12d,%esi
ffffffff81036120:       48 89 df                mov    %rbx,%rdi
ffffffff81036123:       e8 2f 75 ff ff          callq  ffffffff8102d657
<set_task_rq>
ffffffff81036128:       48 8b 43 08             mov    0x8(%rbx),%rax
ffffffff8103612c:       44 89 60 18             mov    %r12d,0x18(%rax)
ffffffff81036130:       48 81 c4 b8 00 00 00    add    $0xb8,%rsp
ffffffff81036137:       5b                      pop    %rbx
ffffffff81036138:       41 5c                   pop    %r12
ffffffff8103613a:       41 5d                   pop    %r13
ffffffff8103613c:       c9                      leaveq
ffffffff8103613d:       c3                      retq
ffffffff8103613e:       4c 8b 2d 3b 26 a9 00    mov
0xa9263b(%rip),%r13        # ffffffff81ac8780
<__tracepoint_sched_migrate_task+0x20>
ffffffff81036145:       4d 85 ed                test   %r13,%r13
ffffffff81036148:       0f 85 75 ff ff ff       jne    ffffffff810360c3

<set_task_cpu+0x1d>
ffffffff8103614e: eb 8c jmp ffffffff810360dc
<set_task_cpu+0x36>

I'm using gcc (GCC) 4.5.1 20100812

is my patch wrong?

thanks,

-Jason

maintainer
#64 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 6 lines · Thomas Gleixner
Quoted 5 lines · Thomas Gleixner
Quoted 4 lines · Jason Baron
Quoted 3 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

The 'jmpq' in the enabled case is patched with a jmpq to the body of the tracepoint itself.

Brilliant.

IOW, We now jump around the jump which jumps around the disabled code.

Do you happen to have CONFIG_CC_OPTIMIZE_FOR_SIZE set? If so, then this is a known issue. We even originally had jump label enabled _only_ if CC_OPTIMIZE_FOR_SIZE was not set, but hpa NAK'd it.

http://lkml.org/lkml/2010/9/22/482

http://lkml.org/lkml/2010/9/20/488

http://lkml.org/lkml/2010/9/24/259

-- Steve

#65 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 21 lines · Steven Rostedt
Quoted 6 lines · Thomas Gleixner
Quoted 5 lines · Thomas Gleixner
Quoted 4 lines · Jason Baron
Quoted 3 lines

Now even worse, when you NOP out the jmpq then your tracepoint is still not enabled. Brilliant !

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

The 'jmpq' in the enabled case is patched with a jmpq to the body of the tracepoint itself.

Brilliant.

IOW, We now jump around the jump which jumps around the disabled code.

Do you happen to have CONFIG_CC_OPTIMIZE_FOR_SIZE set? If so, then this is a known issue. We even originally had jump label enabled _only_ if CC_OPTIMIZE_FOR_SIZE was not set, but hpa NAK'd it.

Quoted 7 lines

http://lkml.org/lkml/2010/9/22/482

http://lkml.org/lkml/2010/9/20/488

http://lkml.org/lkml/2010/9/24/259

-- Steve

thanks Steve. I was about to say this. When CONFIG_CC_OPTIMIZE_FOR_SIZE is not set we don't get the double 'jmp' and the tracepoint code is moved out of line. It was mentioned that a number of distros ship with CONFIG_CC_OPTIMIZE_FOR_SIZE not set, and as Steve mentioned my original patch set was conditional on !CONFIG_CC_OPTIMIZE_FOR_SIZE.

using hot/cold labels gcc can fix the CONFIG_CC_OPTIMIZE_FOR_SIZE case, but its a non-trivial amount of work for gcc. I was hoping that if jump labels are included, we could make the gcc work happen.

thanks,

-Jason

#40 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 10 lines · Steven Rostedt
Quoted 9 lines · H. Peter Anvin
Quoted 8 lines · Mathieu Desnoyers
Quoted 7 lines

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines

This code is dynamically patched at boot time (and module load time) with a better nop, just like the function tracer does.

That's just ridiculous... start out with something sane and you at least have the chance of not having to patch it.

Yep we can fix this. Jason?

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

I've got a few fixup patches in the queue that I'm going to post first, and then I'll take a look at this change.

thanks,

-Jason

#41 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 21 lines · * Jason Baron ([email protected]) wrote:
Quoted 10 lines · Steven Rostedt
Quoted 9 lines · H. Peter Anvin
Quoted 8 lines · Mathieu Desnoyers
Quoted 7 lines

OK, first of all, there are some serious WTFs here:

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

A jump instruction is one of the worst possible NOPs. Why are we doing this?

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines

This code is dynamically patched at boot time (and module load time) with a better nop, just like the function tracer does.

That's just ridiculous... start out with something sane and you at least have the chance of not having to patch it.

Yep we can fix this. Jason?

Quoted 8 lines

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

I've got a few fixup patches in the queue that I'm going to post first, and then I'll take a look at this change.

One thing to consider here is that some nops are not compatible across all architectures. And it would be safer to use an atomic nops (a single instruction) too. e.g. GENERIC_NOP5 in arch/x86/include/asm/nops.h is really 2 instructions, which can cause problems if a concurrent thread is preempted between the two instructions while we patch.

arch_init_ideal_nop5() is actually doing the task of finding the best nop, and it falls-back on a 5-byte nop (just like you do).

HPA, do you have any recommendation for a 5-byte single-instruction nop that is efficient enough and will work on all x86 (Intel, AMD and other variants) ?

Thanks,

Mathieu

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#73 lore raw

[tip:perf/core] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Commit-ID:  f4bc6bb2d562703eafc895c37e7be20906de139d
Gitweb:     http://git.kernel.org/tip/f4bc6bb2d562703eafc895c37e7be20906de139d
Author:     Thomas Gleixner <[email protected]>
AuthorDate: Tue, 19 Oct 2010 15:00:13 +0200
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Thu, 21 Oct 2010 16:50:29 +0200

tracing: Cleanup the convoluted softirq tracepoints

With the addition of trace_softirq_raise() the softirq tracepoint got even more convoluted. Why the tracepoints take two pointers to assign an integer is beyond my comprehension.

But adding an extra case which treats the first pointer as an unsigned long when the second pointer is NULL including the back and forth type casting is just horrible.

Convert the softirq tracepoints to take a single unsigned int argument for the softirq vector number and fix the call sites.

LKML-Reference: <[email protected]>

Cc Frederic Weisbecker <[email protected]>
Cc Steven Rostedt <[email protected]>
---
 include/linux/interrupt.h  |    2 +-
 include/trace/events/irq.h |   54 ++++++++++++++++---------------------------
 kernel/softirq.c           |   16 +++++++-----
 3 files changed, 30 insertions(+), 42 deletions(-)
include/linux/interrupt.h +1 -1
index 531495d..0ac1949 100644
@@ -410,7 +410,7 @@ extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
 static inline void __raise_softirq_irqoff(unsigned int nr)
 {
-	trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+	trace_softirq_raise(nr);
 	or_softirq_pending(1UL << nr);
 }
 
include/trace/events/irq.h +20 -34

96 lines not on this page · raw message

kernel/softirq.c +9 -7
index 07b4f1b..b3cb1dc 100644
@@ -212,18 +212,20 @@ restart:
 
 	do {
 		if (pending & 1) {
+			unsigned int vec_nr = h - softirq_vec;
 			int prev_count = preempt_count();
-			kstat_incr_softirqs_this_cpu(h - softirq_vec);
 
-			trace_softirq_entry(h, softirq_vec);
+			kstat_incr_softirqs_this_cpu(vec_nr);
+
+			trace_softirq_entry(vec_nr);
 			h->action(h);
-			trace_softirq_exit(h, softirq_vec);
+			trace_softirq_exit(vec_nr);
 			if (unlikely(prev_count != preempt_count())) {
-				printk(KERN_ERR "huh, entered softirq %td %s %p"
+				printk(KERN_ERR "huh, entered softirq %u %s %p"
 				       "with preempt_count %08x,"
-				       " exited with %08x?\n", h - softirq_vec,
-				       softirq_to_name[h - softirq_vec],
-				       h->action, prev_count, preempt_count());
+				       " exited with %08x?\n", vec_nr,
+				       softirq_to_name[vec_nr], h->action,
+				       prev_count, preempt_count());
 				preempt_count() = prev_count;
 			}
 
#51 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Steven Rostedt
Quoted 8 lines · Steven Rostedt
Quoted 2 lines · Thomas Gleixner

hpa just posted code which does the _RIGHT_ _THING_ independent of any compiler madness and you tracer folks just missed it.

Thomas,

Can you try this patch and see if it makes the object code better?

Nope, same result.

Thanks,

tglx

Quoted 31 lines

-- Steve

include/linux/tracepoint.h +7 -2
index a4a90b6..6264bd3 100644
@@ -144,14 +144,19 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
  */
 #define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
 	extern struct tracepoint __tracepoint_##name;			\
-	static inline void trace_##name(proto)				\
+	static __always_inline int __trace_##name(proto)		\
 	{								\
 		JUMP_LABEL(&__tracepoint_##name.state, do_trace);	\
-		return;							\
+		return 0;						\
 do_trace:								\
 			__DO_TRACE(&__tracepoint_##name,		\
 				TP_PROTO(data_proto),			\
 				TP_ARGS(data_args));			\
+			return 1;					\
+	}								\
+	static inline void trace_##name(proto)				\
+	{								\
+		unlikely(__trace_##name(args));				\
 	}								\
 	static inline int						\
 	register_trace_##name(void (*probe)(data_proto), void *data)	\
maintainer
#52 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 5 lines · Thomas Gleixner
Quoted 2 lines · Steven Rostedt

On Wed, 2010-10-20 at 00:04 +0200, Thomas Gleixner wrote:

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

hpa just posted code which does the _RIGHT_ _THING_ independent of any compiler madness and you tracer folks just missed it.

Thomas,

Can you try this patch and see if it makes the object code better?

Nope, same result.

Yeah, I figured. Do you have CC_OPTIMIZE_FOR_SIZE set? And if you do, what happens if you disable it?

-- Steve

#53 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 9 lines · Steven Rostedt
Quoted 8 lines · Thomas Gleixner
Quoted 5 lines · Steven Rostedt
Quoted 2 lines · Thomas Gleixner

hpa just posted code which does the _RIGHT_ _THING_ independent of any compiler madness and you tracer folks just missed it.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

Thomas,

Can you try this patch and see if it makes the object code better?

Nope, same result.

Yeah, I figured. Do you have CC_OPTIMIZE_FOR_SIZE set? And if you do, what happens if you disable it?

Hmm. Indeed. That gets rid of the double jump.

Thanks,

tglx

#42 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Jason Baron
Quoted 7 lines · Jason Baron

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

It's still a completely unnecessary waste of startup time some potentially significant fraction of the time. Startup time matters, especially as the number of tracepoints grow.

-hpa

#43 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 9 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 7 lines · Jason Baron

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

Quoted 3 lines

It's still a completely unnecessary waste of startup time some potentially significant fraction of the time. Startup time matters, especially as the number of tracepoints grow.

We're still waiting for input for the best single-5-byte-instruction nop that will work on all x86 variants. Please note that the GENERIC_NOP5 is actually two instructions one next to each other, which is not appropriate here.

Thanks,

Mathieu

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#44 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 10 lines · Mathieu Desnoyers
Quoted 9 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 7 lines · Jason Baron

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

Quoted 8 lines
Quoted 3 lines

It's still a completely unnecessary waste of startup time some potentially significant fraction of the time. Startup time matters, especially as the number of tracepoints grow.

We're still waiting for input for the best single-5-byte-instruction nop that will work on all x86 variants. Please note that the GENERIC_NOP5 is actually two instructions one next to each other, which is not appropriate here.

On 64 bits, use P6_NOP5; it seems to not suck on any platform.

On 32 bits, 3E 8D 74 26 00 (i.e. DS: + GENERIC_NOP4) seems to at least do okay.

I can't say these are the *best* (in fact, they are guaranteed not the best on some significant number of chips), but they haven't sucked on any chips I have been able to measure -- and are way faster than JMP.

-hpa

#45 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 10 lines · H. Peter Anvin

On 64 bits, use P6_NOP5; it seems to not suck on any platform.

On 32 bits, 3E 8D 74 26 00 (i.e. DS: + GENERIC_NOP4) seems to at least do okay.

I can't say these are the *best* (in fact, they are guaranteed not the best on some significant number of chips), but they haven't sucked on any chips I have been able to measure -- and are way faster than JMP.

This is pure conjecture, I have not measured it, but I suspect in fact that we could just change the composite nops in nops.h to use a 3E prefix instead of a separate 90 nop. Some platforms will take a penalty on the prefix, but that would be balanced against handling two instructions.

The P5 core and others of the same generation might suffer, as it might have been able to do U+V pipe pairing on two instructions which it wouldn't for prefixes.

-hpa

#54 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Thomas Gleixner
Quoted 13 lines · Thomas Gleixner
Quoted 11 lines · Steven Rostedt
Quoted 10 lines · Thomas Gleixner
Quoted 7 lines · Steven Rostedt
Quoted 2 lines · Thomas Gleixner

hpa just posted code which does the _RIGHT_ _THING_ independent of any compiler madness and you tracer folks just missed it.

Thomas,

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line

Can you try this patch and see if it makes the object code better?

Nope, same result.

Yeah, I figured. Do you have CC_OPTIMIZE_FOR_SIZE set? And if you do, what happens if you disable it?

Hmm. Indeed. That gets rid of the double jump.

-Os unfortunately drops a bunch of optimizations.

With gcc 4.5.1 there is actually a way to guarantee to get rid of double jumps, which is that you tell gcc that it is branching to one of two targets:

                asm goto("1: .byte 0xe9 ; .long %l[t_no]-2f\n"
			 "2:\n"
		         /* patching infrastructure goes here */
                         : : "i" (bit) : : t_no, t_yes);
	        __builtin_unreachable();
t_no:
                return false;
t_yes:
                return true;

[The open-coding of the jump is necessary to force the 5-byte form instead of the 2-byte form.]

The patching machinery can recognize the case where the jump offset is zero and patch in a NOP instead.

There does, however, seem to be a couple of problems:

a) gcc 4.5.1 is required due to a bug in previous versions of gcc when an asm goto doesn't have a fallthrough case.

b) it seems to encourage gcc to actively jump around as it reorders blocks, since gcc no longer sees a fallthrough case at all.

Not sure I have a good solution for this, at least not with current gcc.

-hpa

#66 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to Jason Baron
Quoted 11 lines · Jason Baron

thanks Steve. I was about to say this. When CONFIG_CC_OPTIMIZE_FOR_SIZE is not set we don't get the double 'jmp' and the tracepoint code is moved out of line. It was mentioned that a number of distros ship with CONFIG_CC_OPTIMIZE_FOR_SIZE not set, and as Steve mentioned my original patch set was conditional on !CONFIG_CC_OPTIMIZE_FOR_SIZE.

using hot/cold labels gcc can fix the CONFIG_CC_OPTIMIZE_FOR_SIZE case, but its a non-trivial amount of work for gcc. I was hoping that if jump labels are included, we could make the gcc work happen.

That's fair. I think jump labels are still a win even in the double-jump case (especially if the the tracepoint turns into a NOP rather than a JMP.)

Code generated with -Os has a bunch of other problems, too.

-hpa

#46 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

In reply to H. Peter Anvin
Quoted 20 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 10 lines · Mathieu Desnoyers
Quoted 9 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 7 lines · Jason Baron

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

Quoted 8 lines
Quoted 3 lines

It's still a completely unnecessary waste of startup time some potentially significant fraction of the time. Startup time matters, especially as the number of tracepoints grow.

We're still waiting for input for the best single-5-byte-instruction nop that will work on all x86 variants. Please note that the GENERIC_NOP5 is actually two instructions one next to each other, which is not appropriate here.

Quoted 8 lines

On 64 bits, use P6_NOP5; it seems to not suck on any platform.

On 32 bits, 3E 8D 74 26 00 (i.e. DS: + GENERIC_NOP4) seems to at least do okay.

I can't say these are the *best* (in fact, they are guaranteed not the best on some significant number of chips), but they haven't sucked on any chips I have been able to measure -- and are way faster than JMP.

Cool, thanks for the info! Steven and Jason should probably update their respective infrastructure to use the 32-bit 5-byte nop you propose rather than the 5-byte jump.

Mathieu

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
maintainer
#47 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 26 lines · Mathieu Desnoyers
Quoted 25 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 10 lines · Mathieu Desnoyers
Quoted 9 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 7 lines · Jason Baron

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

Quoted 8 lines
Quoted 3 lines

It's still a completely unnecessary waste of startup time some potentially significant fraction of the time. Startup time matters, especially as the number of tracepoints grow.

We're still waiting for input for the best single-5-byte-instruction nop that will work on all x86 variants. Please note that the GENERIC_NOP5 is actually two instructions one next to each other, which is not appropriate here.

On 64 bits, use P6_NOP5; it seems to not suck on any platform.

On 32 bits, 3E 8D 74 26 00 (i.e. DS: + GENERIC_NOP4) seems to at least do okay.

Quoted 7 lines
Quoted 3 lines

I can't say these are the *best* (in fact, they are guaranteed not the best on some significant number of chips), but they haven't sucked on any chips I have been able to measure -- and are way faster than JMP.

Cool, thanks for the info! Steven and Jason should probably update their respective infrastructure to use the 32-bit 5-byte nop you propose rather than the 5-byte jump.

Actually, I was thinking that we could take any 5 byte nop. The alternate code is executed _before_ SMP is enabled. Thus we should not have any cases where something could be executing in midstream.

-- Steve

#48 lore raw

Re: [PATCH] tracing: Cleanup the convoluted softirq tracepoints

Quoted 31 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 30 lines · Mathieu Desnoyers
Quoted 28 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 10 lines · Mathieu Desnoyers
Quoted 9 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 7 lines · Jason Baron

sure. The idea of the 'jmp 0' was simply to be an lcd for x86, if there's a better lcd for x86, I'll update it. But note, that since the 'jmp 0' is patched to a better nop at boot, we wouldn't see much gain. And in the boot path we are using 'text_poke_early()', so avoiding that isn't going to improve things much.

Quoted 8 lines
Quoted 3 lines

It's still a completely unnecessary waste of startup time some potentially significant fraction of the time. Startup time matters, especially as the number of tracepoints grow.

We're still waiting for input for the best single-5-byte-instruction nop that will work on all x86 variants. Please note that the GENERIC_NOP5 is actually two instructions one next to each other, which is not appropriate here.

On 64 bits, use P6_NOP5; it seems to not suck on any platform.

On 32 bits, 3E 8D 74 26 00 (i.e. DS: + GENERIC_NOP4) seems to at least do okay.

I can't say these are the *best* (in fact, they are guaranteed not the best on some significant number of chips), but they haven't sucked on any chips I have been able to measure -- and are way faster than JMP.

Quoted 7 lines
Quoted 3 lines

Cool, thanks for the info! Steven and Jason should probably update their respective infrastructure to use the 32-bit 5-byte nop you propose rather than the 5-byte jump.

Actually, I was thinking that we could take any 5 byte nop. The alternate code is executed _before_ SMP is enabled. Thus we should not have any cases where something could be executing in midstream.

Nay, absolutely not. See, the goal here is to find a no-op that is good enough to be left there *without* init-time dynamic patching on a range of architectures, so we can diminish the boot-time delay. This imply that we have to select a no-op that can be patched in SMP context, thus it must be a single 5-byte instruction. We could even create a EMBEDDED config that lets specify that the built-in nop should be left there for embedded systems that care about boot time.

Moreover, even if it was not the case, I'd be tempted to still use a single instruction 5-byte no-op just in case interrupts or any sorts (standard interrupts, nmis, mce or whatnot) would happen to be enabled earlier than this boot time nop patching.

IOW, you'd need a _very_ strong argument to support using the fragile 2 instructions nops there.

Thanks,

Mathieu

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com