discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=6353a699e3161bc2a6a962e76cffc7257b250da0

commit 6353a699e3161bc2a6a962e76cffc7257b250da0
Author: Mike Blumenkrantz <[email protected]>
Date:   Tue Jun 19 13:30:44 2018 -0400

    eina_threadqueue: add locking for variable used between threads
    
    Summary:
    the 'first' member of this struct is used simultaneously across
    threads and can have conflicting read/write operations occurring at this
    time
    
    as int operations are not guaranteed to be atomic, ensure that we are
    using atomic operations or locking as necessary
    
    @fix
    
    Depends on D6299
    
    Reviewers: ManMower, devilhorns
    
    Reviewed By: ManMower
    
    Subscribers: cedric, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D6300
---
 src/lib/eina/eina_thread_queue.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/src/lib/eina/eina_thread_queue.c b/src/lib/eina/eina_thread_queue.c
index 7ceb663376..531800dac7 100644
--- a/src/lib/eina/eina_thread_queue.c
+++ b/src/lib/eina/eina_thread_queue.c
@@ -57,6 +57,7 @@ struct _Eina_Thread_Queue_Msg_Block
    Eina_Lock                     lock_non_0_ref; // block non-0 ref state
 #ifndef ATOMIC
    Eina_Spinlock                 lock_ref; // lock for ref field
+   Eina_Spinlock                 lock_first; // lock for first field
 #endif
    int                           ref; // the number of open reads/writes
    int                           size; // the total allocated bytes of data[]
@@ -124,6 +125,7 @@ _eina_thread_queue_msg_block_new(int size)
    blk->next = NULL;
 #ifndef ATOMIC
    eina_spinlock_new(&(blk->lock_ref));
+   eina_spinlock_new(&(blk->lock_first));
 #endif
    eina_lock_new(&(blk->lock_non_0_ref));
    blk->size = size;
@@ -144,6 +146,9 @@ 
_eina_thread_queue_msg_block_real_free(Eina_Thread_Queue_Msg_Block *blk)
    eina_spinlock_take(&(blk->lock_ref));
    eina_spinlock_release(&(blk->lock_ref));
    eina_spinlock_free(&(blk->lock_ref));
+   eina_spinlock_take(&(blk->lock_first));
+   eina_spinlock_release(&(blk->lock_first));
+   eina_spinlock_free(&(blk->lock_first));
 #endif
    free(blk);
 }
@@ -294,7 +299,7 @@ _eina_thread_queue_msg_fetch(Eina_Thread_Queue *thq, 
Eina_Thread_Queue_Msg_Block
 {
    Eina_Thread_Queue_Msg_Block *blk;
    Eina_Thread_Queue_Msg *msg;
-   int ref;
+   int ref, first;
 
    if (!thq->read)
      {
@@ -321,9 +326,17 @@ _eina_thread_queue_msg_fetch(Eina_Thread_Queue *thq, 
Eina_Thread_Queue_Msg_Block
         RWLOCK_UNLOCK(&(thq->lock_write));
      }
    blk = thq->read;
+#ifdef ATOMIC
+   __atomic_load(&blk->first, &first, __ATOMIC_RELAXED);
+   msg = (Eina_Thread_Queue_Msg *)((char *)(&(blk->data[0])) + first);
+   first = __atomic_add_fetch(&(blk->first), msg->size, __ATOMIC_RELAXED);
+#else
+   eina_spinlock_take(&blk->lock_first);
    msg = (Eina_Thread_Queue_Msg *)((char *)(&(blk->data[0])) + blk->first);
-   blk->first += msg->size;
-   if (blk->first >= blk->last) thq->read = NULL;
+   first = blk->first += msg->size;
+   eina_spinlock_release(&blk->lock_first);
+#endif
+   if (first >= blk->last) thq->read = NULL;
    *blkret = blk;
 #ifdef ATOMIC
    __atomic_add_fetch(&(blk->ref), 1, __ATOMIC_RELAXED);
@@ -338,17 +351,21 @@ _eina_thread_queue_msg_fetch(Eina_Thread_Queue *thq, 
Eina_Thread_Queue_Msg_Block
 static void
 _eina_thread_queue_msg_fetch_done(Eina_Thread_Queue_Msg_Block *blk)
 {
-   int ref;
+   int ref, first;
 
 #ifdef ATOMIC
    ref = __atomic_sub_fetch(&(blk->ref), 1, __ATOMIC_RELAXED);
+   __atomic_load(&blk->first, &first, __ATOMIC_RELAXED);
 #else
    eina_spinlock_take(&(blk->lock_ref));
    blk->ref--;
    ref = blk->ref;
    eina_spinlock_release(&(blk->lock_ref));
+   eina_spinlock_take(&blk->lock_first);
+   first = blk->first;
+   eina_spinlock_release(&blk->lock_first);
 #endif
-   if ((blk->first >= blk->last) && (ref == 0))
+   if ((first >= blk->last) && (ref == 0))
      _eina_thread_queue_msg_block_free(blk);
 }
 

-- 


Reply via email to