Piotr Caban : msvcp100: Add _Concurrent_queue_base_v4 push/ pop implementation.

Alexandre Julliard julliard at winehq.org
Tue Jan 23 16:09:50 CST 2018


Module: wine
Branch: master
Commit: 411e3c51c01daa3c14e62220465b8829510e7981
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=411e3c51c01daa3c14e62220465b8829510e7981

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue Jan 23 17:03:56 2018 +0100

msvcp100: Add _Concurrent_queue_base_v4 push/pop implementation.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcp90/misc.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 157 insertions(+), 5 deletions(-)

diff --git a/dlls/msvcp90/misc.c b/dlls/msvcp90/misc.c
index ca85079..b3e546a 100644
--- a/dlls/msvcp90/misc.c
+++ b/dlls/msvcp90/misc.c
@@ -1236,9 +1236,24 @@ typedef struct
 
 extern const vtable_ptr MSVCP__Concurrent_queue_base_v4_vtable;
 #if _MSVCP_VER == 100
+#define call__Concurrent_queue_base_v4__Move_item call__Concurrent_queue_base_v4__Copy_item
+#define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
+        0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
+#define  call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
+        4, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
+#define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
+        12, _Page*, (_Concurrent_queue_base_v4*), (this))
 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
         16, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
 #else
+#define call__Concurrent_queue_base_v4__Move_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
+        0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,void*), (this,dst,idx,src))
+#define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
+        4, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
+#define  call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
+        8, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
+#define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
+        16, _Page*, (_Concurrent_queue_base_v4*), (this))
 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
         20, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
 #endif
@@ -1344,13 +1359,134 @@ MSVCP_size_t __thiscall _Concurrent_queue_base_v4__Internal_size(
     return this->data->tail_pos - this->data->head_pos;
 }
 
+static void spin_wait(int *counter)
+{
+    static int spin_limit = -1;
+
+    if(spin_limit == -1)
+    {
+        SYSTEM_INFO si;
+        GetSystemInfo(&si);
+        spin_limit = si.dwNumberOfProcessors>1 ? 4000 : 0;
+    }
+
+    if(*counter >= spin_limit)
+    {
+        *counter = 0;
+        Sleep(0);
+    }
+    else
+    {
+        (*counter)++;
+    }
+}
+
+#ifdef _WIN64
+static MSVCP_size_t InterlockedIncrementSizeT(MSVCP_size_t volatile *dest)
+{
+    MSVCP_size_t v;
+
+    do
+    {
+        v = *dest;
+    } while(InterlockedCompareExchange64((LONGLONG*)dest, v+1, v) != v);
+
+    return v+1;
+}
+#else
+#define InterlockedIncrementSizeT(dest) InterlockedIncrement((LONG*)dest)
+#endif
+
+static void threadsafe_queue_push(threadsafe_queue *queue, MSVCP_size_t id,
+        void *e, _Concurrent_queue_base_v4 *parent, BOOL copy)
+{
+    MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
+    int spin;
+    _Page *p;
+
+    spin = 0;
+    while(queue->tail_pos != id)
+        spin_wait(&spin);
+
+    if(page_id == id)
+    {
+        /* TODO: Add exception handling */
+        p = call__Concurrent_queue_base_v4__Allocate_page(parent);
+        p->_Next = NULL;
+        p->_Mask = 0;
+
+        spin = 0;
+        while(InterlockedCompareExchange(&queue->lock, 1, 0))
+            spin_wait(&spin);
+        if(queue->tail)
+            queue->tail->_Next = p;
+        queue->tail = p;
+        if(!queue->head)
+            queue->head = p;
+        queue->lock = 0;
+    }
+    else
+    {
+        p = queue->tail;
+    }
+
+    /* TODO: Add exception handling */
+    if(copy)
+        call__Concurrent_queue_base_v4__Copy_item(parent, p, id-page_id, e);
+    else
+        call__Concurrent_queue_base_v4__Move_item(parent, p, id-page_id, e);
+    p->_Mask |= 1 << (id - page_id);
+    InterlockedIncrementSizeT(&queue->tail_pos);
+}
+
+static void threadsafe_queue_pop(threadsafe_queue *queue, MSVCP_size_t id,
+        void *e, _Concurrent_queue_base_v4 *parent)
+{
+    MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
+    int spin;
+    _Page *p;
+
+    spin = 0;
+    while(queue->tail_pos <= id)
+        spin_wait(&spin);
+
+    spin = 0;
+    while(queue->head_pos != id)
+        spin_wait(&spin);
+
+    p = queue->head;
+    /* TODO: Add exception handling */
+    call__Concurrent_queue_base_v4__Assign_and_destroy_item(parent, e, p, id-page_id);
+
+    if(id == page_id+parent->alloc_count-1)
+    {
+        spin = 0;
+        while(InterlockedCompareExchange(&queue->lock, 1, 0))
+            spin_wait(&spin);
+        queue->head = p->_Next;
+        if(!queue->head)
+            queue->tail = NULL;
+        queue->lock = 0;
+
+        /* TODO: Add exception handling */
+        call__Concurrent_queue_base_v4__Deallocate_page(parent, p);
+    }
+    InterlockedIncrementSizeT(&queue->head_pos);
+}
+
 /* ?_Internal_push at _Concurrent_queue_base_v4@details at Concurrency@@IAEXPBX at Z */
 /* ?_Internal_push at _Concurrent_queue_base_v4@details at Concurrency@@IEAAXPEBX at Z */
 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_push, 8)
 void __thiscall _Concurrent_queue_base_v4__Internal_push(
-        _Concurrent_queue_base_v4 *this, const void *e)
+        _Concurrent_queue_base_v4 *this, void *e)
 {
-    FIXME("(%p %p) stub\n", this, e);
+    MSVCP_size_t id;
+
+    TRACE("(%p %p)\n", this, e);
+
+    id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
+    threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
+            id / QUEUES_NO, e, this, TRUE);
 }
 
 /* ?_Internal_move_push at _Concurrent_queue_base_v4@details at Concurrency@@IAEXPAX at Z */
@@ -1359,7 +1495,13 @@ DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_move_push, 8)
 void __thiscall _Concurrent_queue_base_v4__Internal_move_push(
         _Concurrent_queue_base_v4 *this, void *e)
 {
-    FIXME("(%p %p) stub\n", this, e);
+    MSVCP_size_t id;
+
+    TRACE("(%p %p)\n", this, e);
+
+    id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
+    threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
+            id / QUEUES_NO, e, this, FALSE);
 }
 
 /* ?_Internal_pop_if_present at _Concurrent_queue_base_v4@details at Concurrency@@IAE_NPAX at Z */
@@ -1368,8 +1510,18 @@ DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_pop_if_present, 8)
 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_pop_if_present(
         _Concurrent_queue_base_v4 *this, void *e)
 {
-    FIXME("(%p %p) stub\n", this, e);
-    return 0;
+    MSVCP_size_t id;
+
+    TRACE("(%p %p)\n", this, e);
+
+    do
+    {
+        id = this->data->head_pos;
+        if(id == this->data->tail_pos) return FALSE;
+    } while(InterlockedCompareExchangePointer((void**)&this->data->head_pos,
+                (void*)(id+1), (void*)id) != (void*)id);
+    threadsafe_queue_pop(this->data->queues + id % QUEUES_NO, id / QUEUES_NO, e, this);
+    return TRUE;
 }
 
 /* ?_Internal_swap at _Concurrent_queue_base_v4@details at Concurrency@@IAEXAAV123@@Z */




More information about the wine-cvs mailing list