@@ -477,7 +477,7 @@ static inline void free_bufs(odp_packet_hdr_t *pkt_hdr, int first, int num)
for (i = 0, nfree = 0; i < num; i++) {
odp_packet_hdr_t *hdr = pkt_hdr->buf_hdr.seg[first + i].hdr;
- if (packet_ref_dec(hdr) == 1)
+ if (packet_ref_count(hdr) == 1 || packet_ref_dec(hdr) == 1)
buf[nfree++] = buffer_handle(hdr);
}
@@ -499,7 +499,8 @@ static inline odp_packet_hdr_t *free_segments(odp_packet_hdr_t *pkt_hdr,
for (i = 0, nfree = 0; i < num; i++) {
new_hdr = pkt_hdr->buf_hdr.seg[i].hdr;
- if (packet_ref_dec(new_hdr) == 1)
+ if (packet_ref_count(new_hdr) == 1 ||
+ packet_ref_dec(new_hdr) == 1)
buf[nfree++] = buffer_handle(new_hdr);
}
@@ -643,12 +644,12 @@ static inline odp_packet_hdr_t *packet_free_to_list(odp_packet_hdr_t *pkt_hdr,
int num_seg, i;
do {
- ref_count = packet_ref_count(pkt_hdr) - 1;
+ ref_count = packet_ref_count(pkt_hdr);
num_seg = pkt_hdr->buf_hdr.segcount;
ref_hdr = pkt_hdr->ref_hdr;
if (odp_likely((CONFIG_PACKET_MAX_SEGS == 1 || num_seg == 1) &&
- ref_count == 0)) {
+ ref_count == 1)) {
if (*nfree >= nbufs)
break;
@@ -661,11 +662,12 @@ static inline odp_packet_hdr_t *packet_free_to_list(odp_packet_hdr_t *pkt_hdr,
odp_packet_hdr_t *hdr =
pkt_hdr->buf_hdr.seg[i].hdr;
- if (packet_ref_dec(hdr) == 1)
+ if (packet_ref_count(hdr) == 1 ||
+ packet_ref_dec(hdr) == 1)
buf[(*nfree)++] = buffer_handle(hdr);
}
- if (ref_count == 1)
+ if (ref_count == 2)
pkt_hdr->unshared_len = pkt_hdr->frame_len;
}
@@ -682,18 +684,18 @@ static inline void packet_free(odp_packet_hdr_t *pkt_hdr)
int num_seg;
do {
- ref_count = packet_ref_count(pkt_hdr) - 1;
+ ref_count = packet_ref_count(pkt_hdr);
num_seg = pkt_hdr->buf_hdr.segcount;
ref_hdr = pkt_hdr->ref_hdr;
if (odp_likely((CONFIG_PACKET_MAX_SEGS == 1 || num_seg == 1) &&
- ref_count == 0)) {
+ ref_count == 1)) {
buffer_free_multi((odp_buffer_t *)
&pkt_hdr->buf_hdr.handle.handle, 1);
} else {
free_bufs(pkt_hdr, 0, num_seg);
- if (ref_count == 1)
+ if (ref_count == 2)
pkt_hdr->unshared_len = pkt_hdr->frame_len;
}
While reference counts are implemented as atomics, try to avoid unnecessary atomic decrement operations in free paths. This streamlines free processing in the expected case where packets do not contain shared segments. Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org> --- Changes for v2 - avoid potential race condition in decrement processing platform/linux-generic/odp_packet.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) -- 2.12.0.rc1