Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API for specifying thread stack size #243

Merged
merged 21 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ function(enableSanitizer SANITIZER)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${SANITIZER}" PARENT_SCOPE)
endfunction()

if(KVS_DEFAULT_STACK_SIZE)
disa6302 marked this conversation as resolved.
Show resolved Hide resolved
message(STATUS "Building with default stack size")
jdelapla marked this conversation as resolved.
Show resolved Hide resolved
add_compile_definitions(KVS_DEFAULT_STACK_SIZE_BYTES=${KVS_DEFAULT_STACK_SIZE})
endif()

if(ADDRESS_SANITIZER)
enableSanitizer("address")
endif()
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ You can pass the following options to `cmake ..`
* `-DUNDEFINED_BEHAVIOR_SANITIZER` Build with UndefinedBehaviorSanitizer
* `-DBUILD_DEBUG_HEAP` Build debug heap with guard bands and validation. This is ONLY intended for low-level debugging purposes. Default is OFF
* `-DALIGNED_MEMORY_MODEL` Build for aligned memory model only devices. Default is OFF.
* `-DKVS_DEFAULT_STACK_SIZE` -- Value in bytes for default stack size of threads. Pthread minimum for Unix applications is 16 Kib.

### Build
To build the library run make in the build directory you executed CMake.
Expand Down
16 changes: 10 additions & 6 deletions src/common/include/com/amazonaws/kinesis/video/common/CommonDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ typedef VOID (*unlockMutex)(MUTEX);
typedef BOOL (*tryLockMutex)(MUTEX);
typedef VOID (*freeMutex)(MUTEX);
typedef STATUS (*createThread)(PTID, startRoutine, PVOID);
typedef STATUS (*createThreadWithParams)(PTID, startRoutine, SIZE_T, PVOID);
typedef STATUS (*joinThread)(TID, PVOID*);
typedef VOID (*threadSleep)(UINT64);
typedef VOID (*threadSleepUntil)(UINT64);
Expand Down Expand Up @@ -763,6 +764,7 @@ extern unlockMutex globalUnlockMutex;
extern tryLockMutex globalTryLockMutex;
extern freeMutex globalFreeMutex;
extern createThread globalCreateThread;
extern createThreadWithParams globalCreateThreadWithParams;
extern joinThread globalJoinThread;
extern threadSleep globalThreadSleep;
extern threadSleepUntil globalThreadSleepUntil;
Expand Down Expand Up @@ -1032,12 +1034,14 @@ extern PUBLIC_API atomicXor globalAtomicXor;
//
// Thread functionality
//
#define THREAD_CREATE globalCreateThread
#define THREAD_JOIN globalJoinThread
#define THREAD_SLEEP globalThreadSleep
#define THREAD_SLEEP_UNTIL globalThreadSleepUntil
#define THREAD_CANCEL globalCancelThread
#define THREAD_DETACH globalDetachThread
// Wrappers around OS specific utilities for threads. Takes arguments as given.
#define THREAD_CREATE globalCreateThread
#define THREAD_CREATE_WITH_PARAMS globalCreateThreadWithParams
hassanctech marked this conversation as resolved.
Show resolved Hide resolved
#define THREAD_JOIN globalJoinThread
#define THREAD_SLEEP globalThreadSleep
#define THREAD_SLEEP_UNTIL globalThreadSleepUntil
#define THREAD_CANCEL globalCancelThread
#define THREAD_DETACH globalDetachThread

//
// Static initializers
Expand Down
53 changes: 43 additions & 10 deletions src/utils/src/Thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ PUBLIC_API DWORD WINAPI startWrapperRoutine(LPVOID data)
return retVal;
}

PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID args)
PUBLIC_API STATUS defaultCreateThreadWithParams(PTID pThreadId, startRoutine start, SIZE_T stackSize, PVOID args)
{
STATUS retStatus = STATUS_SUCCESS;
HANDLE threadHandle;
Expand All @@ -51,7 +51,7 @@ PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID
pWrapper->storedArgs = args;
pWrapper->storedStartRoutine = start;

threadHandle = CreateThread(NULL, 0, startWrapperRoutine, pWrapper, 0, NULL);
threadHandle = CreateThread(NULL, stackSize, startWrapperRoutine, pWrapper, 0, NULL);
jdelapla marked this conversation as resolved.
Show resolved Hide resolved
CHK(threadHandle != NULL, STATUS_CREATE_THREAD_FAILED);

*pThreadId = (TID) threadHandle;
Expand All @@ -64,6 +64,21 @@ PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID
return retStatus;
}

PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID args)
{
STATUS retStatus = STATUS_SUCCESS;

#if defined(KVS_DEFAULT_STACK_SIZE_BYTES)
CHK_STATUS(defaultCreateThreadWithParams(pThreadId, start, (SIZE_T) KVS_DEFAULT_STACK_SIZE_BYTES, args));
#else
CHK_STATUS(defaultCreateThreadWithParams(pThreadId, start, 0, args));
#endif

CleanUp:

return retStatus;
}

PUBLIC_API STATUS defaultJoinThread(TID threadId, PVOID* retVal)
{
STATUS retStatus = STATUS_SUCCESS;
Expand Down Expand Up @@ -150,7 +165,7 @@ PUBLIC_API TID defaultGetThreadId()
return (TID) pthread_self();
}

PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID args)
PUBLIC_API STATUS defaultCreateThreadWithParams(PTID pThreadId, startRoutine start, SIZE_T stackSize, PVOID args)
{
STATUS retStatus = STATUS_SUCCESS;
pthread_t threadId;
Expand All @@ -159,14 +174,14 @@ PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID

CHK(pThreadId != NULL, STATUS_NULL_ARG);

#ifdef CONSTRAINED_DEVICE
pthread_attr_t attr;
pAttr = &attr;
result = pthread_attr_init(pAttr);
CHK_ERR(result == 0, STATUS_THREAD_ATTR_INIT_FAILED, "pthread_attr_init failed with %d", result);
result = pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE_ON_CONSTRAINED_DEVICE);
CHK_ERR(result == 0, STATUS_THREAD_ATTR_SET_STACK_SIZE_FAILED, "pthread_attr_setstacksize failed with %d", result);
#endif
if (stackSize != 0) {
pAttr = &attr;
result = pthread_attr_init(pAttr);
CHK_ERR(result == 0, STATUS_THREAD_ATTR_INIT_FAILED, "pthread_attr_init failed with %d", result);
result = pthread_attr_setstacksize(&attr, stackSize);
CHK_ERR(result == 0, STATUS_THREAD_ATTR_SET_STACK_SIZE_FAILED, "pthread_attr_setstacksize failed with %d", result);
}

result = pthread_create(&threadId, pAttr, start, args);
switch (result) {
Expand Down Expand Up @@ -198,6 +213,23 @@ PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID
return retStatus;
}

PUBLIC_API STATUS defaultCreateThread(PTID pThreadId, startRoutine start, PVOID args)
jdelapla marked this conversation as resolved.
Show resolved Hide resolved
{
STATUS retStatus = STATUS_SUCCESS;

#if defined(KVS_DEFAULT_STACK_SIZE_BYTES)
CHK_STATUS(defaultCreateThreadWithParams(pThreadId, start, (SIZE_T) KVS_DEFAULT_STACK_SIZE_BYTES, args));
#elif defined(CONSTRAINED_DEVICE)
jdelapla marked this conversation as resolved.
Show resolved Hide resolved
CHK_STATUS(defaultCreateThreadWithParams(pThreadId, start, (SIZE_T) THREAD_STACK_SIZE_ON_CONSTRAINED_DEVICE, args));
#else
CHK_STATUS(defaultCreateThreadWithParams(pThreadId, start, 0, args));
#endif

CleanUp:

return retStatus;
}

PUBLIC_API STATUS defaultJoinThread(TID threadId, PVOID* retVal)
{
STATUS retStatus = STATUS_SUCCESS;
Expand Down Expand Up @@ -330,6 +362,7 @@ PUBLIC_API VOID defaultThreadSleepUntil(UINT64 time)
getTId globalGetThreadId = defaultGetThreadId;
getTName globalGetThreadName = defaultGetThreadName;
createThread globalCreateThread = defaultCreateThread;
createThreadWithParams globalCreateThreadWithParams = defaultCreateThreadWithParams;
threadSleep globalThreadSleep = defaultThreadSleep;
threadSleepUntil globalThreadSleepUntil = defaultThreadSleepUntil;
joinThread globalJoinThread = defaultJoinThread;
Expand Down
55 changes: 55 additions & 0 deletions tst/utils/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,58 @@ TEST_F(ThreadFunctionalityTest, ThreadCreateAndCancel)

MUTEX_FREE(gThreadMutex);
}

TEST_F(ThreadFunctionalityTest, ThreadCreateAndReleaseSimpleCheckWithStack)
{
UINT64 index;
TID threads[TEST_THREAD_COUNT];
gThreadMutex = MUTEX_CREATE(FALSE);
srand(GETTIME());
SIZE_T threadStack = 64 * 1024;
struct sleep_times st[TEST_THREAD_COUNT];

gThreadCount = 0;

// Create the threads
for (index = 0; index < TEST_THREAD_COUNT; index++) {
st[index].threadVisited = FALSE;
st[index].threadCleared = FALSE;
st[index].threadSleepTime = index * HUNDREDS_OF_NANOS_IN_A_MILLISECOND;
EXPECT_EQ(STATUS_SUCCESS, THREAD_CREATE_WITH_PARAMS(&threads[index], testThreadRoutine, threadStack, (PVOID)&st[index]));
}

// Await for the threads to finish
for (index = 0; index < TEST_THREAD_COUNT; index++) {
EXPECT_EQ(STATUS_SUCCESS, THREAD_JOIN(threads[index], NULL));
}

MUTEX_LOCK(gThreadMutex);
EXPECT_EQ(0, gThreadCount);
MUTEX_UNLOCK(gThreadMutex);

for (index = 0; index < TEST_THREAD_COUNT; index++) {
EXPECT_TRUE(st[index].threadVisited) << "Thread didn't visit index " << index;
EXPECT_TRUE(st[index].threadCleared) << "Thread didn't clear index " << index;
jdelapla marked this conversation as resolved.
Show resolved Hide resolved
}

MUTEX_FREE(gThreadMutex);
}
jdelapla marked this conversation as resolved.
Show resolved Hide resolved
jdelapla marked this conversation as resolved.
Show resolved Hide resolved

TEST_F(ThreadFunctionalityTest, NegativeTest)
{
UINT64 index;
TID threads[TEST_THREAD_COUNT];
gThreadMutex = MUTEX_CREATE(FALSE);
SIZE_T threadStack = 16 * 1024;
struct sleep_times st[TEST_THREAD_COUNT];

gThreadCount = 0;
EXPECT_NE(STATUS_SUCCESS, THREAD_CREATE_WITH_PARAMS(NULL, testThreadRoutine, threadStack, NULL));
EXPECT_NE(STATUS_SUCCESS, THREAD_CREATE(NULL, testThreadRoutine, NULL));

MUTEX_LOCK(gThreadMutex);
EXPECT_EQ(0, gThreadCount);
MUTEX_UNLOCK(gThreadMutex);

MUTEX_FREE(gThreadMutex);
}
Loading