Commit 7a120b0b authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mfplat: Initialize system queues on startup.

parent f42b3a1f
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "mfplat_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
static LONG platform_lock; static LONG platform_lock;
...@@ -465,11 +467,16 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags) ...@@ -465,11 +467,16 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
#define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 ) #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
#define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 ) #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
FIXME("(%u, %u): stub\n", version, flags); TRACE("%#x, %#x.\n", version, flags);
if(version != MF_VERSION_XP && version != MF_VERSION_WIN7) if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
return MF_E_BAD_STARTUP_VERSION; return MF_E_BAD_STARTUP_VERSION;
if (InterlockedIncrement(&platform_lock) == 1)
{
init_system_queues();
}
return S_OK; return S_OK;
} }
...@@ -478,7 +485,15 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags) ...@@ -478,7 +485,15 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
*/ */
HRESULT WINAPI MFShutdown(void) HRESULT WINAPI MFShutdown(void)
{ {
FIXME("(): stub\n"); TRACE("\n");
if (platform_lock <= 0)
return S_OK;
if (InterlockedExchangeAdd(&platform_lock, -1) == 1)
{
shutdown_system_queues();
}
return S_OK; return S_OK;
} }
...@@ -498,7 +513,10 @@ HRESULT WINAPI MFLockPlatform(void) ...@@ -498,7 +513,10 @@ HRESULT WINAPI MFLockPlatform(void)
*/ */
HRESULT WINAPI MFUnlockPlatform(void) HRESULT WINAPI MFUnlockPlatform(void)
{ {
InterlockedDecrement(&platform_lock); if (InterlockedDecrement(&platform_lock) == 0)
{
shutdown_system_queues();
}
return S_OK; return S_OK;
} }
......
/*
* Copyright 2019 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
extern void init_system_queues(void) DECLSPEC_HIDDEN;
extern void shutdown_system_queues(void) DECLSPEC_HIDDEN;
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/heap.h" #include "wine/heap.h"
#include "mfplat_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
#define FIRST_USER_QUEUE_HANDLE 5 #define FIRST_USER_QUEUE_HANDLE 5
...@@ -33,26 +35,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); ...@@ -33,26 +35,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
struct queue struct queue
{ {
TP_POOL *pool;
};
struct queue_handle
{
void *obj; void *obj;
LONG refcount; LONG refcount;
WORD generation; WORD generation;
}; };
static struct queue user_queues[MAX_USER_QUEUE_HANDLES]; static struct queue_handle user_queues[MAX_USER_QUEUE_HANDLES];
static struct queue *next_free_user_queue; static struct queue_handle *next_free_user_queue;
static struct queue *next_unused_user_queue = user_queues; static struct queue_handle *next_unused_user_queue = user_queues;
static WORD queue_generation; static WORD queue_generation;
static CRITICAL_SECTION user_queues_section; static CRITICAL_SECTION queues_section;
static CRITICAL_SECTION_DEBUG user_queues_critsect_debug = static CRITICAL_SECTION_DEBUG queues_critsect_debug =
{ {
0, 0, &user_queues_section, 0, 0, &queues_section,
{ &user_queues_critsect_debug.ProcessLocksList, &user_queues_critsect_debug.ProcessLocksList }, { &queues_critsect_debug.ProcessLocksList, &queues_critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": user_queues_section") } 0, 0, { (DWORD_PTR)(__FILE__ ": queues_section") }
}; };
static CRITICAL_SECTION user_queues_section = { &user_queues_critsect_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION queues_section = { &queues_critsect_debug, -1, 0, 0, 0, 0 };
static struct queue *get_queue_obj(DWORD handle) static struct queue_handle *get_queue_obj(DWORD handle)
{ {
unsigned int idx = HIWORD(handle) - FIRST_USER_QUEUE_HANDLE; unsigned int idx = HIWORD(handle) - FIRST_USER_QUEUE_HANDLE;
...@@ -65,12 +72,79 @@ static struct queue *get_queue_obj(DWORD handle) ...@@ -65,12 +72,79 @@ static struct queue *get_queue_obj(DWORD handle)
return NULL; return NULL;
} }
static HRESULT alloc_user_queue(DWORD *queue) enum system_queue_index
{
SYS_QUEUE_STANDARD = 0,
SYS_QUEUE_RT,
SYS_QUEUE_IO,
SYS_QUEUE_TIMER,
SYS_QUEUE_MULTITHREADED,
SYS_QUEUE_DO_NOT_USE,
SYS_QUEUE_LONG_FUNCTION,
SYS_QUEUE_COUNT,
};
static struct queue system_queues[SYS_QUEUE_COUNT];
static void init_work_queue(MFASYNC_WORKQUEUE_TYPE queue_type, struct queue *queue)
{
queue->pool = CreateThreadpool(NULL);
}
void init_system_queues(void)
{
/* Always initialize standard queue, keep the rest lazy. */
EnterCriticalSection(&queues_section);
if (system_queues[SYS_QUEUE_STANDARD].pool)
{
LeaveCriticalSection(&queues_section);
return;
}
init_work_queue(MF_STANDARD_WORKQUEUE, &system_queues[SYS_QUEUE_STANDARD]);
LeaveCriticalSection(&queues_section);
}
static void shutdown_queue(struct queue *queue)
{
if (!queue->pool)
return;
CloseThreadpool(queue->pool);
queue->pool = NULL;
}
void shutdown_system_queues(void)
{
unsigned int i;
EnterCriticalSection(&queues_section);
for (i = 0; i < ARRAY_SIZE(system_queues); ++i)
{
shutdown_queue(&system_queues[i]);
}
LeaveCriticalSection(&queues_section);
}
static HRESULT alloc_user_queue(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue_id)
{ {
struct queue *entry; struct queue_handle *entry;
struct queue *queue;
unsigned int idx; unsigned int idx;
EnterCriticalSection(&user_queues_section); *queue_id = MFASYNC_CALLBACK_QUEUE_UNDEFINED;
queue = heap_alloc_zero(sizeof(*queue));
if (!queue)
return E_OUTOFMEMORY;
init_work_queue(queue_type, queue);
EnterCriticalSection(&queues_section);
entry = next_free_user_queue; entry = next_free_user_queue;
if (entry) if (entry)
...@@ -79,17 +153,18 @@ static HRESULT alloc_user_queue(DWORD *queue) ...@@ -79,17 +153,18 @@ static HRESULT alloc_user_queue(DWORD *queue)
entry = next_unused_user_queue++; entry = next_unused_user_queue++;
else else
{ {
LeaveCriticalSection(&user_queues_section); LeaveCriticalSection(&queues_section);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
entry->refcount = 1; entry->refcount = 1;
entry->obj = NULL; entry->obj = queue;
if (++queue_generation == 0xffff) queue_generation = 1; if (++queue_generation == 0xffff) queue_generation = 1;
entry->generation = queue_generation; entry->generation = queue_generation;
idx = entry - user_queues + FIRST_USER_QUEUE_HANDLE; idx = entry - user_queues + FIRST_USER_QUEUE_HANDLE;
*queue = (idx << 16) | entry->generation; *queue_id = (idx << 16) | entry->generation;
LeaveCriticalSection(&user_queues_section);
LeaveCriticalSection(&queues_section);
return S_OK; return S_OK;
} }
...@@ -97,31 +172,31 @@ static HRESULT alloc_user_queue(DWORD *queue) ...@@ -97,31 +172,31 @@ static HRESULT alloc_user_queue(DWORD *queue)
static HRESULT lock_user_queue(DWORD queue) static HRESULT lock_user_queue(DWORD queue)
{ {
HRESULT hr = MF_E_INVALID_WORKQUEUE; HRESULT hr = MF_E_INVALID_WORKQUEUE;
struct queue *entry; struct queue_handle *entry;
if (!(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK)) if (!(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK))
return S_OK; return S_OK;
EnterCriticalSection(&user_queues_section); EnterCriticalSection(&queues_section);
entry = get_queue_obj(queue); entry = get_queue_obj(queue);
if (entry && entry->refcount) if (entry && entry->refcount)
{ {
entry->refcount++; entry->refcount++;
hr = S_OK; hr = S_OK;
} }
LeaveCriticalSection(&user_queues_section); LeaveCriticalSection(&queues_section);
return hr; return hr;
} }
static HRESULT unlock_user_queue(DWORD queue) static HRESULT unlock_user_queue(DWORD queue)
{ {
HRESULT hr = MF_E_INVALID_WORKQUEUE; HRESULT hr = MF_E_INVALID_WORKQUEUE;
struct queue *entry; struct queue_handle *entry;
if (!(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK)) if (!(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK))
return S_OK; return S_OK;
EnterCriticalSection(&user_queues_section); EnterCriticalSection(&queues_section);
entry = get_queue_obj(queue); entry = get_queue_obj(queue);
if (entry && entry->refcount) if (entry && entry->refcount)
{ {
...@@ -132,7 +207,7 @@ static HRESULT unlock_user_queue(DWORD queue) ...@@ -132,7 +207,7 @@ static HRESULT unlock_user_queue(DWORD queue)
} }
hr = S_OK; hr = S_OK;
} }
LeaveCriticalSection(&user_queues_section); LeaveCriticalSection(&queues_section);
return hr; return hr;
} }
...@@ -309,7 +384,7 @@ HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue) ...@@ -309,7 +384,7 @@ HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue)
{ {
TRACE("%p.\n", queue); TRACE("%p.\n", queue);
return alloc_user_queue(queue); return alloc_user_queue(MF_STANDARD_WORKQUEUE, queue);
} }
/*********************************************************************** /***********************************************************************
......
...@@ -88,7 +88,15 @@ DEFINE_GUID(MFMediaType_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0 ...@@ -88,7 +88,15 @@ DEFINE_GUID(MFMediaType_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0
typedef unsigned __int64 MFWORKITEM_KEY; typedef unsigned __int64 MFWORKITEM_KEY;
typedef enum
{
MF_STANDARD_WORKQUEUE,
MF_WINDOW_WORKQUEUE,
MF_MULTITHREADED_WORKQUEUE,
} MFASYNC_WORKQUEUE_TYPE;
HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue);
HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue);
HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key); HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key);
HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines); HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines);
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size); HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
......
...@@ -431,6 +431,7 @@ cpp_quote("#define MFASYNC_CALLBACK_QUEUE_STANDARD 0x00000001") ...@@ -431,6 +431,7 @@ cpp_quote("#define MFASYNC_CALLBACK_QUEUE_STANDARD 0x00000001")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_RT 0x00000002") cpp_quote("#define MFASYNC_CALLBACK_QUEUE_RT 0x00000002")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_IO 0x00000003") cpp_quote("#define MFASYNC_CALLBACK_QUEUE_IO 0x00000003")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_TIMER 0x00000004") cpp_quote("#define MFASYNC_CALLBACK_QUEUE_TIMER 0x00000004")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_MULTITHREADED 0x00000005")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION 0x00000007") cpp_quote("#define MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION 0x00000007")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK 0xffff0000") cpp_quote("#define MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK 0xffff0000")
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_ALL 0xffffffff") cpp_quote("#define MFASYNC_CALLBACK_QUEUE_ALL 0xffffffff")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment