mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +03:00
more work to make sdlwork.c and winwork.c match (nw)
This commit is contained in:
parent
f176a45d35
commit
6232bc0e50
@ -36,6 +36,11 @@ struct osd_lock
|
|||||||
CRITICAL_SECTION critsect;
|
CRITICAL_SECTION critsect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct osd_event
|
||||||
|
{
|
||||||
|
void * ptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct osd_scalable_lock
|
struct osd_scalable_lock
|
||||||
{
|
{
|
||||||
#if USE_SCALABLE_LOCKS
|
#if USE_SCALABLE_LOCKS
|
||||||
@ -184,6 +189,52 @@ INT32 win_atomic_add32(INT32 volatile *ptr, INT32 delta)
|
|||||||
return InterlockedExchangeAdd((LONG *) ptr, delta) + delta;
|
return InterlockedExchangeAdd((LONG *) ptr, delta) + delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// osd_event_alloc
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
osd_event *osd_event_alloc(int manualreset, int initialstate)
|
||||||
|
{
|
||||||
|
return (osd_event *) CreateEvent(NULL, manualreset, initialstate, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// osd_event_free
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
void osd_event_free(osd_event *event)
|
||||||
|
{
|
||||||
|
CloseHandle((HANDLE) event);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// osd_event_set
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
void osd_event_set(osd_event *event)
|
||||||
|
{
|
||||||
|
SetEvent((HANDLE) event);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// osd_event_reset
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
void osd_event_reset(osd_event *event)
|
||||||
|
{
|
||||||
|
ResetEvent((HANDLE) event);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// osd_event_wait
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
|
||||||
|
{
|
||||||
|
int ret = WaitForSingleObject((HANDLE) event, timeout * 1000 / osd_ticks_per_second());
|
||||||
|
return ( ret == WAIT_OBJECT_0);
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// Scalable Locks
|
// Scalable Locks
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -10,6 +10,95 @@
|
|||||||
#ifndef __WINSYNC__
|
#ifndef __WINSYNC__
|
||||||
#define __WINSYNC__
|
#define __WINSYNC__
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
SYNCHRONIZATION INTERFACES - Events
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/* osd_event is an opaque type which represents a setable/resetable event */
|
||||||
|
|
||||||
|
struct osd_event;
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
osd_lock_event_alloc: allocate a new event
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
manualreset - boolean. If true, the event will be automatically set
|
||||||
|
to non-signalled after a thread successfully waited for
|
||||||
|
it.
|
||||||
|
initialstate - boolean. If true, the event is signalled initially.
|
||||||
|
|
||||||
|
Return value:
|
||||||
|
|
||||||
|
A pointer to the allocated event.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
osd_event *osd_event_alloc(int manualreset, int initialstate);
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
osd_event_wait: wait for an event to be signalled
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
event - The event to wait for. If the event is in signalled state, the
|
||||||
|
function returns immediately. If not it will wait for the event
|
||||||
|
to become signalled.
|
||||||
|
timeout - timeout in osd_ticks
|
||||||
|
|
||||||
|
Return value:
|
||||||
|
|
||||||
|
TRUE: The event was signalled
|
||||||
|
FALSE: A timeout occurred
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
int osd_event_wait(osd_event *event, osd_ticks_t timeout);
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
osd_event_reset: reset an event to non-signalled state
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
event - The event to set to non-signalled state
|
||||||
|
|
||||||
|
Return value:
|
||||||
|
|
||||||
|
None
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
void osd_event_reset(osd_event *event);
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
osd_event_set: set an event to signalled state
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
event - The event to set to signalled state
|
||||||
|
|
||||||
|
Return value:
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
All threads waiting for the event will be signalled.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
void osd_event_set(osd_event *event);
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
osd_event_free: free the memory and resources associated with an osd_event
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
event - a pointer to a previously allocated osd_event.
|
||||||
|
|
||||||
|
Return value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
void osd_event_free(osd_event *event);
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// Scalable Locks
|
// Scalable Locks
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -83,7 +83,7 @@ struct work_thread_info
|
|||||||
{
|
{
|
||||||
osd_work_queue * queue; // pointer back to the queue
|
osd_work_queue * queue; // pointer back to the queue
|
||||||
HANDLE handle; // handle to the thread
|
HANDLE handle; // handle to the thread
|
||||||
HANDLE wakeevent; // wake event for the thread
|
osd_event * wakeevent; // wake event for the thread
|
||||||
volatile INT32 active; // are we actively processing work?
|
volatile INT32 active; // are we actively processing work?
|
||||||
|
|
||||||
#if KEEP_STATISTICS
|
#if KEEP_STATISTICS
|
||||||
@ -109,7 +109,7 @@ struct osd_work_queue
|
|||||||
UINT32 threads; // number of threads in this queue
|
UINT32 threads; // number of threads in this queue
|
||||||
UINT32 flags; // creation flags
|
UINT32 flags; // creation flags
|
||||||
work_thread_info * thread; // array of thread information
|
work_thread_info * thread; // array of thread information
|
||||||
HANDLE doneevent; // event signalled when work is complete
|
osd_event * doneevent; // event signalled when work is complete
|
||||||
|
|
||||||
#if KEEP_STATISTICS
|
#if KEEP_STATISTICS
|
||||||
volatile INT32 itemsqueued; // total items queued
|
volatile INT32 itemsqueued; // total items queued
|
||||||
@ -127,7 +127,7 @@ struct osd_work_item
|
|||||||
osd_work_callback callback; // callback function
|
osd_work_callback callback; // callback function
|
||||||
void * param; // callback parameter
|
void * param; // callback parameter
|
||||||
void * result; // callback result
|
void * result; // callback result
|
||||||
HANDLE event; // event signalled when complete
|
osd_event * event; // event signalled when complete
|
||||||
UINT32 flags; // creation flags
|
UINT32 flags; // creation flags
|
||||||
volatile INT32 done; // is the item done?
|
volatile INT32 done; // is the item done?
|
||||||
};
|
};
|
||||||
@ -169,7 +169,7 @@ osd_work_queue *osd_work_queue_alloc(int flags)
|
|||||||
queue->flags = flags;
|
queue->flags = flags;
|
||||||
|
|
||||||
// allocate events for the queue
|
// allocate events for the queue
|
||||||
queue->doneevent = CreateEvent(NULL, TRUE, TRUE, NULL); // manual reset, signalled
|
queue->doneevent = osd_event_alloc(TRUE, TRUE); // manual reset, signalled
|
||||||
if (queue->doneevent == NULL)
|
if (queue->doneevent == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ osd_work_queue *osd_work_queue_alloc(int flags)
|
|||||||
thread->queue = queue;
|
thread->queue = queue;
|
||||||
|
|
||||||
// create the per-thread wake event
|
// create the per-thread wake event
|
||||||
thread->wakeevent = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset, not signalled
|
thread->wakeevent = osd_event_alloc(FALSE, FALSE); // auto-reset, not signalled
|
||||||
if (thread->wakeevent == NULL)
|
if (thread->wakeevent == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -295,10 +295,10 @@ int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset our done event and double-check the items before waiting
|
// reset our done event and double-check the items before waiting
|
||||||
ResetEvent(queue->doneevent);
|
osd_event_reset(queue->doneevent);
|
||||||
atomic_exchange32(&queue->waiting, TRUE);
|
atomic_exchange32(&queue->waiting, TRUE);
|
||||||
if (queue->items != 0)
|
if (queue->items != 0)
|
||||||
WaitForSingleObject(queue->doneevent, timeout * 1000 / osd_ticks_per_second());
|
osd_event_wait(queue->doneevent, timeout);
|
||||||
atomic_exchange32(&queue->waiting, FALSE);
|
atomic_exchange32(&queue->waiting, FALSE);
|
||||||
|
|
||||||
// return TRUE if we actually hit 0
|
// return TRUE if we actually hit 0
|
||||||
@ -326,7 +326,7 @@ void osd_work_queue_free(osd_work_queue *queue)
|
|||||||
{
|
{
|
||||||
work_thread_info *thread = &queue->thread[threadnum];
|
work_thread_info *thread = &queue->thread[threadnum];
|
||||||
if (thread->wakeevent != NULL)
|
if (thread->wakeevent != NULL)
|
||||||
SetEvent(thread->wakeevent);
|
osd_event_set(thread->wakeevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for all the threads to go away
|
// wait for all the threads to go away
|
||||||
@ -343,7 +343,7 @@ void osd_work_queue_free(osd_work_queue *queue)
|
|||||||
|
|
||||||
// clean up the wake event
|
// clean up the wake event
|
||||||
if (thread->wakeevent != NULL)
|
if (thread->wakeevent != NULL)
|
||||||
CloseHandle(thread->wakeevent);
|
osd_event_free(thread->wakeevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if KEEP_STATISTICS
|
#if KEEP_STATISTICS
|
||||||
@ -368,7 +368,7 @@ void osd_work_queue_free(osd_work_queue *queue)
|
|||||||
|
|
||||||
// free all the events
|
// free all the events
|
||||||
if (queue->doneevent != NULL)
|
if (queue->doneevent != NULL)
|
||||||
CloseHandle(queue->doneevent);
|
osd_event_free(queue->doneevent);
|
||||||
|
|
||||||
// free all items in the free list
|
// free all items in the free list
|
||||||
while (queue->free != NULL)
|
while (queue->free != NULL)
|
||||||
@ -376,7 +376,7 @@ void osd_work_queue_free(osd_work_queue *queue)
|
|||||||
osd_work_item *item = (osd_work_item *)queue->free;
|
osd_work_item *item = (osd_work_item *)queue->free;
|
||||||
queue->free = item->next;
|
queue->free = item->next;
|
||||||
if (item->event != NULL)
|
if (item->event != NULL)
|
||||||
CloseHandle(item->event);
|
osd_event_free(item->event);
|
||||||
osd_free(item);
|
osd_free(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +386,7 @@ void osd_work_queue_free(osd_work_queue *queue)
|
|||||||
osd_work_item *item = (osd_work_item *)queue->list;
|
osd_work_item *item = (osd_work_item *)queue->list;
|
||||||
queue->list = item->next;
|
queue->list = item->next;
|
||||||
if (item->event != NULL)
|
if (item->event != NULL)
|
||||||
CloseHandle(item->event);
|
osd_event_free(item->event);
|
||||||
osd_free(item);
|
osd_free(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +474,7 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
|
|||||||
// if this thread is not active, wake him up
|
// if this thread is not active, wake him up
|
||||||
if (!thread->active)
|
if (!thread->active)
|
||||||
{
|
{
|
||||||
SetEvent(thread->wakeevent);
|
osd_event_set(thread->wakeevent);
|
||||||
add_to_stat(&queue->setevents, 1);
|
add_to_stat(&queue->setevents, 1);
|
||||||
|
|
||||||
// for non-shared, the first one we find is good enough
|
// for non-shared, the first one we find is good enough
|
||||||
@ -505,9 +505,9 @@ int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout)
|
|||||||
|
|
||||||
// if we don't have an event, create one
|
// if we don't have an event, create one
|
||||||
if (item->event == NULL)
|
if (item->event == NULL)
|
||||||
item->event = CreateEvent(NULL, TRUE, FALSE, NULL); // manual reset, not signalled
|
item->event = osd_event_alloc(TRUE, FALSE); // manual reset, not signalled
|
||||||
else
|
else
|
||||||
ResetEvent(item->event);
|
osd_event_reset(item->event);
|
||||||
|
|
||||||
// if we don't have an event, we need to spin (shouldn't ever really happen)
|
// if we don't have an event, we need to spin (shouldn't ever really happen)
|
||||||
if (item->event == NULL)
|
if (item->event == NULL)
|
||||||
@ -519,7 +519,7 @@ int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout)
|
|||||||
|
|
||||||
// otherwise, block on the event until done
|
// otherwise, block on the event until done
|
||||||
else if (!item->done)
|
else if (!item->done)
|
||||||
WaitForSingleObject(item->event, timeout * 1000 / osd_ticks_per_second());
|
osd_event_wait(item->event, timeout);
|
||||||
|
|
||||||
// return TRUE if the refcount actually hit 0
|
// return TRUE if the refcount actually hit 0
|
||||||
return item->done;
|
return item->done;
|
||||||
@ -598,11 +598,12 @@ static unsigned __stdcall worker_thread_entry(void *param)
|
|||||||
// loop until we exit
|
// loop until we exit
|
||||||
for ( ;; )
|
for ( ;; )
|
||||||
{
|
{
|
||||||
|
// block waiting for work or exit
|
||||||
// bail on exit, and only wait if there are no pending items in queue
|
// bail on exit, and only wait if there are no pending items in queue
|
||||||
if (!queue->exiting && queue->list == NULL)
|
if (!queue->exiting && queue->list == NULL)
|
||||||
{
|
{
|
||||||
begin_timing(thread->waittime);
|
begin_timing(thread->waittime);
|
||||||
WaitForSingleObject(thread->wakeevent, INFINITE);
|
osd_event_wait(thread->wakeevent, INFINITE);
|
||||||
end_timing(thread->waittime);
|
end_timing(thread->waittime);
|
||||||
}
|
}
|
||||||
if (queue->exiting)
|
if (queue->exiting)
|
||||||
@ -695,7 +696,7 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
|
|||||||
// set the result and signal the event
|
// set the result and signal the event
|
||||||
else if (item->event != NULL)
|
else if (item->event != NULL)
|
||||||
{
|
{
|
||||||
SetEvent(item->event);
|
osd_event_set(item->event);
|
||||||
add_to_stat(&item->queue->setevents, 1);
|
add_to_stat(&item->queue->setevents, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,7 +709,7 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
|
|||||||
// we don't need to set the doneevent for multi queues because they spin
|
// we don't need to set the doneevent for multi queues because they spin
|
||||||
if (queue->waiting)
|
if (queue->waiting)
|
||||||
{
|
{
|
||||||
SetEvent(queue->doneevent);
|
osd_event_set(queue->doneevent);
|
||||||
add_to_stat(&queue->setevents, 1);
|
add_to_stat(&queue->setevents, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user