aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-05-21 05:08:34 -0400
committerJohannes Berg <johannes@sipsolutions.net>2010-05-25 07:17:03 -0400
commit436458c3567f64355095e0b75474d94bdfe9646f (patch)
treeb72470571f79efdf9b3f66bf0236a8e5e024b0b9
parentd01318f336b345e7727a711a98eda59cf9d3ba8f (diff)
trace-cmd: make records refcounted
If a callback wants to hold on to a record, it can then increase the refcount and keep it. This is most likely to happen with the upcoming python plugin. Since the underlying data pages are already refcounted, we can just add a refcount to struct record (rather than having the error checking with the 'locked' member). Acked-by: Darren Hart <dvhltc@us.ibm.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
-rw-r--r--parse-events.h2
-rw-r--r--trace-ftrace.c9
-rw-r--r--trace-input.c43
-rw-r--r--trace-plot-cpu.c2
-rw-r--r--trace-plot-task.c1
5 files changed, 37 insertions, 20 deletions
diff --git a/parse-events.h b/parse-events.h
index 7d1c42e..7f79619 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -43,7 +43,7 @@ struct record {
43 int size; /* size of data */ 43 int size; /* size of data */
44 void *data; 44 void *data;
45 int cpu; 45 int cpu;
46 int locked; /* Do not allow freeing */ 46 int ref_count;
47 void *private; 47 void *private;
48}; 48};
49 49
diff --git a/trace-ftrace.c b/trace-ftrace.c
index af9ac8d..7cd5032 100644
--- a/trace-ftrace.c
+++ b/trace-ftrace.c
@@ -255,8 +255,13 @@ fgraph_ent_handler(struct trace_seq *s, struct record *record,
255 return trace_seq_putc(s, '!'); 255 return trace_seq_putc(s, '!');
256 256
257 rec = tracecmd_peek_data(tracecmd_curr_thread_handle, cpu); 257 rec = tracecmd_peek_data(tracecmd_curr_thread_handle, cpu);
258 if (rec) 258 if (rec) {
259 rec = get_return_for_leaf(s, cpu, pid, val, rec); 259 struct record *tmp;
260
261 tmp = get_return_for_leaf(s, cpu, pid, val, rec);
262 free_record(rec);
263 rec = tmp;
264 }
260 265
261 if (rec) { 266 if (rec) {
262 /* 267 /*
diff --git a/trace-input.c b/trace-input.c
index c39004a..9db96c7 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -660,8 +660,13 @@ void free_record(struct record *record)
660 if (!record) 660 if (!record)
661 return; 661 return;
662 662
663 if (record->locked) 663 if (!record->ref_count)
664 die("freeing record when it is locked!"); 664 die("record ref count is zero!");
665
666 record->ref_count--;
667 if (record->ref_count)
668 return;
669
665 record->data = NULL; 670 record->data = NULL;
666 671
667 __free_record(record); 672 __free_record(record);
@@ -675,7 +680,8 @@ static void free_next(struct tracecmd_input *handle, int cpu)
675 return; 680 return;
676 681
677 handle->cpu_data[cpu].next = NULL; 682 handle->cpu_data[cpu].next = NULL;
678 __free_record(record); 683
684 free_record(record);
679} 685}
680 686
681/* 687/*
@@ -870,6 +876,7 @@ read_old_format(struct tracecmd_input *handle, void **ptr, int cpu)
870 return NULL; 876 return NULL;
871 memset(data, 0, sizeof(*data)); 877 memset(data, 0, sizeof(*data));
872 878
879 data->ref_count = 1;
873 data->ts = handle->cpu_data[cpu].timestamp; 880 data->ts = handle->cpu_data[cpu].timestamp;
874 data->size = length; 881 data->size = length;
875 data->data = *ptr; 882 data->data = *ptr;
@@ -902,11 +909,12 @@ peek_event(struct tracecmd_input *handle, unsigned long long offset,
902 free_next(handle, cpu); 909 free_next(handle, cpu);
903 910
904 do { 911 do {
905 free_record(record);
906 record = tracecmd_peek_data(handle, cpu); 912 record = tracecmd_peek_data(handle, cpu);
907 if (record && (record->offset + record->record_size) > offset) 913 if (record && (record->offset + record->record_size) > offset)
908 break; 914 break;
909 record = tracecmd_read_data(handle, cpu); 915 free_record(record);
916
917 free_next(handle, cpu);
910 } while (record); 918 } while (record);
911 919
912 return record; 920 return record;
@@ -919,8 +927,10 @@ read_event(struct tracecmd_input *handle, unsigned long long offset,
919 struct record *record; 927 struct record *record;
920 928
921 record = peek_event(handle, offset, cpu); 929 record = peek_event(handle, offset, cpu);
922 if (record) 930 if (record) {
931 free_record(record);
923 record = tracecmd_read_data(handle, cpu); 932 record = tracecmd_read_data(handle, cpu);
933 }
924 return record; 934 return record;
925} 935}
926 936
@@ -1301,7 +1311,7 @@ int tracecmd_set_cursor(struct tracecmd_input *handle,
1301 if (get_page(handle, cpu, page_offset) < 0) 1311 if (get_page(handle, cpu, page_offset) < 0)
1302 return -1; 1312 return -1;
1303 1313
1304 peek_event(handle, offset, cpu); 1314 free_record(peek_event(handle, offset, cpu));
1305 1315
1306 return 0; 1316 return 0;
1307} 1317}
@@ -1429,6 +1439,7 @@ tracecmd_translate_data(struct tracecmd_input *handle,
1429 return NULL; 1439 return NULL;
1430 memset(record, 0, sizeof(*record)); 1440 memset(record, 0, sizeof(*record));
1431 1441
1442 record->ref_count = 1;
1432 record->data = ptr; 1443 record->data = ptr;
1433 type_len = translate_data(handle, &record->data, &record->ts, &record->size); 1444 type_len = translate_data(handle, &record->data, &record->ts, &record->size);
1434 switch (type_len) { 1445 switch (type_len) {
@@ -1451,8 +1462,6 @@ tracecmd_translate_data(struct tracecmd_input *handle,
1451 * 1462 *
1452 * This returns the record at the current location of the CPU 1463 * This returns the record at the current location of the CPU
1453 * iterator. It does not increment the CPU iterator. 1464 * iterator. It does not increment the CPU iterator.
1454 *
1455 * NOTE: Do not free the record returned, it is stored in the @handle.
1456 */ 1465 */
1457struct record * 1466struct record *
1458tracecmd_peek_data(struct tracecmd_input *handle, int cpu) 1467tracecmd_peek_data(struct tracecmd_input *handle, int cpu)
@@ -1479,8 +1488,10 @@ tracecmd_peek_data(struct tracecmd_input *handle, int cpu)
1479 if (!record->data) 1488 if (!record->data)
1480 die("Something freed the record"); 1489 die("Something freed the record");
1481 1490
1482 if (handle->cpu_data[cpu].timestamp == record->ts) 1491 if (handle->cpu_data[cpu].timestamp == record->ts) {
1492 record->ref_count++;
1483 return record; 1493 return record;
1494 }
1484 1495
1485 /* 1496 /*
1486 * The timestamp changed, which means the cached 1497 * The timestamp changed, which means the cached
@@ -1553,6 +1564,7 @@ read_again:
1553 record->data = ptr; 1564 record->data = ptr;
1554 record->offset = handle->cpu_data[cpu].offset + index; 1565 record->offset = handle->cpu_data[cpu].offset + index;
1555 record->missed_events = missed_events; 1566 record->missed_events = missed_events;
1567 record->ref_count = 2; /* will be returned and stored in page */
1556 1568
1557 ptr += length; 1569 ptr += length;
1558 1570
@@ -1561,7 +1573,6 @@ read_again:
1561 1573
1562 record->record_size = handle->cpu_data[cpu].index - index; 1574 record->record_size = handle->cpu_data[cpu].index - index;
1563 record->private = page; 1575 record->private = page;
1564 record->locked = 1;
1565 page->ref_count++; 1576 page->ref_count++;
1566 1577
1567 return record; 1578 return record;
@@ -1585,7 +1596,7 @@ tracecmd_read_data(struct tracecmd_input *handle, int cpu)
1585 record = tracecmd_peek_data(handle, cpu); 1596 record = tracecmd_peek_data(handle, cpu);
1586 handle->cpu_data[cpu].next = NULL; 1597 handle->cpu_data[cpu].next = NULL;
1587 if (record) 1598 if (record)
1588 record->locked = 0; 1599 record->ref_count--;
1589 1600
1590 return record; 1601 return record;
1591} 1602}
@@ -1627,6 +1638,7 @@ tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu)
1627 ts = record->ts; 1638 ts = record->ts;
1628 next = cpu; 1639 next = cpu;
1629 } 1640 }
1641 free_record(record);
1630 } 1642 }
1631 1643
1632 if (next >= 0) { 1644 if (next >= 0) {
@@ -1647,13 +1659,12 @@ tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu)
1647 * @record is the first record, NULL is returned. The cursor is set 1659 * @record is the first record, NULL is returned. The cursor is set
1648 * as if the previous record was read by tracecmd_read_data(). 1660 * as if the previous record was read by tracecmd_read_data().
1649 * 1661 *
1650 * @record can not be NULL, otherwise NULL is returned. 1662 * @record can not be NULL, otherwise NULL is returned; the
1663 * record ownership goes to this function.
1651 * 1664 *
1652 * Note, this is not that fast of an algorithm, since it needs 1665 * Note, this is not that fast of an algorithm, since it needs
1653 * to build the timestamp for the record. 1666 * to build the timestamp for the record.
1654 * 1667 *
1655 * Note 2: This may free any record allocoted with tracecmd_peek_data().
1656 *
1657 * The record returned must be freed with free_record(). 1668 * The record returned must be freed with free_record().
1658 */ 1669 */
1659struct record * 1670struct record *
@@ -1674,7 +1685,7 @@ tracecmd_read_prev(struct tracecmd_input *handle, struct record *record)
1674 page_offset = calc_page_offset(handle, offset); 1685 page_offset = calc_page_offset(handle, offset);
1675 index = offset - page_offset; 1686 index = offset - page_offset;
1676 1687
1677 /* Note, the record passed in could have been a peek */ 1688 free_record(record);
1678 free_next(handle, cpu); 1689 free_next(handle, cpu);
1679 1690
1680 /* Reset the cursor */ 1691 /* Reset the cursor */
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c
index 50d720b..fdfbdf7 100644
--- a/trace-plot-cpu.c
+++ b/trace-plot-cpu.c
@@ -137,7 +137,7 @@ static int cpu_plot_display_last_event(struct graph_info *ginfo,
137 record = tracecmd_peek_data(ginfo->handle, cpu); 137 record = tracecmd_peek_data(ginfo->handle, cpu);
138 if (record) 138 if (record)
139 offset = record->offset; 139 offset = record->offset;
140 /* Don't need to free a peek */ 140 free_record(record);
141 141
142 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time); 142 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
143 143
diff --git a/trace-plot-task.c b/trace-plot-task.c
index 0c9f8e0..71fa731 100644
--- a/trace-plot-task.c
+++ b/trace-plot-task.c
@@ -183,6 +183,7 @@ static struct offset_cache *save_offsets(struct graph_info *ginfo)
183 record = tracecmd_peek_data(ginfo->handle, cpu); 183 record = tracecmd_peek_data(ginfo->handle, cpu);
184 if (record) 184 if (record)
185 offsets->offsets[cpu] = record->offset; 185 offsets->offsets[cpu] = record->offset;
186 free_record(record);
186 } 187 }
187 188
188 return offsets; 189 return offsets;