msvcrt: Avoid using global critical section while allocating new file descriptors.
This commit is contained in:
parent
e7fc237088
commit
6ed69c107f
|
@ -114,9 +114,6 @@ ioinfo * MSVCRT___pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { 0 };
|
||||||
*/
|
*/
|
||||||
ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
|
ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
|
||||||
|
|
||||||
static int MSVCRT_fdstart = 3; /* first unallocated fd */
|
|
||||||
static int MSVCRT_fdend = 3; /* highest allocated fd */
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MSVCRT_FILE file;
|
MSVCRT_FILE file;
|
||||||
CRITICAL_SECTION crit;
|
CRITICAL_SECTION crit;
|
||||||
|
@ -143,12 +140,9 @@ static const ULONGLONG WCBAT = TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
|
||||||
static const ULONGLONG WCCMD = TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
|
static const ULONGLONG WCCMD = TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
|
||||||
static const ULONGLONG WCCOM = TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
|
static const ULONGLONG WCCOM = TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
|
||||||
|
|
||||||
/* This critical section protects the tables MSVCRT___pioinfo and MSVCRT_fstreams,
|
/* This critical section protects the MSVCRT_fstreams table
|
||||||
* and their related indexes, MSVCRT_fdstart, MSVCRT_fdend,
|
* and MSVCRT_stream_idx from race conditions. It also
|
||||||
* and MSVCRT_stream_idx, from race conditions.
|
* protects fd critical sections creation code.
|
||||||
* It doesn't protect against race conditions manipulating the underlying files
|
|
||||||
* or flags; doing so would probably be better accomplished with per-file
|
|
||||||
* protection, rather than locking the whole table for every change.
|
|
||||||
*/
|
*/
|
||||||
static CRITICAL_SECTION MSVCRT_file_cs;
|
static CRITICAL_SECTION MSVCRT_file_cs;
|
||||||
static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug =
|
static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug =
|
||||||
|
@ -257,19 +251,24 @@ static inline ioinfo* get_ioinfo_nolock(int fd)
|
||||||
return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
|
return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void init_ioinfo_cs(ioinfo *info)
|
||||||
|
{
|
||||||
|
if(!(info->exflag & EF_CRIT_INIT)) {
|
||||||
|
LOCK_FILES();
|
||||||
|
if(!(info->exflag & EF_CRIT_INIT)) {
|
||||||
|
InitializeCriticalSection(&info->crit);
|
||||||
|
info->exflag |= EF_CRIT_INIT;
|
||||||
|
}
|
||||||
|
UNLOCK_FILES();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline ioinfo* get_ioinfo(int fd)
|
static inline ioinfo* get_ioinfo(int fd)
|
||||||
{
|
{
|
||||||
ioinfo *ret = get_ioinfo_nolock(fd);
|
ioinfo *ret = get_ioinfo_nolock(fd);
|
||||||
if(ret == &MSVCRT___badioinfo)
|
if(ret == &MSVCRT___badioinfo)
|
||||||
return ret;
|
return ret;
|
||||||
if(!(ret->exflag & EF_CRIT_INIT)) {
|
init_ioinfo_cs(ret);
|
||||||
LOCK_FILES();
|
|
||||||
if(!(ret->exflag & EF_CRIT_INIT)) {
|
|
||||||
InitializeCriticalSection(&ret->crit);
|
|
||||||
ret->exflag |= EF_CRIT_INIT;
|
|
||||||
}
|
|
||||||
UNLOCK_FILES();
|
|
||||||
}
|
|
||||||
EnterCriticalSection(&ret->crit);
|
EnterCriticalSection(&ret->crit);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -301,77 +300,49 @@ static inline BOOL alloc_pioinfo_block(int fd)
|
||||||
|
|
||||||
static inline ioinfo* get_ioinfo_alloc_fd(int fd)
|
static inline ioinfo* get_ioinfo_alloc_fd(int fd)
|
||||||
{
|
{
|
||||||
ioinfo *ret, *info;
|
ioinfo *ret;
|
||||||
|
|
||||||
ret = get_ioinfo(fd);
|
ret = get_ioinfo(fd);
|
||||||
if(ret != &MSVCRT___badioinfo)
|
if(ret != &MSVCRT___badioinfo)
|
||||||
{
|
|
||||||
LOCK_FILES();
|
|
||||||
/* locate next free slot */
|
|
||||||
if (fd == MSVCRT_fdstart && fd == MSVCRT_fdend)
|
|
||||||
MSVCRT_fdstart = MSVCRT_fdend + 1;
|
|
||||||
else if (fd == MSVCRT_fdstart)
|
|
||||||
{
|
|
||||||
MSVCRT_fdstart++;
|
|
||||||
while (MSVCRT_fdstart < MSVCRT_fdend &&
|
|
||||||
((info = get_ioinfo_nolock(MSVCRT_fdstart))->exflag & EF_CRIT_INIT))
|
|
||||||
{
|
|
||||||
if (TryEnterCriticalSection(&info->crit))
|
|
||||||
{
|
|
||||||
if (info->handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LeaveCriticalSection(&info->crit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&info->crit);
|
|
||||||
}
|
|
||||||
MSVCRT_fdstart++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* update last fd in use */
|
|
||||||
if (fd >= MSVCRT_fdend)
|
|
||||||
MSVCRT_fdend = fd + 1;
|
|
||||||
TRACE("fdstart is %d, fdend is %d\n", MSVCRT_fdstart, MSVCRT_fdend);
|
|
||||||
UNLOCK_FILES();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
|
|
||||||
if(!alloc_pioinfo_block(fd))
|
if(!alloc_pioinfo_block(fd))
|
||||||
return &MSVCRT___badioinfo;
|
return &MSVCRT___badioinfo;
|
||||||
|
|
||||||
ret = get_ioinfo(fd);
|
return get_ioinfo(fd);
|
||||||
if(ret == &MSVCRT___badioinfo)
|
}
|
||||||
return ret;
|
|
||||||
|
|
||||||
LOCK_FILES();
|
static inline ioinfo* get_ioinfo_alloc(int *fd)
|
||||||
/* locate next free slot */
|
{
|
||||||
if (fd == MSVCRT_fdstart && fd == MSVCRT_fdend)
|
int i;
|
||||||
MSVCRT_fdstart = MSVCRT_fdend + 1;
|
|
||||||
else if (fd == MSVCRT_fdstart)
|
*fd = -1;
|
||||||
|
for(i=0; i<MSVCRT_MAX_FILES; i++)
|
||||||
{
|
{
|
||||||
MSVCRT_fdstart++;
|
ioinfo *info = get_ioinfo_nolock(i);
|
||||||
while (MSVCRT_fdstart < MSVCRT_fdend &&
|
|
||||||
((info = get_ioinfo_nolock(MSVCRT_fdstart))->exflag & EF_CRIT_INIT))
|
if(info == &MSVCRT___badioinfo)
|
||||||
{
|
{
|
||||||
if (TryEnterCriticalSection(&info->crit))
|
if(!alloc_pioinfo_block(i))
|
||||||
|
return &MSVCRT___badioinfo;
|
||||||
|
info = get_ioinfo_nolock(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_ioinfo_cs(info);
|
||||||
|
if(TryEnterCriticalSection(&info->crit))
|
||||||
|
{
|
||||||
|
if(info->handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (info->handle == INVALID_HANDLE_VALUE)
|
*fd = i;
|
||||||
{
|
return info;
|
||||||
LeaveCriticalSection(&info->crit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&info->crit);
|
|
||||||
}
|
}
|
||||||
MSVCRT_fdstart++;
|
LeaveCriticalSection(&info->crit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* update last fd in use */
|
|
||||||
if (fd >= MSVCRT_fdend)
|
|
||||||
MSVCRT_fdend = fd + 1;
|
|
||||||
TRACE("fdstart is %d, fdend is %d\n", MSVCRT_fdstart, MSVCRT_fdend);
|
|
||||||
UNLOCK_FILES();
|
|
||||||
|
|
||||||
return ret;
|
WARN(":files exhausted!\n");
|
||||||
|
*MSVCRT__errno() = MSVCRT_ENFILE;
|
||||||
|
return &MSVCRT___badioinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void release_ioinfo(ioinfo *info)
|
static inline void release_ioinfo(ioinfo *info)
|
||||||
|
@ -434,13 +405,6 @@ static void msvcrt_free_fd(int fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
release_ioinfo(fdinfo);
|
release_ioinfo(fdinfo);
|
||||||
|
|
||||||
LOCK_FILES();
|
|
||||||
if (fd == MSVCRT_fdend - 1)
|
|
||||||
MSVCRT_fdend--;
|
|
||||||
if (fd < MSVCRT_fdstart)
|
|
||||||
MSVCRT_fdstart = fd;
|
|
||||||
UNLOCK_FILES();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
|
static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
|
||||||
|
@ -463,23 +427,11 @@ static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
|
||||||
/* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
|
/* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
|
||||||
static int msvcrt_alloc_fd(HANDLE hand, int flag)
|
static int msvcrt_alloc_fd(HANDLE hand, int flag)
|
||||||
{
|
{
|
||||||
ioinfo *info;
|
|
||||||
int fd;
|
int fd;
|
||||||
|
ioinfo *info = get_ioinfo_alloc(&fd);
|
||||||
|
|
||||||
LOCK_FILES();
|
|
||||||
fd = MSVCRT_fdstart;
|
|
||||||
TRACE(":handle (%p) allocating fd (%d)\n", hand, fd);
|
TRACE(":handle (%p) allocating fd (%d)\n", hand, fd);
|
||||||
|
|
||||||
if (fd >= MSVCRT_MAX_FILES)
|
|
||||||
{
|
|
||||||
UNLOCK_FILES();
|
|
||||||
WARN(":files exhausted!\n");
|
|
||||||
*MSVCRT__errno() = MSVCRT_ENFILE;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
info = get_ioinfo_alloc_fd(fd);
|
|
||||||
UNLOCK_FILES();
|
|
||||||
if(info == &MSVCRT___badioinfo)
|
if(info == &MSVCRT___badioinfo)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -623,9 +575,6 @@ void msvcrt_init_io(void)
|
||||||
|
|
||||||
wxflag_ptr++; handle_ptr++;
|
wxflag_ptr++; handle_ptr++;
|
||||||
}
|
}
|
||||||
MSVCRT_fdend = max( 3, count );
|
|
||||||
for (MSVCRT_fdstart = 3; MSVCRT_fdstart < MSVCRT_fdend; MSVCRT_fdstart++)
|
|
||||||
if (get_ioinfo_nolock(MSVCRT_fdstart)->handle == INVALID_HANDLE_VALUE) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDIN_FILENO);
|
fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDIN_FILENO);
|
||||||
|
@ -1147,14 +1096,13 @@ int CDECL MSVCRT__dup2(int od, int nd)
|
||||||
int CDECL MSVCRT__dup(int od)
|
int CDECL MSVCRT__dup(int od)
|
||||||
{
|
{
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
ioinfo *info = get_ioinfo_alloc(&fd);
|
||||||
|
|
||||||
LOCK_FILES();
|
|
||||||
fd = MSVCRT_fdstart;
|
|
||||||
if (MSVCRT__dup2(od, fd) == 0)
|
if (MSVCRT__dup2(od, fd) == 0)
|
||||||
ret = fd;
|
ret = fd;
|
||||||
else
|
else
|
||||||
ret = -1;
|
ret = -1;
|
||||||
UNLOCK_FILES();
|
release_ioinfo(info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4377,7 +4325,7 @@ MSVCRT_FILE* CDECL MSVCRT__wfreopen(const MSVCRT_wchar_t *path, const MSVCRT_wch
|
||||||
TRACE(":path (%s) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file ? file->_file : -1);
|
TRACE(":path (%s) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file ? file->_file : -1);
|
||||||
|
|
||||||
LOCK_FILES();
|
LOCK_FILES();
|
||||||
if (!file || ((fd = file->_file) < 0) || fd > MSVCRT_fdend)
|
if (!file || ((fd = file->_file) < 0))
|
||||||
file = NULL;
|
file = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue