From d1a79ea2eb4835344318c0ed09e978f1759a4f43 Mon Sep 17 00:00:00 2001 From: Peter Hunnisett Date: Thu, 21 Feb 2002 20:22:00 +0000 Subject: [PATCH] Add _lock,_unlock and header file for them. Convert all msvcrt locks over to use _lock and _unlock. Explicitly make msvcrt compile with multithreaded option. Fix flag handling in _sopen. Add W->A call for new _swopen. --- dlls/msvcrt/Makefile.in | 3 +- dlls/msvcrt/console.c | 6 +- dlls/msvcrt/exit.c | 7 +-- dlls/msvcrt/file.c | 125 +++++++++++++++++++++++++++++++--------- dlls/msvcrt/heap.c | 8 +-- dlls/msvcrt/locale.c | 6 +- dlls/msvcrt/lock.c | 122 +++++++++++++++++++++++++++++++++++++++ dlls/msvcrt/main.c | 32 +--------- dlls/msvcrt/msvcrt.h | 4 ++ dlls/msvcrt/msvcrt.spec | 8 +-- dlls/msvcrt/mtdll.h | 56 ++++++++++++++++++ 11 files changed, 300 insertions(+), 77 deletions(-) create mode 100644 dlls/msvcrt/lock.c create mode 100644 dlls/msvcrt/mtdll.h diff --git a/dlls/msvcrt/Makefile.in b/dlls/msvcrt/Makefile.in index c9f57c4f76b..33a53d8571e 100644 --- a/dlls/msvcrt/Makefile.in +++ b/dlls/msvcrt/Makefile.in @@ -1,4 +1,4 @@ -EXTRADEFS = -DUSE_MSVCRT_PREFIX +EXTRADEFS = -DUSE_MSVCRT_PREFIX -D_MT TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ @@ -22,6 +22,7 @@ C_SRCS = \ file.c \ heap.c \ locale.c \ + lock.c \ main.c \ math.c \ mbcs.c \ diff --git a/dlls/msvcrt/console.c b/dlls/msvcrt/console.c index 0983b1246e6..0bf8117f207 100644 --- a/dlls/msvcrt/console.c +++ b/dlls/msvcrt/console.c @@ -12,6 +12,7 @@ #include "msvcrt/conio.h" #include "msvcrt/malloc.h" #include "msvcrt/stdio.h" +#include "mtdll.h" #include "wine/debug.h" @@ -20,9 +21,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); /* MT */ -extern CRITICAL_SECTION MSVCRT_console_cs; -#define LOCK_CONSOLE EnterCriticalSection(&MSVCRT_console_cs) -#define UNLOCK_CONSOLE LeaveCriticalSection(&MSVCRT_console_cs) +#define LOCK_CONSOLE _mlock(_CONIO_LOCK) +#define UNLOCK_CONSOLE _munlock(_CONIO_LOCK) static HANDLE MSVCRT_console_in = INVALID_HANDLE_VALUE; static HANDLE MSVCRT_console_out= INVALID_HANDLE_VALUE; diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index 274035a6fc8..f7b0710a8b8 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -7,16 +7,15 @@ #include "msvcrt/conio.h" #include "msvcrt/stdlib.h" - +#include "mtdll.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); /* MT */ -extern CRITICAL_SECTION MSVCRT_exit_cs; -#define LOCK_EXIT EnterCriticalSection(&MSVCRT_exit_cs) -#define UNLOCK_EXIT LeaveCriticalSection(&MSVCRT_exit_cs) +#define LOCK_EXIT _mlock(_EXIT_LOCK1) +#define UNLOCK_EXIT _munlock(_EXIT_LOCK1) static _onexit_t *MSVCRT_atexit_table = NULL; static int MSVCRT_atexit_table_size = 0; diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index ec61b1faf5a..80c673e2d2d 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -24,6 +24,7 @@ #include "msvcrt/sys/stat.h" #include "msvcrt/sys/utime.h" #include "msvcrt/time.h" +#include "msvcrt/share.h" #include "wine/debug.h" @@ -719,18 +720,23 @@ WCHAR *_wmktemp(WCHAR *pattern) } /********************************************************************* - * _open (MSVCRT.@) + * _sopen (MSVCRT.@) */ -int _open(const char *path,int flags,...) +int MSVCRT__sopen( const char *path, int oflags, int shflags, ... ) { + va_list ap; + int pmode; DWORD access = 0, creation = 0; + DWORD sharing; int ioflag = 0, fd; HANDLE hand; SECURITY_ATTRIBUTES sa; - - TRACE(":file (%s) mode 0x%04x\n",path,flags); - switch(flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) + + TRACE(":file (%s) oflags: 0x%04x shflags: 0x%04x\n", + path, oflags, shflags); + + switch(oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { case _O_RDONLY: access |= GENERIC_READ; @@ -746,49 +752,73 @@ int _open(const char *path,int flags,...) break; } - if (flags & _O_CREAT) + if (oflags & _O_CREAT) { - if (flags & _O_EXCL) + va_start(ap, shflags); + pmode = va_arg(ap, int); + va_end(ap); + + FIXME(": pmode 0x%04x ignored\n", pmode); + + if (oflags & _O_EXCL) creation = CREATE_NEW; - else if (flags & _O_TRUNC) + else if (oflags & _O_TRUNC) creation = CREATE_ALWAYS; else creation = OPEN_ALWAYS; } else /* no _O_CREAT */ { - if (flags & _O_TRUNC) + if (oflags & _O_TRUNC) creation = TRUNCATE_EXISTING; else creation = OPEN_EXISTING; } - if (flags & _O_APPEND) + if (oflags & _O_APPEND) ioflag |= MSVCRT__IOAPPEND; - flags |= _O_BINARY; /* FIXME: Default to text */ + oflags |= _O_BINARY; /* FIXME: Default to text */ - if (flags & _O_TEXT) + if (oflags & _O_TEXT) { /* Dont warn when writing */ if (ioflag & GENERIC_READ) FIXME(":TEXT node not implemented\n"); - flags &= ~_O_TEXT; + oflags &= ~_O_TEXT; } - if (flags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL - |_O_CREAT|_O_RDWR|_O_TEMPORARY)) - TRACE(":unsupported flags 0x%04x\n",flags); - + switch( shflags ) + { + case _SH_DENYRW: + sharing = 0L; + break; + case _SH_DENYWR: + sharing = FILE_SHARE_READ; + break; + case _SH_DENYRD: + sharing = FILE_SHARE_WRITE; + break; + case _SH_DENYNO: + sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + default: + ERR( "Unhandled shflags 0x%x\n", shflags ); + return -1; + } + + if (oflags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL + |_O_CREAT|_O_RDWR|_O_TEMPORARY|_O_NOINHERIT)) + TRACE(":unsupported oflags 0x%04x\n",oflags); + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; + sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE; - hand = CreateFileA(path, access, FILE_SHARE_READ | FILE_SHARE_WRITE, + hand = CreateFileA(path, access, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, 0); - if (hand == INVALID_HANDLE_VALUE) - { + if (hand == INVALID_HANDLE_VALUE) { WARN(":failed-last error (%ld)\n",GetLastError()); MSVCRT__set_errno(GetLastError()); return -1; @@ -800,7 +830,7 @@ int _open(const char *path,int flags,...) if (fd > 0) { - if (flags & _O_TEMPORARY) + if (oflags & _O_TEMPORARY) MSVCRT_tempfiles[fd] = _strdup(path); if (ioflag & MSVCRT__IOAPPEND) _lseek(fd, 0, FILE_END); @@ -810,15 +840,22 @@ int _open(const char *path,int flags,...) } /********************************************************************* - * _wopen (MSVCRT.@) + * _wsopen (MSVCRT.@) */ -int _wopen(const WCHAR *path,int flags,...) +int MSVCRT__wsopen( const WCHAR* path, int oflags, int shflags, ... ) { const unsigned int len = strlenW(path); char *patha = MSVCRT_calloc(len + 1,1); + va_list ap; + int pmode; + + va_start(ap, shflags); + pmode = va_arg(ap, int); + va_end(ap); + if (patha && WideCharToMultiByte(CP_ACP,0,path,len,patha,len,NULL,NULL)) { - int retval = _open(patha,flags); + int retval = MSVCRT__sopen(patha,oflags,shflags,pmode); MSVCRT_free(patha); return retval; } @@ -828,11 +865,43 @@ int _wopen(const WCHAR *path,int flags,...) } /********************************************************************* - * _sopen (MSVCRT.@) + * _open (MSVCRT.@) */ -int MSVCRT__sopen(const char *path,int oflags,int shflags) +int _open( const char *path, int flags, ... ) { - return _open(path, oflags | shflags); + va_list ap; + int pmode; + + va_start(ap, flags); + pmode = va_arg(ap, int); + va_end(ap); + + return MSVCRT__sopen( path, flags, _SH_DENYNO, pmode ); +} + +/********************************************************************* + * _wopen (MSVCRT.@) + */ +int _wopen(const WCHAR *path,int flags,...) +{ + const unsigned int len = strlenW(path); + char *patha = MSVCRT_calloc(len + 1,1); + va_list ap; + int pmode; + + va_start(ap, flags); + pmode = va_arg(ap, int); + va_end(ap); + + if (patha && WideCharToMultiByte(CP_ACP,0,path,len,patha,len,NULL,NULL)) + { + int retval = _open(patha,flags,pmode); + MSVCRT_free(patha); + return retval; + } + + MSVCRT__set_errno(GetLastError()); + return -1; } /********************************************************************* diff --git a/dlls/msvcrt/heap.c b/dlls/msvcrt/heap.c index 1ae40ac2a6c..6fc3c2217d6 100644 --- a/dlls/msvcrt/heap.c +++ b/dlls/msvcrt/heap.c @@ -11,16 +11,16 @@ #include "ms_errno.h" #include "msvcrt/malloc.h" - +#include "mtdll.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); /* MT */ -extern CRITICAL_SECTION MSVCRT_heap_cs; -#define LOCK_HEAP EnterCriticalSection(&MSVCRT_heap_cs) -#define UNLOCK_HEAP LeaveCriticalSection(&MSVCRT_heap_cs) +#define LOCK_HEAP _mlock( _HEAP_LOCK ) +#define UNLOCK_HEAP _munlock( _HEAP_LOCK ) + typedef void (*MSVCRT_new_handler_func)(unsigned long size); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 512ee3b0655..d3d0bc27f97 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -9,6 +9,7 @@ #include "msvcrt.h" #include "msvcrt/locale.h" +#include "mtdll.h" #include "wine/debug.h" @@ -24,9 +25,8 @@ LCID MSVCRT_current_lc_all_lcid; int MSVCRT_current_lc_all_cp; /* MT */ -extern CRITICAL_SECTION MSVCRT_locale_cs; -#define LOCK_LOCALE EnterCriticalSection(&MSVCRT_locale_cs) -#define UNLOCK_LOCALE LeaveCriticalSection(&MSVCRT_locale_cs) +#define LOCK_LOCALE _mlock(_SETLOCALE_LOCK); +#define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK); /* ctype data modified when the locale changes */ extern WORD MSVCRT__ctype [257]; diff --git a/dlls/msvcrt/lock.c b/dlls/msvcrt/lock.c new file mode 100644 index 00000000000..d93352d8989 --- /dev/null +++ b/dlls/msvcrt/lock.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2002, TransGaming Technologies Inc. + */ + +#include "mtdll.h" + +#include "debugtools.h" +#include "winbase.h" + +DEFAULT_DEBUG_CHANNEL(msvcrt); + +typedef struct +{ + BOOL bInit; + CRITICAL_SECTION crit; +} LOCKTABLEENTRY; + +static LOCKTABLEENTRY lock_table[ _TOTAL_LOCKS ]; + +static inline void msvcrt_mlock_set_entry_initialized( int locknum, BOOL initialized ) +{ + lock_table[ locknum ].bInit = initialized; +} + +static inline void msvcrt_initialize_mlock( int locknum ) +{ + InitializeCriticalSection( &(lock_table[ locknum ].crit) ); + msvcrt_mlock_set_entry_initialized( locknum, TRUE ); +} + +static inline void msvcrt_uninitialize_mlock( int locknum ) +{ + DeleteCriticalSection( &(lock_table[ locknum ].crit) ); + msvcrt_mlock_set_entry_initialized( locknum, FALSE ); +} + +/********************************************************************** + * msvcrt_init_mt_locks (internal) + * + * Initialize the table lock. All other locks will be initialized + * upon first use. + * + */ +void msvcrt_init_mt_locks(void) +{ + int i; + + TRACE( "initializing mtlocks\n" ); + + /* Initialize the table */ + for( i=0; i < _TOTAL_LOCKS; i++ ) + { + msvcrt_mlock_set_entry_initialized( i, FALSE ); + } + + /* Initialize our lock table lock */ + msvcrt_initialize_mlock( _LOCKTAB_LOCK ); +} + +/********************************************************************** + * msvcrt_free_mt_locks (internal) + * + * Uninitialize all mt locks. Assume that neither _lock or _unlock will + * be called once we're calling this routine (ie _LOCKTAB_LOCK can be deleted) + * + */ +void msvcrt_free_mt_locks(void) +{ + int i; + + TRACE( ": uninitializing all mtlocks\n" ); + + /* Uninitialize the table */ + for( i=0; i < _TOTAL_LOCKS; i++ ) + { + if( lock_table[ i ].bInit == TRUE ) + { + msvcrt_uninitialize_mlock( i ); + } + } +} + + +/********************************************************************** + * _lock (MSVCRT.@) + */ +void _lock( int locknum ) +{ + TRACE( "(%d)\n", locknum ); + + /* If the lock doesn't exist yet, create it */ + if( lock_table[ locknum ].bInit == FALSE ) + { + /* Lock while we're changing the lock table */ + _lock( _LOCKTAB_LOCK ); + + /* Check again if we've got a bit of a race on lock creation */ + if( lock_table[ locknum ].bInit == FALSE ) + { + TRACE( ": creating lock #%d\n", locknum ); + msvcrt_initialize_mlock( locknum ); + } + + /* Unlock ourselves */ + _unlock( _LOCKTAB_LOCK ); + } + + EnterCriticalSection( &(lock_table[ locknum ].crit) ); +} + +/********************************************************************** + * _unlock (MSVCRT.@) + * + * NOTE: There is no error detection to make sure the lock exists and is acquired. + */ +void _unlock( int locknum ) +{ + TRACE( "(%d)\n", locknum ); + + LeaveCriticalSection( &(lock_table[ locknum ].crit) ); +} + diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c index 684dcccbcc6..79488af829e 100644 --- a/dlls/msvcrt/main.c +++ b/dlls/msvcrt/main.c @@ -8,7 +8,6 @@ #include "msvcrt/locale.h" #include "msvcrt/stdio.h" - #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); @@ -16,17 +15,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); /* Index to TLS */ DWORD MSVCRT_tls_index; -/* MT locks */ -CRITICAL_SECTION MSVCRT_heap_cs; -CRITICAL_SECTION MSVCRT_file_cs; -CRITICAL_SECTION MSVCRT_exit_cs; -CRITICAL_SECTION MSVCRT_console_cs; -CRITICAL_SECTION MSVCRT_locale_cs; - static inline BOOL msvcrt_init_tls(void); static inline BOOL msvcrt_free_tls(void); -static inline void msvcrt_init_critical_sections(void); -static inline void msvcrt_free_critical_sections(void); const char* msvcrt_get_reason(DWORD reason) WINE_UNUSED; void msvcrt_init_io(void); @@ -56,8 +46,8 @@ BOOL WINAPI MSVCRT_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: if (!msvcrt_init_tls()) return FALSE; + msvcrt_init_mt_locks(); msvcrt_init_vtables(); - msvcrt_init_critical_sections(); msvcrt_init_io(); msvcrt_init_console(); msvcrt_init_args(); @@ -77,7 +67,7 @@ BOOL WINAPI MSVCRT_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) TRACE("finished thread init\n"); break; case DLL_PROCESS_DETACH: - msvcrt_free_critical_sections(); + msvcrt_free_mt_locks(); _fcloseall(); msvcrt_free_console(); msvcrt_free_args(); @@ -123,24 +113,6 @@ static inline BOOL msvcrt_free_tls(void) return TRUE; } -static inline void msvcrt_init_critical_sections(void) -{ - InitializeCriticalSectionAndSpinCount(&MSVCRT_heap_cs, 4000); - InitializeCriticalSection(&MSVCRT_file_cs); - InitializeCriticalSection(&MSVCRT_exit_cs); - InitializeCriticalSection(&MSVCRT_console_cs); - InitializeCriticalSection(&MSVCRT_locale_cs); -} - -static inline void msvcrt_free_critical_sections(void) -{ - DeleteCriticalSection(&MSVCRT_locale_cs); - DeleteCriticalSection(&MSVCRT_console_cs); - DeleteCriticalSection(&MSVCRT_exit_cs); - DeleteCriticalSection(&MSVCRT_file_cs); - DeleteCriticalSection(&MSVCRT_heap_cs); -} - const char* msvcrt_get_reason(DWORD reason) { switch (reason) diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index f548baefece..c2e39aa9ba2 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -40,4 +40,8 @@ LPWSTR msvcrt_wstrndup(LPCWSTR, unsigned int); */ int MSVCRT__set_new_mode(int mode); +/* Setup and teardown multi threaded locks */ +void msvcrt_init_mt_locks(void); +void msvcrt_free_mt_locks(void); + #endif /* __WINE_MSVCRT_H */ diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index e3ab663c696..a15e75b41bb 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -325,7 +325,7 @@ debug_channels (msvcrt) @ cdecl _lfind(ptr ptr ptr long ptr) _lfind @ cdecl _loaddll(str) _loaddll @ cdecl _local_unwind2(ptr long) _local_unwind2 -@ stub _lock +@ cdecl _lock(long) _lock @ stub _locking #(long long long) @ cdecl _logb( double ) _logb @ stub _longjmpex @@ -441,7 +441,7 @@ debug_channels (msvcrt) @ cdecl _sleep(long) _sleep @ varargs _snprintf(str long str) snprintf @ forward -noimport _snwprintf ntdll._snwprintf -@ cdecl _sopen(str long long) MSVCRT__sopen +@ varargs _sopen(str long long) MSVCRT__sopen @ varargs _spawnl(long str str) _spawnl @ stub _spawnle #(str str) varargs @ varargs _spawnlp(long str str) _spawnlp @@ -488,7 +488,7 @@ debug_channels (msvcrt) @ cdecl _ungetch(long) _ungetch @ cdecl _unlink(str) _unlink @ cdecl _unloaddll(long) _unloaddll -@ stub _unlock +@ cdecl _unlock(long) _unlock @ cdecl _utime(str ptr) _utime @ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf @ cdecl _vsnwprintf(ptr long wstr long) _vsnwprintf @@ -548,7 +548,7 @@ debug_channels (msvcrt) @ cdecl _wrmdir(wstr) _wrmdir @ stub _wsearchenv #(wstr wstr wstr) @ stub _wsetlocale #(long wstr) -@ stub _wsopen #(wstr long long) varargs +@ varargs _wsopen (wstr long long) MSVCRT__wsopen @ stub _wspawnl #(long wstr wstr) varargs @ stub _wspawnle #(long wstr wstr) varargs @ stub _wspawnlp #(long wstr wstr) varargs diff --git a/dlls/msvcrt/mtdll.h b/dlls/msvcrt/mtdll.h new file mode 100644 index 00000000000..ed4606742fb --- /dev/null +++ b/dlls/msvcrt/mtdll.h @@ -0,0 +1,56 @@ +#ifndef WINE_MTDLL_H +#define WINE_MTDLL_H + +#if defined(_MT) + +#define _mlock(locknum) _lock(locknum) +#define _munlock(locknum) _unlock(locknum) + +void _unlock( int locknum ); +void _lock( int locknum ); + +#else + +#define _mlock(locknum) do {} while(0) +#define _munlock(locknum) do {} while(0) + +#endif + + +#define _SIGNAL_LOCK 1 +#define _IOB_SCAN_LOCK 2 +#define _TMPNAM_LOCK 3 +#define _INPUT_LOCK 4 +#define _OUTPUT_LOCK 5 +#define _CSCANF_LOCK 6 +#define _CPRINTF_LOCK 7 +#define _CONIO_LOCK 8 +#define _HEAP_LOCK 9 +#define _BHEAP_LOCK 10 /* No longer used? */ +#define _TIME_LOCK 11 +#define _ENV_LOCK 12 +#define _EXIT_LOCK1 13 +#define _EXIT_LOCK2 14 /* No longer used? */ +#define _THREADDATA_LOCK 15 /* No longer used? */ +#define _POPEN_LOCK 16 +#define _LOCKTAB_LOCK 17 +#define _OSFHND_LOCK 18 +#define _SETLOCALE_LOCK 19 +#define _LC_COLLATE_LOCK 20 /* No longer used? */ +#define _LC_CTYPE_LOCK 21 /* No longer used? */ +#define _LC_MONETARY_LOCK 22 /* No longer used? */ +#define _LC_NUMERIC_LOCK 23 /* No longer used? */ +#define _LC_TIME_LOCK 24 /* No longer used? */ +#define _MB_CP_LOCK 25 +#define _NLG_LOCK 26 +#define _TYPEINFO_LOCK 27 +#define _STREAM_LOCKS 28 + +/* Must match definition in msvcrt/stdio.h */ +#define _IOB_ENTRIES 20 + +#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_IOB_ENTRIES-1) + +#define _TOTAL_LOCKS (_LAST_STREAM_LOCK+1) + +#endif /* WINE_MTDLL_H */