2 * lttng-filter-validator.c
4 * LTTng UST filter bytecode validator.
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "lttng-filter.h"
28 #include <urcu/rculfhash.h>
29 #include "lttng-hash-helper.h"
31 /* merge point table node */
33 struct cds_lfht_node node
;
35 /* Context at merge point */
36 struct vreg reg
[NR_REG
];
37 unsigned long target_pc
;
40 static unsigned long lttng_hash_seed
;
41 static unsigned int lttng_hash_seed_ready
;
44 int lttng_hash_match(struct cds_lfht_node
*node
, const void *key
)
46 struct lfht_mp_node
*mp_node
=
47 caa_container_of(node
, struct lfht_mp_node
, node
);
48 unsigned long key_pc
= (unsigned long) key
;
50 if (mp_node
->target_pc
== key_pc
)
57 int merge_point_add(struct cds_lfht
*ht
, unsigned long target_pc
,
58 const struct vreg reg
[NR_REG
])
60 struct lfht_mp_node
*node
;
61 unsigned long hash
= lttng_hash_mix((const void *) target_pc
,
65 dbg_printf("Filter: adding merge point at offset %lu, hash %lu\n",
67 node
= zmalloc(sizeof(struct lfht_mp_node
));
70 node
->target_pc
= target_pc
;
71 memcpy(node
->reg
, reg
, sizeof(node
->reg
));
72 cds_lfht_add(ht
, hash
, &node
->node
);
77 * Number of merge points for hash table size. Hash table initialized to
78 * that size, and we do not resize, because we do not want to trigger
79 * RCU worker thread execution: fall-back on linear traversal if number
80 * of merge points exceeds this value.
82 #define DEFAULT_NR_MERGE_POINTS 128
83 #define MIN_NR_BUCKETS 128
84 #define MAX_NR_BUCKETS 128
87 int bin_op_compare_check(const struct vreg reg
[NR_REG
], const char *str
)
89 switch (reg
[REG_R0
].type
) {
94 switch (reg
[REG_R1
].type
) {
107 switch (reg
[REG_R1
].type
) {
126 ERR("type mismatch for '%s' binary operator\n", str
);
131 * Validate bytecode range overflow within the validation pass.
132 * Called for each instruction encountered.
135 int bytecode_validate_overflow(struct bytecode_runtime
*bytecode
,
136 void *start_pc
, void *pc
)
140 switch (*(filter_opcode_t
*) pc
) {
141 case FILTER_OP_UNKNOWN
:
144 ERR("unknown bytecode op %u\n",
145 (unsigned int) *(filter_opcode_t
*) pc
);
150 case FILTER_OP_RETURN
:
152 if (unlikely(pc
+ sizeof(struct return_op
)
153 > start_pc
+ bytecode
->len
)) {
164 case FILTER_OP_MINUS
:
165 case FILTER_OP_RSHIFT
:
166 case FILTER_OP_LSHIFT
:
167 case FILTER_OP_BIN_AND
:
168 case FILTER_OP_BIN_OR
:
169 case FILTER_OP_BIN_XOR
:
171 ERR("unsupported bytecode op %u\n",
172 (unsigned int) *(filter_opcode_t
*) pc
);
183 case FILTER_OP_EQ_STRING
:
184 case FILTER_OP_NE_STRING
:
185 case FILTER_OP_GT_STRING
:
186 case FILTER_OP_LT_STRING
:
187 case FILTER_OP_GE_STRING
:
188 case FILTER_OP_LE_STRING
:
189 case FILTER_OP_EQ_S64
:
190 case FILTER_OP_NE_S64
:
191 case FILTER_OP_GT_S64
:
192 case FILTER_OP_LT_S64
:
193 case FILTER_OP_GE_S64
:
194 case FILTER_OP_LE_S64
:
195 case FILTER_OP_EQ_DOUBLE
:
196 case FILTER_OP_NE_DOUBLE
:
197 case FILTER_OP_GT_DOUBLE
:
198 case FILTER_OP_LT_DOUBLE
:
199 case FILTER_OP_GE_DOUBLE
:
200 case FILTER_OP_LE_DOUBLE
:
202 if (unlikely(pc
+ sizeof(struct binary_op
)
203 > start_pc
+ bytecode
->len
)) {
210 case FILTER_OP_UNARY_PLUS
:
211 case FILTER_OP_UNARY_MINUS
:
212 case FILTER_OP_UNARY_NOT
:
213 case FILTER_OP_UNARY_PLUS_S64
:
214 case FILTER_OP_UNARY_MINUS_S64
:
215 case FILTER_OP_UNARY_NOT_S64
:
216 case FILTER_OP_UNARY_PLUS_DOUBLE
:
217 case FILTER_OP_UNARY_MINUS_DOUBLE
:
218 case FILTER_OP_UNARY_NOT_DOUBLE
:
220 if (unlikely(pc
+ sizeof(struct unary_op
)
221 > start_pc
+ bytecode
->len
)) {
231 if (unlikely(pc
+ sizeof(struct logical_op
)
232 > start_pc
+ bytecode
->len
)) {
239 case FILTER_OP_LOAD_FIELD_REF
:
241 ERR("Unknown field ref type\n");
245 case FILTER_OP_LOAD_FIELD_REF_STRING
:
246 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
247 case FILTER_OP_LOAD_FIELD_REF_S64
:
248 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
250 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct field_ref
)
251 > start_pc
+ bytecode
->len
)) {
257 case FILTER_OP_LOAD_STRING
:
259 struct load_op
*insn
= (struct load_op
*) pc
;
260 uint32_t str_len
, maxlen
;
262 if (unlikely(pc
+ sizeof(struct load_op
)
263 > start_pc
+ bytecode
->len
)) {
268 maxlen
= start_pc
+ bytecode
->len
- pc
- sizeof(struct load_op
);
269 str_len
= strnlen(insn
->data
, maxlen
);
270 if (unlikely(str_len
>= maxlen
)) {
271 /* Final '\0' not found within range */
277 case FILTER_OP_LOAD_S64
:
279 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_numeric
)
280 > start_pc
+ bytecode
->len
)) {
286 case FILTER_OP_LOAD_DOUBLE
:
288 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_double
)
289 > start_pc
+ bytecode
->len
)) {
295 case FILTER_OP_CAST_TO_S64
:
296 case FILTER_OP_CAST_DOUBLE_TO_S64
:
297 case FILTER_OP_CAST_NOP
:
299 if (unlikely(pc
+ sizeof(struct cast_op
)
300 > start_pc
+ bytecode
->len
)) {
311 unsigned long delete_all_nodes(struct cds_lfht
*ht
)
313 struct cds_lfht_iter iter
;
314 struct lfht_mp_node
*node
;
315 unsigned long nr_nodes
= 0;
317 cds_lfht_for_each_entry(ht
, &iter
, node
, node
) {
320 ret
= cds_lfht_del(ht
, cds_lfht_iter_get_node(&iter
));
322 /* note: this hash table is never used concurrently */
335 int validate_instruction_context(struct bytecode_runtime
*bytecode
,
336 const struct vreg reg
[NR_REG
],
342 switch (*(filter_opcode_t
*) pc
) {
343 case FILTER_OP_UNKNOWN
:
346 ERR("unknown bytecode op %u\n",
347 (unsigned int) *(filter_opcode_t
*) pc
);
352 case FILTER_OP_RETURN
:
362 case FILTER_OP_MINUS
:
363 case FILTER_OP_RSHIFT
:
364 case FILTER_OP_LSHIFT
:
365 case FILTER_OP_BIN_AND
:
366 case FILTER_OP_BIN_OR
:
367 case FILTER_OP_BIN_XOR
:
369 ERR("unsupported bytecode op %u\n",
370 (unsigned int) *(filter_opcode_t
*) pc
);
377 ret
= bin_op_compare_check(reg
, "==");
384 ret
= bin_op_compare_check(reg
, "!=");
391 ret
= bin_op_compare_check(reg
, ">");
398 ret
= bin_op_compare_check(reg
, "<");
405 ret
= bin_op_compare_check(reg
, ">=");
412 ret
= bin_op_compare_check(reg
, "<=");
418 case FILTER_OP_EQ_STRING
:
419 case FILTER_OP_NE_STRING
:
420 case FILTER_OP_GT_STRING
:
421 case FILTER_OP_LT_STRING
:
422 case FILTER_OP_GE_STRING
:
423 case FILTER_OP_LE_STRING
:
425 if (reg
[REG_R0
].type
!= REG_STRING
426 || reg
[REG_R1
].type
!= REG_STRING
) {
427 ERR("Unexpected register type for string comparator\n");
434 case FILTER_OP_EQ_S64
:
435 case FILTER_OP_NE_S64
:
436 case FILTER_OP_GT_S64
:
437 case FILTER_OP_LT_S64
:
438 case FILTER_OP_GE_S64
:
439 case FILTER_OP_LE_S64
:
441 if (reg
[REG_R0
].type
!= REG_S64
442 || reg
[REG_R1
].type
!= REG_S64
) {
443 ERR("Unexpected register type for s64 comparator\n");
450 case FILTER_OP_EQ_DOUBLE
:
451 case FILTER_OP_NE_DOUBLE
:
452 case FILTER_OP_GT_DOUBLE
:
453 case FILTER_OP_LT_DOUBLE
:
454 case FILTER_OP_GE_DOUBLE
:
455 case FILTER_OP_LE_DOUBLE
:
457 if ((reg
[REG_R0
].type
!= REG_DOUBLE
&& reg
[REG_R0
].type
!= REG_S64
)
458 || (reg
[REG_R1
].type
!= REG_DOUBLE
&& reg
[REG_R1
].type
!= REG_S64
)) {
459 ERR("Unexpected register type for double comparator\n");
463 if (reg
[REG_R0
].type
!= REG_DOUBLE
&& reg
[REG_R1
].type
!= REG_DOUBLE
) {
464 ERR("Double operator should have at least one double register\n");
472 case FILTER_OP_UNARY_PLUS
:
473 case FILTER_OP_UNARY_MINUS
:
474 case FILTER_OP_UNARY_NOT
:
476 struct unary_op
*insn
= (struct unary_op
*) pc
;
478 if (unlikely(insn
->reg
>= REG_ERROR
)) {
479 ERR("invalid register %u\n",
480 (unsigned int) insn
->reg
);
484 switch (reg
[insn
->reg
].type
) {
486 ERR("unknown register type\n");
491 ERR("Unary op can only be applied to numeric or floating point registers\n");
502 case FILTER_OP_UNARY_PLUS_S64
:
503 case FILTER_OP_UNARY_MINUS_S64
:
504 case FILTER_OP_UNARY_NOT_S64
:
506 struct unary_op
*insn
= (struct unary_op
*) pc
;
508 if (unlikely(insn
->reg
>= REG_ERROR
)) {
509 ERR("invalid register %u\n",
510 (unsigned int) insn
->reg
);
514 if (reg
[insn
->reg
].type
!= REG_S64
) {
515 ERR("Invalid register type\n");
522 case FILTER_OP_UNARY_PLUS_DOUBLE
:
523 case FILTER_OP_UNARY_MINUS_DOUBLE
:
524 case FILTER_OP_UNARY_NOT_DOUBLE
:
526 struct unary_op
*insn
= (struct unary_op
*) pc
;
528 if (unlikely(insn
->reg
>= REG_ERROR
)) {
529 ERR("invalid register %u\n",
530 (unsigned int) insn
->reg
);
534 if (reg
[insn
->reg
].type
!= REG_DOUBLE
) {
535 ERR("Invalid register type\n");
546 struct logical_op
*insn
= (struct logical_op
*) pc
;
548 if (reg
[REG_R0
].type
!= REG_S64
) {
549 ERR("Logical comparator expects S64 register\n");
554 dbg_printf("Validate jumping to bytecode offset %u\n",
555 (unsigned int) insn
->skip_offset
);
556 if (unlikely(start_pc
+ insn
->skip_offset
<= pc
)) {
557 ERR("Loops are not allowed in bytecode\n");
565 case FILTER_OP_LOAD_FIELD_REF
:
567 ERR("Unknown field ref type\n");
571 case FILTER_OP_LOAD_FIELD_REF_STRING
:
572 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
574 struct load_op
*insn
= (struct load_op
*) pc
;
575 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
577 if (unlikely(insn
->reg
>= REG_ERROR
)) {
578 ERR("invalid register %u\n",
579 (unsigned int) insn
->reg
);
583 dbg_printf("Validate load field ref offset %u type string\n",
587 case FILTER_OP_LOAD_FIELD_REF_S64
:
589 struct load_op
*insn
= (struct load_op
*) pc
;
590 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
592 if (unlikely(insn
->reg
>= REG_ERROR
)) {
593 ERR("invalid register %u\n",
594 (unsigned int) insn
->reg
);
598 dbg_printf("Validate load field ref offset %u type s64\n",
602 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
604 struct load_op
*insn
= (struct load_op
*) pc
;
605 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
607 if (unlikely(insn
->reg
>= REG_ERROR
)) {
608 ERR("invalid register %u\n",
609 (unsigned int) insn
->reg
);
613 dbg_printf("Validate load field ref offset %u type double\n",
618 case FILTER_OP_LOAD_STRING
:
620 struct load_op
*insn
= (struct load_op
*) pc
;
622 if (unlikely(insn
->reg
>= REG_ERROR
)) {
623 ERR("invalid register %u\n",
624 (unsigned int) insn
->reg
);
631 case FILTER_OP_LOAD_S64
:
633 struct load_op
*insn
= (struct load_op
*) pc
;
635 if (unlikely(insn
->reg
>= REG_ERROR
)) {
636 ERR("invalid register %u\n",
637 (unsigned int) insn
->reg
);
644 case FILTER_OP_LOAD_DOUBLE
:
646 struct load_op
*insn
= (struct load_op
*) pc
;
648 if (unlikely(insn
->reg
>= REG_ERROR
)) {
649 ERR("invalid register %u\n",
650 (unsigned int) insn
->reg
);
657 case FILTER_OP_CAST_TO_S64
:
658 case FILTER_OP_CAST_DOUBLE_TO_S64
:
660 struct cast_op
*insn
= (struct cast_op
*) pc
;
662 if (unlikely(insn
->reg
>= REG_ERROR
)) {
663 ERR("invalid register %u\n",
664 (unsigned int) insn
->reg
);
668 switch (reg
[insn
->reg
].type
) {
670 ERR("unknown register type\n");
675 ERR("Cast op can only be applied to numeric or floating point registers\n");
683 if (insn
->op
== FILTER_OP_CAST_DOUBLE_TO_S64
) {
684 if (reg
[insn
->reg
].type
!= REG_DOUBLE
) {
685 ERR("Cast expects double\n");
692 case FILTER_OP_CAST_NOP
:
708 int validate_instruction_all_contexts(struct bytecode_runtime
*bytecode
,
709 struct cds_lfht
*merge_points
,
710 const struct vreg reg
[NR_REG
],
715 unsigned long target_pc
= pc
- start_pc
;
716 struct cds_lfht_iter iter
;
717 struct cds_lfht_node
*node
;
720 /* Validate the context resulting from the previous instruction */
721 ret
= validate_instruction_context(bytecode
, reg
, start_pc
, pc
);
725 /* Validate merge points */
726 hash
= lttng_hash_mix((const void *) target_pc
, sizeof(target_pc
),
728 cds_lfht_for_each_duplicate(merge_points
, hash
, lttng_hash_match
,
729 (const void *) target_pc
, &iter
, node
) {
730 struct lfht_mp_node
*mp_node
=
731 caa_container_of(node
, struct lfht_mp_node
, node
);
733 dbg_printf("Filter: validate merge point at offset %lu\n",
735 ret
= validate_instruction_context(bytecode
, mp_node
->reg
,
739 /* Once validated, we can remove the merge point */
740 dbg_printf("Filter: remove one merge point at offset %lu\n",
742 ret
= cds_lfht_del(merge_points
, node
);
750 * >0: going to next insn.
751 * 0: success, stop iteration.
755 int exec_insn(struct bytecode_runtime
*bytecode
,
756 struct cds_lfht
*merge_points
,
757 struct vreg reg
[NR_REG
],
762 void *next_pc
= *_next_pc
;
764 switch (*(filter_opcode_t
*) pc
) {
765 case FILTER_OP_UNKNOWN
:
768 ERR("unknown bytecode op %u\n",
769 (unsigned int) *(filter_opcode_t
*) pc
);
774 case FILTER_OP_RETURN
:
785 case FILTER_OP_MINUS
:
786 case FILTER_OP_RSHIFT
:
787 case FILTER_OP_LSHIFT
:
788 case FILTER_OP_BIN_AND
:
789 case FILTER_OP_BIN_OR
:
790 case FILTER_OP_BIN_XOR
:
792 ERR("unsupported bytecode op %u\n",
793 (unsigned int) *(filter_opcode_t
*) pc
);
804 case FILTER_OP_EQ_STRING
:
805 case FILTER_OP_NE_STRING
:
806 case FILTER_OP_GT_STRING
:
807 case FILTER_OP_LT_STRING
:
808 case FILTER_OP_GE_STRING
:
809 case FILTER_OP_LE_STRING
:
810 case FILTER_OP_EQ_S64
:
811 case FILTER_OP_NE_S64
:
812 case FILTER_OP_GT_S64
:
813 case FILTER_OP_LT_S64
:
814 case FILTER_OP_GE_S64
:
815 case FILTER_OP_LE_S64
:
817 reg
[REG_R0
].type
= REG_S64
;
818 next_pc
+= sizeof(struct binary_op
);
822 case FILTER_OP_EQ_DOUBLE
:
823 case FILTER_OP_NE_DOUBLE
:
824 case FILTER_OP_GT_DOUBLE
:
825 case FILTER_OP_LT_DOUBLE
:
826 case FILTER_OP_GE_DOUBLE
:
827 case FILTER_OP_LE_DOUBLE
:
829 reg
[REG_R0
].type
= REG_DOUBLE
;
830 next_pc
+= sizeof(struct binary_op
);
835 case FILTER_OP_UNARY_PLUS
:
836 case FILTER_OP_UNARY_MINUS
:
837 case FILTER_OP_UNARY_NOT
:
838 case FILTER_OP_UNARY_PLUS_S64
:
839 case FILTER_OP_UNARY_MINUS_S64
:
840 case FILTER_OP_UNARY_NOT_S64
:
842 reg
[REG_R0
].type
= REG_S64
;
843 next_pc
+= sizeof(struct unary_op
);
847 case FILTER_OP_UNARY_PLUS_DOUBLE
:
848 case FILTER_OP_UNARY_MINUS_DOUBLE
:
849 case FILTER_OP_UNARY_NOT_DOUBLE
:
851 reg
[REG_R0
].type
= REG_DOUBLE
;
852 next_pc
+= sizeof(struct unary_op
);
860 struct logical_op
*insn
= (struct logical_op
*) pc
;
863 /* Add merge point to table */
864 merge_ret
= merge_point_add(merge_points
, insn
->skip_offset
, reg
);
869 /* Continue to next instruction */
870 next_pc
+= sizeof(struct logical_op
);
875 case FILTER_OP_LOAD_FIELD_REF
:
877 ERR("Unknown field ref type\n");
881 case FILTER_OP_LOAD_FIELD_REF_STRING
:
882 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
884 struct load_op
*insn
= (struct load_op
*) pc
;
886 reg
[insn
->reg
].type
= REG_STRING
;
887 reg
[insn
->reg
].literal
= 0;
888 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
891 case FILTER_OP_LOAD_FIELD_REF_S64
:
893 struct load_op
*insn
= (struct load_op
*) pc
;
895 reg
[insn
->reg
].type
= REG_S64
;
896 reg
[insn
->reg
].literal
= 0;
897 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
900 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
902 struct load_op
*insn
= (struct load_op
*) pc
;
904 reg
[insn
->reg
].type
= REG_DOUBLE
;
905 reg
[insn
->reg
].literal
= 0;
906 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
910 case FILTER_OP_LOAD_STRING
:
912 struct load_op
*insn
= (struct load_op
*) pc
;
914 reg
[insn
->reg
].type
= REG_STRING
;
915 reg
[insn
->reg
].literal
= 1;
916 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
920 case FILTER_OP_LOAD_S64
:
922 struct load_op
*insn
= (struct load_op
*) pc
;
924 reg
[insn
->reg
].type
= REG_S64
;
925 reg
[insn
->reg
].literal
= 1;
926 next_pc
+= sizeof(struct load_op
)
927 + sizeof(struct literal_numeric
);
931 case FILTER_OP_LOAD_DOUBLE
:
933 struct load_op
*insn
= (struct load_op
*) pc
;
935 reg
[insn
->reg
].type
= REG_DOUBLE
;
936 reg
[insn
->reg
].literal
= 1;
937 next_pc
+= sizeof(struct load_op
)
938 + sizeof(struct literal_double
);
942 case FILTER_OP_CAST_TO_S64
:
943 case FILTER_OP_CAST_DOUBLE_TO_S64
:
945 struct cast_op
*insn
= (struct cast_op
*) pc
;
947 reg
[insn
->reg
].type
= REG_S64
;
948 next_pc
+= sizeof(struct cast_op
);
951 case FILTER_OP_CAST_NOP
:
953 next_pc
+= sizeof(struct cast_op
);
964 * Never called concurrently (hash seed is shared).
966 int lttng_filter_validate_bytecode(struct bytecode_runtime
*bytecode
)
968 struct cds_lfht
*merge_points
;
969 void *pc
, *next_pc
, *start_pc
;
971 struct vreg reg
[NR_REG
];
974 for (i
= 0; i
< NR_REG
; i
++) {
975 reg
[i
].type
= REG_TYPE_UNKNOWN
;
979 if (!lttng_hash_seed_ready
) {
980 lttng_hash_seed
= time(NULL
);
981 lttng_hash_seed_ready
= 1;
984 * Note: merge_points hash table used by single thread, and
985 * never concurrently resized. Therefore, we can use it without
986 * holding RCU read-side lock and free nodes without using
989 merge_points
= cds_lfht_new(DEFAULT_NR_MERGE_POINTS
,
990 MIN_NR_BUCKETS
, MAX_NR_BUCKETS
,
993 ERR("Error allocating hash table for bytecode validation\n");
996 start_pc
= &bytecode
->data
[0];
997 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
999 if (bytecode_validate_overflow(bytecode
, start_pc
, pc
) != 0) {
1000 ERR("filter bytecode overflow\n");
1004 dbg_printf("Validating op %s (%u)\n",
1005 print_op((unsigned int) *(filter_opcode_t
*) pc
),
1006 (unsigned int) *(filter_opcode_t
*) pc
);
1009 * For each instruction, validate the current context
1010 * (traversal of entire execution flow), and validate
1011 * all merge points targeting this instruction.
1013 ret
= validate_instruction_all_contexts(bytecode
, merge_points
,
1017 ret
= exec_insn(bytecode
, merge_points
, reg
, &next_pc
, pc
);
1022 if (delete_all_nodes(merge_points
)) {
1024 ERR("Unexpected merge points\n");
1028 if (cds_lfht_destroy(merge_points
, NULL
)) {
1029 ERR("Error destroying hash table\n");