@@ -64,7 +64,9 @@ typedef struct {
struct pktio_entry {
const struct pktio_if_ops *ops; /**< Implementation specific methods */
- odp_ticketlock_t lock; /**< entry ticketlock */
+ /* These two locks together lock the whole pktio device */
+ odp_ticketlock_t rxl; /**< RX ticketlock */
+ odp_ticketlock_t txl; /**< TX ticketlock */
int taken; /**< is entry taken(1) or free(0) */
int cls_enabled; /**< is classifier enabled */
odp_pktio_t handle; /**< pktio handle */
@@ -55,7 +55,8 @@ int odp_pktio_init_global(void)
for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
pktio_entry = &pktio_tbl->entries[id - 1];
- odp_ticketlock_init(&pktio_entry->s.lock);
+ odp_ticketlock_init(&pktio_entry->s.rxl);
+ odp_ticketlock_init(&pktio_entry->s.txl);
odp_spinlock_init(&pktio_entry->s.cls.lock);
odp_spinlock_init(&pktio_entry->s.cls.l2_cos_table.lock);
odp_spinlock_init(&pktio_entry->s.cls.l3_cos_table.lock);
@@ -106,24 +107,28 @@ static void set_taken(pktio_entry_t *entry)
static void lock_entry(pktio_entry_t *entry)
{
- odp_ticketlock_lock(&entry->s.lock);
+ odp_ticketlock_lock(&entry->s.rxl);
+ odp_ticketlock_lock(&entry->s.txl);
}
static void unlock_entry(pktio_entry_t *entry)
{
- odp_ticketlock_unlock(&entry->s.lock);
+ odp_ticketlock_unlock(&entry->s.txl);
+ odp_ticketlock_unlock(&entry->s.rxl);
}
static void lock_entry_classifier(pktio_entry_t *entry)
{
- odp_ticketlock_lock(&entry->s.lock);
+ odp_ticketlock_lock(&entry->s.rxl);
+ odp_ticketlock_lock(&entry->s.txl);
odp_spinlock_lock(&entry->s.cls.lock);
}
static void unlock_entry_classifier(pktio_entry_t *entry)
{
odp_spinlock_unlock(&entry->s.cls.lock);
- odp_ticketlock_unlock(&entry->s.lock);
+ odp_ticketlock_unlock(&entry->s.txl);
+ odp_ticketlock_unlock(&entry->s.rxl);
}
static void init_pktio_entry(pktio_entry_t *entry)
@@ -385,15 +390,15 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], int len)
if (pktio_entry == NULL)
return -1;
- lock_entry(pktio_entry);
+ odp_ticketlock_lock(&pktio_entry->s.rxl);
if (pktio_entry->s.state == STATE_STOP ||
pktio_entry->s.param.in_mode == ODP_PKTIN_MODE_DISABLED) {
- unlock_entry(pktio_entry);
+ odp_ticketlock_unlock(&pktio_entry->s.rxl);
__odp_errno = EPERM;
return -1;
}
pkts = pktio_entry->s.ops->recv(pktio_entry, pkt_table, len);
- unlock_entry(pktio_entry);
+ odp_ticketlock_unlock(&pktio_entry->s.rxl);
if (pkts < 0)
return pkts;
@@ -412,15 +417,15 @@ int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], int len)
if (pktio_entry == NULL)
return -1;
- lock_entry(pktio_entry);
+ odp_ticketlock_lock(&pktio_entry->s.txl);
if (pktio_entry->s.state == STATE_STOP ||
pktio_entry->s.param.out_mode == ODP_PKTOUT_MODE_DISABLED) {
- unlock_entry(pktio_entry);
+ odp_ticketlock_unlock(&pktio_entry->s.txl);
__odp_errno = EPERM;
return -1;
}
pkts = pktio_entry->s.ops->send(pktio_entry, pkt_table, len);
- unlock_entry(pktio_entry);
+ odp_ticketlock_unlock(&pktio_entry->s.txl);
return pkts;
}
It's possible that two threads want to use the same packet IO in the same time, but one wants RX while the other wants TX. In this case they would block each other unnecessary on the same lock. This could be seen e.g. with odp_l2fwd. Replace that lock with two new ones for each direction. Most callers need both, but send and receive can work with only one. Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org> --- .../linux-generic/include/odp_packet_io_internal.h | 4 +++- platform/linux-generic/odp_packet_io.c | 27 +++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-)