2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include <rte_cycles.h>
20 #include "task_base.h"
21 #include "task_init.h"
22 #include "handle_irq.h"
27 #define MAX_INDEX 65535 * 16
36 struct irq_info info[MAX_INDEX];
40 struct task_base base;
45 volatile uint16_t stats_use_lt; /* which lt to use, */
46 volatile uint16_t task_use_lt; /* 0 or 1 depending on which of the 2 result records are used */
47 struct irq_bucket buffer[2];
50 #define MAX_INTERRUPT_LENGTH 500000 /* Maximum length of an interrupt is (1 / MAX_INTERRUPT_LENGTH) seconds */
53 * This module is not handling any packets.
54 * It loops on rdtsc() and checks whether it has been interrupted
55 * for more than (1 / MAX_INTERRUPT_LENGTH) sec.
56 * This is a debugging only task, useful to check if the system h
57 * as been properly configured.
60 void task_irq_show_stats(struct task_irq *task_irq, struct input *input)
62 struct irq_bucket *bucket = &task_irq->buffer[!task_irq->task_use_lt];
65 if (bucket->index == 0) {
67 input->reply(input, buf, strlen(buf));
70 for (uint64_t i = 0; i < bucket->index; i++) {
71 sprintf(buf + strlen(buf), "%d; %"PRIu64"""; %ld; %ld; %ld; %ld ;",
75 bucket->info[i].lat * 1000000 / rte_get_tsc_hz(),
76 bucket->info[i].tsc - task_irq->start_tsc,
77 (bucket->info[i].tsc - task_irq->start_tsc) * 1000 / rte_get_tsc_hz());
78 sprintf(buf+strlen(buf), "\n");
79 input->reply(input, buf, strlen(buf));
83 for (uint64_t i = 0; i < bucket->index; i++)
84 if (bucket->info[i].lat)
85 plog_info("[%d]; Interrupt %"PRIu64": %ld cycles (%ld micro-sec) at %ld cycles (%ld msec)\n",
89 bucket->info[i].lat * 1000000 / rte_get_tsc_hz(),
90 bucket->info[i].tsc - task_irq->start_tsc,
91 (bucket->info[i].tsc - task_irq->start_tsc) * 1000 / rte_get_tsc_hz());
93 task_irq->stats_use_lt = !task_irq->task_use_lt;
97 static void irq_stop(struct task_base *tbase)
99 struct task_irq *task = (struct task_irq *)tbase;
101 uint32_t lcore_id = rte_lcore_id();
104 plog_info("Stopping core %u\n", lcore_id);
105 plog_info("Core ID; Interrupt (nanosec); Time (msec)\n");
106 for (int j = 0; j < 2; j++) {
107 // Start dumping the oldest bucket first
108 if (task->buffer[0].info[0].tsc < task->buffer[1].info[0].tsc)
112 struct irq_bucket *bucket = &task->buffer[bucket_id];
113 for (i=0; i< bucket->index;i++) {
114 if (bucket->info[i].lat != 0) {
115 plog_info("%d; %ld; %ld\n",
117 bucket->info[i].lat * 1000000000 / rte_get_tsc_hz(),
118 (bucket->info[i].tsc - task->start_tsc) * 1000 / rte_get_tsc_hz());
122 plog_info("Core %u stopped\n", lcore_id);
125 static inline int handle_irq_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
127 struct task_irq *task = (struct task_irq *)tbase;
131 if (task->stats_use_lt != task->task_use_lt)
132 task->task_use_lt = task->stats_use_lt;
133 struct irq_bucket *bucket = &task->buffer[task->task_use_lt];
136 if ((task->tsc != 0) && ((tsc1 - task->tsc) > task->max_irq) && (bucket->index < MAX_INDEX)) {
137 bucket->info[bucket->index].tsc = tsc1;
138 bucket->info[bucket->index++].lat = tsc1 - task->tsc;
144 static void init_task_irq(struct task_base *tbase,
145 __attribute__((unused)) struct task_args *targ)
147 struct task_irq *task = (struct task_irq *)tbase;
148 // max_irq expressed in cycles
149 task->max_irq = rte_get_tsc_hz() / MAX_INTERRUPT_LENGTH;
150 task->start_tsc = rte_rdtsc();
151 task->lcore_id = targ->lconf->id;
152 plog_info("\tusing irq mode with max irq set to %ld cycles\n", task->max_irq);
155 static struct task_init task_init_irq = {
157 .init = init_task_irq,
158 .handle = handle_irq_bulk,
160 .flag_features = TASK_FEATURE_NO_RX,
161 .size = sizeof(struct task_irq)
164 static struct task_init task_init_none;
166 __attribute__((constructor)) static void reg_task_irq(void)
168 reg_task(&task_init_irq);