summaryrefslogtreecommitdiff
path: root/src/pal/src/thread/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/thread/thread.cpp')
-rw-r--r--src/pal/src/thread/thread.cpp108
1 files changed, 40 insertions, 68 deletions
diff --git a/src/pal/src/thread/thread.cpp b/src/pal/src/thread/thread.cpp
index 566ef855b4..53283320c5 100644
--- a/src/pal/src/thread/thread.cpp
+++ b/src/pal/src/thread/thread.cpp
@@ -34,6 +34,8 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do
#include "pal/module.h"
#include "pal/environ.h"
#include "pal/init.h"
+#include "pal/utils.h"
+#include "pal/virtual.h"
#if defined(__NetBSD__) && !HAVE_PTHREAD_GETCPUCLOCKID
#include <sys/cdefs.h>
@@ -77,13 +79,6 @@ using namespace CorUnix;
/* ------------------- Definitions ------------------------------*/
-// The default stack size of a newly created thread (currently 256KB)
-// when the dwStackSize parameter of PAL_CreateThread()
-// is zero. This value can be set by setting the
-// environment variable PAL_THREAD_DEFAULT_STACK_SIZE
-// (the value should be in bytes and in hex).
-DWORD CPalThread::s_dwDefaultThreadStackSize = 256*1024;
-
/* list of free CPalThread objects */
static Volatile<CPalThread*> free_threads_list = NULL;
@@ -528,6 +523,7 @@ CorUnix::InternalCreateThread(
#endif // PTHREAD_CREATE_MODIFIES_ERRNO
BOOL fHoldingProcessLock = FALSE;
int iError = 0;
+ size_t alignedStackSize;
if (0 != terminator)
{
@@ -573,7 +569,24 @@ CorUnix::InternalCreateThread(
palError = ERROR_INVALID_PARAMETER;
goto EXIT;
}
-
+
+ alignedStackSize = dwStackSize;
+ if (alignedStackSize != 0)
+ {
+ // Some systems require the stack size to be aligned to the page size
+ if (sizeof(alignedStackSize) <= sizeof(dwStackSize) && alignedStackSize + (VIRTUAL_PAGE_SIZE - 1) < alignedStackSize)
+ {
+ // When coming here from the public API surface, the incoming value is originally a nonnegative signed int32, so
+ // this shouldn't happen
+ ASSERT(
+ "Couldn't align the requested stack size (%Iu) to the page size because the stack size was too large\n",
+ alignedStackSize);
+ palError = ERROR_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ alignedStackSize = ALIGN_UP(alignedStackSize, VIRTUAL_PAGE_SIZE);
+ }
+
// Ignore the STACK_SIZE_PARAM_IS_A_RESERVATION flag
dwCreationFlags &= ~STACK_SIZE_PARAM_IS_A_RESERVATION;
@@ -616,42 +629,34 @@ CorUnix::InternalCreateThread(
fAttributesInitialized = TRUE;
/* adjust the stack size if necessary */
- if (0 != pthread_attr_getstacksize(&pthreadAttr, &pthreadStackSize))
+ if (alignedStackSize != 0)
{
- ERROR("couldn't set thread stack size\n");
- palError = ERROR_INTERNAL_ERROR;
- goto EXIT;
- }
-
- TRACE("default pthread stack size is %d, caller requested %d (default is %d)\n",
- pthreadStackSize, dwStackSize, CPalThread::s_dwDefaultThreadStackSize);
-
- if (0 == dwStackSize)
- {
- dwStackSize = CPalThread::s_dwDefaultThreadStackSize;
- }
-
#ifdef PTHREAD_STACK_MIN
- if (PTHREAD_STACK_MIN > pthreadStackSize)
- {
- WARN("default stack size is reported as %d, but PTHREAD_STACK_MIN is "
- "%d\n", pthreadStackSize, PTHREAD_STACK_MIN);
- }
-#endif
-
- if (pthreadStackSize < dwStackSize)
- {
- TRACE("setting thread stack size to %d\n", dwStackSize);
- if (0 != pthread_attr_setstacksize(&pthreadAttr, dwStackSize))
+ const size_t MinStackSize = PTHREAD_STACK_MIN;
+#else // !PTHREAD_STACK_MIN
+ const size_t MinStackSize = 64 * 1024; // this value is typically accepted by pthread_attr_setstacksize()
+#endif // PTHREAD_STACK_MIN
+ _ASSERTE(IS_ALIGNED(MinStackSize, VIRTUAL_PAGE_SIZE));
+ if (alignedStackSize < MinStackSize)
{
- ERROR("couldn't set pthread stack size to %d\n", dwStackSize);
+ // Adjust the stack size to a minimum value that is likely to be accepted by pthread_attr_setstacksize(). If this
+ // function fails, typically the caller will end up throwing OutOfMemoryException under the assumption that the
+ // requested stack size is too large or the system does not have sufficient memory to create a thread. Try to
+ // prevent failing just just because the stack size value is too low.
+ alignedStackSize = MinStackSize;
+ }
+
+ TRACE("setting thread stack size to %Iu\n", alignedStackSize);
+ if (0 != pthread_attr_setstacksize(&pthreadAttr, alignedStackSize))
+ {
+ ERROR("couldn't set pthread stack size to %Iu\n", alignedStackSize);
palError = ERROR_INTERNAL_ERROR;
goto EXIT;
}
}
else
{
- TRACE("using the system default thread stack size of %d\n", pthreadStackSize);
+ TRACE("using the system default thread stack size\n");
}
#if HAVE_THREAD_SELF || HAVE__LWP_SELF
@@ -1755,39 +1760,6 @@ fail:
return NULL;
}
-
-#define PAL_THREAD_DEFAULT_STACK_SIZE "PAL_THREAD_DEFAULT_STACK_SIZE"
-
-PAL_ERROR
-CorUnix::InitializeGlobalThreadData(
- void
- )
-{
- PAL_ERROR palError = NO_ERROR;
- char *pszStackSize = NULL;
-
- //
- // Read in the environment to see whether we need to change the default
- // thread stack size.
- //
- pszStackSize = EnvironGetenv(PAL_THREAD_DEFAULT_STACK_SIZE);
- if (NULL != pszStackSize)
- {
- // Environment variable exists
- char *pszEnd;
- DWORD dw = PAL_strtoul(pszStackSize, &pszEnd, 16); // treat it as hex
- if ( (pszStackSize != pszEnd) && (0 != dw) )
- {
- CPalThread::s_dwDefaultThreadStackSize = dw;
- }
-
- free(pszStackSize);
- }
-
- return palError;
-}
-
-
/*++
Function:
CreateThreadData