//============================================================ // // winsync.c - Win32 OSD core synchronization functions // //============================================================ // // Copyright Aaron Giles // All rights reserved. // // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the // following conditions are met: // // * Redistributions of source code must retain the above // copyright notice, this list of conditions and the // following disclaimer. // * Redistributions in binary form must reproduce the // above copyright notice, this list of conditions and // the following disclaimer in the documentation and/or // other materials provided with the distribution. // * Neither the name 'MAME' nor the names of its // contributors may be used to endorse or promote // products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //============================================================ // standard windows headers #define WIN32_LEAN_AND_MEAN #include #include // MAME headers #include "osdcore.h" #include "osinline.h" //============================================================ // DEBUGGING //============================================================ #define DEBUG_SLOW_LOCKS 0 //============================================================ // TYPE DEFINITIONS //============================================================ typedef BOOL (WINAPI *try_enter_critical_section_ptr)(LPCRITICAL_SECTION lpCriticalSection); struct osd_lock { CRITICAL_SECTION critsect; }; //============================================================ // GLOBAL VARIABLES //============================================================ static try_enter_critical_section_ptr try_enter_critical_section = NULL; static int checked_for_try_enter = FALSE; //============================================================ // osd_lock_alloc //============================================================ osd_lock *osd_lock_alloc(void) { osd_lock *lock = (osd_lock *)malloc(sizeof(*lock)); if (lock == NULL) return NULL; InitializeCriticalSection(&lock->critsect); return lock; } //============================================================ // osd_lock_acquire //============================================================ void osd_lock_acquire(osd_lock *lock) { #if DEBUG_SLOW_LOCKS osd_ticks_t ticks = osd_ticks(); #endif // block until we can acquire the lock EnterCriticalSection(&lock->critsect); #if DEBUG_SLOW_LOCKS // log any locks that take more than 1ms ticks = osd_ticks() - ticks; if (ticks > osd_ticks_per_second() / 1000) mame_printf_debug("Blocked %d ticks on lock acquire\n", (int)ticks); #endif } //============================================================ // osd_lock_try //============================================================ int osd_lock_try(osd_lock *lock) { int result = TRUE; // if we haven't yet checked for the TryEnter API, do it now if (!checked_for_try_enter) { // see if we can use TryEnterCriticalSection HMODULE library = LoadLibrary(TEXT("kernel32.dll")); if (library != NULL) try_enter_critical_section = (try_enter_critical_section_ptr)GetProcAddress(library, "TryEnterCriticalSection"); checked_for_try_enter = TRUE; } // if we have it, use it, otherwise just block if (try_enter_critical_section != NULL) result = (*try_enter_critical_section)(&lock->critsect); else EnterCriticalSection(&lock->critsect); return result; } //============================================================ // osd_lock_release //============================================================ void osd_lock_release(osd_lock *lock) { LeaveCriticalSection(&lock->critsect); } //============================================================ // osd_lock_free //============================================================ void osd_lock_free(osd_lock *lock) { DeleteCriticalSection(&lock->critsect); free(lock); } //============================================================ // win_compare_exchange32 //============================================================ INT32 win_compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange) { return InterlockedCompareExchange((LPLONG)ptr, (LONG)exchange, (LONG)compare); } //============================================================ // win_compare_exchange64 //============================================================ #ifdef PTR64 INT64 win_compare_exchange64(INT64 volatile *ptr, INT64 compare, INT64 exchange) { return InterlockedCompareExchange64((LONGLONG*)ptr, (LONGLONG)exchange, (LONGLONG)compare); } #endif //============================================================ // win_atomic_exchange32 //============================================================ INT32 win_atomic_exchange32(INT32 volatile *ptr, INT32 exchange) { return InterlockedExchange((LONG *) ptr, exchange); } //============================================================ // win_atomic_add32 //============================================================ INT32 win_atomic_add32(INT32 volatile *ptr, INT32 delta) { return InterlockedExchangeAdd((LONG *) ptr, delta) + delta; }