newlib-cygwin/winsup/cygwin/miscfuncs.cc

461 lines
12 KiB
C++
Raw Normal View History

/* miscfuncs.cc: misc funcs that don't belong anywhere else
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include "miscfuncs.h"
#include <sys/uio.h>
* dcrt0.cc: Include string.h. (initial_env): Use small_printf's %P specifier. * dll_init.cc (dll_list::alloc): Use PATH_MAX instead of CYG_MAX_PATH for path name buffer size. * dll_init.h (struct dll): Ditto. * environ.cc: Include string.h. (win_env::add_cache): Use temporary local buffer for path conversion. (posify): Ditto. * exceptions.cc (try_to_debug): Use CreateProcessW to allow long path names. * miscfuncs.cc: Drop unused implementations of strcasematch and strncasematch. (ch_case_eq): Drop. (strcasestr): Drop. (cygwin_wcscasecmp): New function. (cygwin_wcsncasecmp): New function. (cygwin_strcasecmp): New function. (cygwin_strncasecmp): New function. (cygwin_wcslwr): New function. (cygwin_wcsupr): New function. (cygwin_strlwr): New function. (cygwin_strupr): New function. * ntdll.h (RtlDowncaseUnicodeString): Declare. (RtlUpcaseUnicodeString): Declare. (RtlInt64ToHexUnicodeString): Fix typo in comment. * string.h: Disable not NLS aware implementations of strcasematch and strncasematch. (cygwin_strcasecmp): Declare. (strcasecmp): Define as cygwin_strcasecmp. (cygwin_strncasecmp): Declare. (strncasecmp): Define as cygwin_strncasecmp. (strcasematch):Define using cygwin_strcasecmp. (strncasematch):Define using cygwin_strncasecmp. (cygwin_strlwr): Declare. (strlwr): Define as cygwin_strlwr. (cygwin_strupr): Declare. (strupr): Define as cygwin_strupr. * wchar.h: New file. * wincap.cc (wincapc::init): Use "NT" as fix OS string. * winsup.h (strcasematch): Drop declaration. (strncasematch): Ditto. (strcasestr): Ditto.
2007-12-12 20:12:24 +08:00
#include "ntdll.h"
* cygwin.din (pthread_attr_getguardsize): Export. (pthread_attr_setguardsize): Export. (pthread_attr_setstack): Export. (pthread_attr_setstackaddr): Export. * init.cc (dll_entry): Remove wow64_test_stack_marker. Check for unusual stack address by testing stack addresses from current TEB. Check validity of _my_tls by testing if it's within the stack as given in current TEB. * miscfuncs.cc (struct thread_wrapper_arg): New structure used to push all required information to thread_wrapper function. (thread_wrapper): Wrapper function for actual thread function. If an application stack has been given, change %ebp and %esp so that the thread function runs on that stack. If the thread has been created by CygwinCreateThread, set up the POSIX guard pages if necessary. (CygwinCreateThread): New function. * miscfuncs.h (CygwinCreateThread): Declare. * ntdll.h (struct _TEB): Define all members up to Peb. * posix.sgml (std-susv4): Move pthread_attr_getguardsize, pthread_attr_setguardsize and pthread_attr_setstack here. (std-deprec): Add pthread_attr_setstackaddr. * sysconf.cc (sca): Set _SC_THREAD_ATTR_STACKADDR to _POSIX_THREAD_ATTR_STACKADDR. * thread.cc (pthread::precreate): Copy pthread_attr stackaddr and guardsize members. (pthread::create): Call CygwinCreateThread. (pthread_attr::pthread_attr): Initialize guardsize. (pthread_attr_setstack): New function. (pthread_attr_setstackaddr): New function. (pthread_attr_setguardsize): New function. (pthread_attr_getguardsize): New function. (pthread_getattr_np): Copy attr.guardsize. * thread.h (pthread_attr): Add member guardsize. * include/pthread.h (pthread_attr_getguardsize): Declare. (pthread_attr_setguardsize): Declare. * include/cygwin/version.h: Bump API minor number.
2011-05-16 02:49:40 +08:00
#include "path.h"
#include "fhandler.h"
#include "tls_pbuf.h"
/* not yet prototyped in w32api */
extern "C" HRESULT SetThreadDescription (HANDLE hThread, PCWSTR lpThreadDescription);
/* Get handle count of an object. */
ULONG
get_obj_handle_count (HANDLE h)
{
OBJECT_BASIC_INFORMATION obi;
NTSTATUS status;
ULONG hdl_cnt = 0;
status = NtQueryObject (h, ObjectBasicInformation, &obi, sizeof obi, NULL);
if (!NT_SUCCESS (status))
debug_printf ("NtQueryObject: %y", status);
else
hdl_cnt = obi.HandleCount;
return hdl_cnt;
}
static char __attribute__ ((noinline))
dummytest (volatile char *p)
{
return *p;
}
ssize_t
check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
{
if (iovcnt < 0 || iovcnt > IOV_MAX)
{
set_errno (EINVAL);
return -1;
}
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
__try
{
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
size_t tot = 0;
while (iovcnt > 0)
{
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
{
set_errno (EINVAL);
__leave;
}
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
volatile char *p = ((char *) iov->iov_base) + iov->iov_len - 1;
if (!iov->iov_len)
/* nothing to do */;
else if (!forwrite)
*p = dummytest (p);
else
dummytest (p);
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
iov++;
iovcnt--;
}
if (tot <= SSIZE_MAX)
return (ssize_t) tot;
set_errno (EINVAL);
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
}
__except (EFAULT)
__endtry
return -1;
}
/* Try hard to schedule another thread.
Remember not to call this in a lock condition or you'll potentially
suffer starvation. */
void
yield ()
{
/* MSDN implies that Sleep will force scheduling of other threads.
Unlike SwitchToThread() the documentation does not mention other
cpus so, presumably (hah!), this + using a lower priority will
stall this thread temporarily and cause another to run.
(stackoverflow and others seem to confirm that setting this thread
to a lower priority and calling Sleep with a 0 paramenter will
have this desired effect)
CV 2017-03-08: Drop lowering the priority. It leads to potential
starvation and it should not be necessary anymore
since Server 2003. See the MSDN Sleep man page. */
Sleep (0L);
}
/* Get a default value for the nice factor. When changing these values,
have a look into the below function nice_to_winprio. The values must
match the layout of the static "priority" array. */
int
winprio_to_nice (DWORD prio)
{
switch (prio)
{
case REALTIME_PRIORITY_CLASS:
return -20;
case HIGH_PRIORITY_CLASS:
return -16;
case ABOVE_NORMAL_PRIORITY_CLASS:
return -8;
case NORMAL_PRIORITY_CLASS:
return 0;
case BELOW_NORMAL_PRIORITY_CLASS:
return 8;
case IDLE_PRIORITY_CLASS:
return 16;
}
return 0;
}
/* Get a Win32 priority matching the incoming nice factor. The incoming
nice is limited to the interval [-NZERO,NZERO-1]. */
2005-02-14 02:17:29 +08:00
DWORD
nice_to_winprio (int &nice)
{
2013-04-23 17:44:36 +08:00
static const DWORD priority[] =
{
REALTIME_PRIORITY_CLASS, /* 0 */
HIGH_PRIORITY_CLASS, /* 1 */
HIGH_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS, /* 7 */
ABOVE_NORMAL_PRIORITY_CLASS, /* 8 */
ABOVE_NORMAL_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS, /* 15 */
NORMAL_PRIORITY_CLASS, /* 16 */
NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS, /* 23 */
BELOW_NORMAL_PRIORITY_CLASS, /* 24 */
BELOW_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS, /* 31 */
IDLE_PRIORITY_CLASS, /* 32 */
IDLE_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS /* 39 */
};
if (nice < -NZERO)
nice = -NZERO;
else if (nice > NZERO - 1)
nice = NZERO - 1;
DWORD prio = priority[nice + NZERO];
return prio;
}
/* Set Win32 priority or return false on failure. Also return
false and revert to the original priority if a different (lower)
priority is set instead. */
bool
set_and_check_winprio (HANDLE proc, DWORD prio)
{
DWORD prev_prio = GetPriorityClass (proc);
if (!prev_prio)
return false;
if (prev_prio == prio)
return true;
if (!SetPriorityClass (proc, prio))
return false;
/* Windows silently sets a lower priority (HIGH_PRIORITY_CLASS) if
the new priority (REALTIME_PRIORITY_CLASS) requires administrator
privileges. */
DWORD curr_prio = GetPriorityClass (proc);
if (curr_prio != prio)
{
debug_printf ("Failed to set priority 0x%x, revert from 0x%x to 0x%x",
prio, curr_prio, prev_prio);
SetPriorityClass (proc, prev_prio);
return false;
}
debug_printf ("Changed priority from 0x%x to 0x%x", prev_prio, curr_prio);
return true;
}
/* Minimal overlapped pipe I/O implementation for signal and commune stuff. */
BOOL
CreatePipeOverlapped (PHANDLE hr, PHANDLE hw, LPSECURITY_ATTRIBUTES sa)
{
int ret = fhandler_pipe::create (sa, hr, hw, 0, NULL,
FILE_FLAG_OVERLAPPED);
if (ret)
SetLastError (ret);
return ret == 0;
}
BOOL
ReadPipeOverlapped (HANDLE h, PVOID buf, DWORD len, LPDWORD ret_len,
DWORD timeout)
2011-12-18 07:39:47 +08:00
{
OVERLAPPED ov;
2011-12-18 07:39:47 +08:00
BOOL ret;
memset (&ov, 0, sizeof ov);
ov.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
ret = ReadFile (h, buf, len, NULL, &ov);
if (ret || GetLastError () == ERROR_IO_PENDING)
{
if (!ret && WaitForSingleObject (ov.hEvent, timeout) != WAIT_OBJECT_0)
CancelIo (h);
ret = GetOverlappedResult (h, &ov, ret_len, FALSE);
2011-12-18 07:39:47 +08:00
}
CloseHandle (ov.hEvent);
2011-12-18 07:39:47 +08:00
return ret;
}
BOOL
WritePipeOverlapped (HANDLE h, LPCVOID buf, DWORD len, LPDWORD ret_len,
DWORD timeout)
{
2011-12-18 07:39:47 +08:00
OVERLAPPED ov;
BOOL ret;
memset (&ov, 0, sizeof ov);
ov.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
ret = WriteFile (h, buf, len, NULL, &ov);
if (ret || GetLastError () == ERROR_IO_PENDING)
{
if (!ret && WaitForSingleObject (ov.hEvent, timeout) != WAIT_OBJECT_0)
CancelIo (h);
ret = GetOverlappedResult (h, &ov, ret_len, FALSE);
2011-12-18 07:39:47 +08:00
}
CloseHandle (ov.hEvent);
return ret;
}
bool
NT_readline::init (POBJECT_ATTRIBUTES attr, PCHAR in_buf, ULONG in_buflen)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
{
paranoid_printf ("NtOpenFile(%S) failed, status %y",
attr->ObjectName, status);
return false;
}
buf = in_buf;
buflen = in_buflen;
got = end = buf;
len = 0;
line = 1;
return true;
}
PCHAR
NT_readline::gets ()
{
IO_STATUS_BLOCK io;
while (true)
{
/* len == 0 indicates we have to read from the file. */
if (!len)
{
if (!NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, got,
(buflen - 2) - (got - buf), NULL, NULL)))
return NULL;
len = io.Information;
/* Set end marker. */
got[len] = got[len + 1] = '\0';
/* Set len to the absolute len of bytes in buf. */
len += got - buf;
/* Reset got to start reading at the start of the buffer again. */
got = end = buf;
}
else
{
got = end + 1;
++line;
}
/* Still some valid full line? */
if (got < buf + len)
{
if ((end = strchr (got, '\n')))
{
end[end[-1] == '\r' ? -1 : 0] = '\0';
return got;
}
/* Last line missing a \n at EOF? */
if (len < buflen - 2)
{
len = 0;
return got;
}
}
/* We have to read once more. Move remaining bytes to the start of
the buffer and reposition got so that it points to the end of
the remaining bytes. */
len = buf + len - got;
memmove (buf, got, len);
got = buf + len;
buf[len] = buf[len + 1] = '\0';
len = 0;
}
}
/* Signal the thread name to any attached debugger
(See "How to: Set a Thread Name in Native Code"
https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx) */
#define MS_VC_EXCEPTION 0x406D1388
static void
SetThreadNameExc (DWORD dwThreadID, const char* threadName)
{
if (!IsDebuggerPresent ())
return;
ULONG_PTR info[] =
{
0x1000, /* type, must be 0x1000 */
(ULONG_PTR) threadName, /* pointer to threadname */
dwThreadID, /* thread ID (+ flags on x86_64) */
};
__try
{
RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (ULONG_PTR),
info);
}
__except (NO_ERROR)
__endtry
}
void
SetThreadName (DWORD dwThreadID, const char* threadName)
{
HANDLE hThread = OpenThread (THREAD_SET_LIMITED_INFORMATION, FALSE, dwThreadID);
if (hThread)
{
/* SetThreadDescription only exists in a wide-char version, so we must
convert threadname to wide-char. The encoding of threadName is
unclear, so use UTF8 until we know better. */
int bufsize = MultiByteToWideChar (CP_UTF8, 0, threadName, -1, NULL, 0);
WCHAR buf[bufsize];
bufsize = MultiByteToWideChar (CP_UTF8, 0, threadName, -1, buf, bufsize);
HRESULT hr = SetThreadDescription (hThread, buf);
if (IS_ERROR (hr))
{
debug_printf ("SetThreadDescription() failed. %08x %08x\n",
GetLastError (), hr);
}
CloseHandle (hThread);
}
/* also use the older, exception-based method of setting threadname for the
benefit of things which don't known about GetThreadDescription. */
SetThreadNameExc (dwThreadID, threadName);
}
#define add_size(p,s) ((p) = ((__typeof__(p))((PBYTE)(p)+(s))))
static WORD num_cpu_per_group = 0;
static WORD group_count = 0;
WORD
__get_cpus_per_group (void)
{
tmp_pathbuf tp;
if (num_cpu_per_group)
return num_cpu_per_group;
num_cpu_per_group = 64;
group_count = 1;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX lpi =
(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) tp.c_get ();
DWORD lpi_size = NT_MAX_PATH;
/* Fake a SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX group info block if
GetLogicalProcessorInformationEx fails for some reason. */
if (!GetLogicalProcessorInformationEx (RelationGroup, lpi, &lpi_size))
{
lpi_size = sizeof *lpi;
lpi->Relationship = RelationGroup;
lpi->Size = lpi_size;
lpi->Group.MaximumGroupCount = 1;
lpi->Group.ActiveGroupCount = 1;
lpi->Group.GroupInfo[0].MaximumProcessorCount = wincap.cpu_count ();
lpi->Group.GroupInfo[0].ActiveProcessorCount
= __builtin_popcountl (wincap.cpu_mask ());
lpi->Group.GroupInfo[0].ActiveProcessorMask = wincap.cpu_mask ();
}
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX plpi = lpi;
for (DWORD size = lpi_size; size > 0;
size -= plpi->Size, add_size (plpi, plpi->Size))
if (plpi->Relationship == RelationGroup)
{
/* There are systems with a MaximumProcessorCount not reflecting the
actually available CPUs. The ActiveProcessorCount is correct
though. So we just use ActiveProcessorCount for now, hoping for
the best. */
num_cpu_per_group = plpi->Group.GroupInfo[0].ActiveProcessorCount;
/* Follow that lead to get the group count. */
group_count = plpi->Group.ActiveGroupCount;
break;
}
return num_cpu_per_group;
}
WORD
__get_group_count (void)
{
if (group_count == 0)
(void) __get_cpus_per_group (); // caller should have called this first
return group_count;
}