On 21/11/2016 06:27, "Ilya Maximets" <[email protected]> wrote:

>
>
>On 16.11.2016 03:46, Daniele Di Proietto wrote:
>> There's no reason for a pmd thread to perform its main loop if there are
>> no queues in its poll_list.
>> 
>> This commit introduces a seq object on which the pmd thread can be
>> blocked, if there are no queues.
>> 
>> When the main thread wants to reload a pmd threads it must now change
>> the seq object (in case it's blocked) and set 'reload' to true.
>> 
>> This is useful to avoid wasting CPU cycles and is also necessary for a
>> future commit.
>> 
>> Signed-off-by: Daniele Di Proietto <[email protected]>
>> ---
>>  lib/dpif-netdev.c | 14 ++++++++++++++
>>  1 file changed, 14 insertions(+)
>> 
>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
>> index 23546b9..6c2ad29 100644
>> --- a/lib/dpif-netdev.c
>> +++ b/lib/dpif-netdev.c
>> @@ -485,6 +485,8 @@ struct dp_netdev_pmd_thread {
>>      unsigned long long last_cycles;
>>  
>>      struct latch exit_latch;        /* For terminating the pmd thread. */
>> +    struct seq *reload_seq;
>> +    uint64_t last_reload_seq;
>>      atomic_bool reload;             /* Do we need to reload ports? */
>>      pthread_t thread;
>>      unsigned core_id;               /* CPU core id of this pmd thread. */
>> @@ -1210,6 +1212,7 @@ dp_netdev_reload_pmd__(struct dp_netdev_pmd_thread 
>> *pmd)
>>      }
>>  
>>      ovs_mutex_lock(&pmd->cond_mutex);
>> +    seq_change(pmd->reload_seq);
>>      atomic_store_relaxed(&pmd->reload, true);
>>      ovs_mutex_cond_wait(&pmd->cond, &pmd->cond_mutex);
>>      ovs_mutex_unlock(&pmd->cond_mutex);
>> @@ -3148,6 +3151,13 @@ reload:
>>                  netdev_rxq_get_queue_id(poll_list[i].rx));
>>      }
>>  
>> +    if (!poll_cnt) {
>> +        while (seq_read(pmd->reload_seq) == pmd->last_reload_seq) {
>> +            seq_wait(pmd->reload_seq, pmd->last_reload_seq);
>> +            poll_block();
>> +        }
>> +    }
>> +
>
>How about putting the next polling loop under 'else'? This will help
>to avoid 1024 empty cycles inside of it. Or, maybe, we can just set
>'lc' to 1025 after the 'while' above.

I tried putting the polling loop under 'else', but it seems to have a
small negative performance impact, but I don't see any problem with
setting lc to 1025, so I did that.

>
>Another thought: I guess, we should enter a quiescent state before
>'while' loop and end it after.

poll_block() already handles quiescent states, I think that's enough for
our purpose.

>
>Also, I prefer to merge 'reload' and 'reload_seq' somehow, but I don't
>know how to do this yet.

That's a good point.  We could use only reload_seq, but seq_read() takes
a mutex, so it's not ideal to call it in the fast path.

We need an object that can be checked with a simple atomic_read_relaxed()
and that can be also used to block.

This (using both 'reload' and 'reload_seq') is the simplest (in terms of
lines of code) solution I came up with, but I'm open to suggestions.

Thanks

>
>>      for (;;) {
>>          for (i = 0; i < poll_cnt; i++) {
>>              dp_netdev_process_rxq_port(pmd, poll_list[i].port, 
>> poll_list[i].rx);
>> @@ -3223,6 +3233,7 @@ dp_netdev_pmd_reload_done(struct dp_netdev_pmd_thread 
>> *pmd)
>>  {
>>      ovs_mutex_lock(&pmd->cond_mutex);
>>      atomic_store_relaxed(&pmd->reload, false);
>> +    pmd->last_reload_seq = seq_read(pmd->reload_seq);
>>      xpthread_cond_signal(&pmd->cond);
>>      ovs_mutex_unlock(&pmd->cond_mutex);
>>  }
>> @@ -3317,6 +3328,8 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread 
>> *pmd, struct dp_netdev *dp,
>>  
>>      ovs_refcount_init(&pmd->ref_cnt);
>>      latch_init(&pmd->exit_latch);
>> +    pmd->reload_seq = seq_create();
>> +    pmd->last_reload_seq = seq_read(pmd->reload_seq);
>>      atomic_init(&pmd->reload, false);
>>      xpthread_cond_init(&pmd->cond, NULL);
>>      ovs_mutex_init(&pmd->cond_mutex);
>> @@ -3356,6 +3369,7 @@ dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd)
>>      cmap_destroy(&pmd->flow_table);
>>      ovs_mutex_destroy(&pmd->flow_mutex);
>>      latch_destroy(&pmd->exit_latch);
>> +    seq_destroy(pmd->reload_seq);
>>      xpthread_cond_destroy(&pmd->cond);
>>      ovs_mutex_destroy(&pmd->cond_mutex);
>>      ovs_mutex_destroy(&pmd->port_mutex);
>> 
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to