diff --git a/CMakeLists.txt b/CMakeLists.txt index f0f2c75..5f2f432 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,14 @@ add_subdirectory(extern/benchmark_runner) add_subdirectory(lib/context_switcher) add_subdirectory(lib/pls) +# ...add a custom target that will only build the library when installing. +# This can allow us to speed up the installation on embedded devices. +ADD_CUSTOM_TARGET(install.pls + ${CMAKE_COMMAND} + -DBUILD_TYPE=${CMAKE_BUILD_TYPE} + -P ${CMAKE_BINARY_DIR}/cmake_install.cmake) +ADD_DEPENDENCIES(install.pls context_switcher pls) + # Include examples add_subdirectory(app/playground) add_subdirectory(app/benchmark_fft) diff --git a/README.md b/README.md index 4577263..ef33160 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,16 @@ This section will give a brief introduction on how to get a minimal project setup that uses the PLS library. -Further [general notes](NOTES.md) and [performance notes](PERFORMANCE.md) can be found in +Further [general notes](NOTES.md) and [performance notes](PERFORMANCE-v2.md) can be found in their respective files. -Further notes on [performance](PERFORMANCE.md) and general -[notes](NOTES.md) on the development progress can be found in -the linked documents. - - ### Installation +PLS has no external dependencies. To compile and install it you +only need cmake and a recent C++ 17 compatible compiler. +Care might be required on not explicitly supported systems +(currently we support Linux x86 and ARMv7). + Clone the repository and open a terminal session in its folder. Create a build folder using `mkdir cmake-build-release` and switch into it `cd cmake-build-release`. @@ -36,54 +36,57 @@ using `target_link_libraries(your_target pls::pls)`. #include #include +// Static memory allocation (see execution trees for how to configure) +static const int MAX_NUM_TASKS = 32; +static const int MAX_STACK_SIZE = 4096; +static const int NUM_THREADS = 8; + long fib(long n); int main() { - // All memory needed by the scheduler can be allocated in advance either on stack or using malloc. - const unsigned int num_threads = 8; - const unsigned int memory_per_thread = 2 << 14; - static pls::static_scheduler_memory memory; - - // Create the scheduler instance (starts a thread pool). - pls::scheduler scheduler{&memory, num_threads}; - - // Wake up the thread pool and perform work. - scheduler.perform_work([&] { - long result = fib(20); - std::cout << "fib(20)=" << result << std::endl; - }); - // At this point the thread pool sleeps. - // This can for example be used for periodic work. + // Create a scheduler with the static amount of resources. + // All memory and system resources are allocated here. + pls::scheduler scheduler{NUM_THREADS, MAX_NUM_TASKS, MAX_STACK_SIZE}; + + // Wake up the thread pool and perform work. + scheduler.perform_work([&] { + long result = fib(20); + std::cout << "fib(20)=" << result << std::endl; + }); + // At this point the thread pool sleeps. + // This can for example be used for periodic work. + + // The scheduler is destroyed at the end of the scope } long fib(long n) { - if (n == 0) { - return 0; - } - if (n == 1) { - return 1; - } - - // Example for the high level API. - // Will run both functions in parallel as seperate tasks. - int left, right; - pls::invoke_parallel( - [&] { left = fib(n - 1); }, - [&] { right = fib(n - 2); } - ); - return left + right; + if (n <= 1) { + return n; + } + + // Example for the high level API. + // Will run both functions in parallel as separate tasks. + int a, b; + pls::invoke( + [&a, n] { a = fib(n - 1); }, + [&b, n] { b = fib(n - 2); } + ); + return a + b; } - ``` +### Execution Trees and Static Resource Allocation + +TODO: For the static memory allocation you need to find the maximum required resources. + ## Project Structure The project uses [CMAKE](https://cmake.org/) as it's build system, the recommended IDE is either a simple text editor or [CLion](https://www.jetbrains.com/clion/). We divide the project into sub-targets to separate for the library itself, testing and example code. The library itself can be found in -`lib/pls`, testing related code is in `test`, example and playground -apps are in `app`. +`lib/pls`, the context switching implementation in `lib/context_switcher`, +testing related code is in `test`, example and playground/benchmark apps are in `app`. ### Buiding diff --git a/app/context_switch/deboost.context/CMakeLists.txt b/app/context_switch/deboost.context/CMakeLists.txt index 3a87e38..817cb61 100644 --- a/app/context_switch/deboost.context/CMakeLists.txt +++ b/app/context_switch/deboost.context/CMakeLists.txt @@ -74,6 +74,3 @@ target_include_directories(fcontext set_property(TARGET fcontext PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE) set_target_properties(fcontext PROPERTIES FOLDER Deps ${IOS_GENERAL_PROPERTIES}) -install(TARGETS fcontext DESTINATION lib) -install(FILES ${HEADER} DESTINATION include/fcontext) - diff --git a/app/playground/main.cpp b/app/playground/main.cpp index d6e3b6c..bc7f7d3 100644 --- a/app/playground/main.cpp +++ b/app/playground/main.cpp @@ -1,4 +1,40 @@ +#include +#include + +// Static memory allocation (see execution trees for how to configure) +static const int MAX_NUM_TASKS = 32; +static const int MAX_STACK_SIZE = 4096; +static const int NUM_THREADS = 8; + +long fib(long n); + int main() { + // Create a scheduler with the static amount of resources. + // All memory and system resources are allocated here. + pls::scheduler scheduler{NUM_THREADS, MAX_NUM_TASKS, MAX_STACK_SIZE}; + + // Wake up the thread pool and perform work. + scheduler.perform_work([&] { + long result = fib(20); + std::cout << "fib(20)=" << result << std::endl; + }); + // At this point the thread pool sleeps. + // This can for example be used for periodic work. + + // The scheduler is destroyed at the end of the scope +} + +long fib(long n) { + if (n <= 1) { + return n; + } - return 0; + // Example for the high level API. + // Will run both functions in parallel as separate tasks. + int a, b; + pls::invoke( + [&a, n] { a = fib(n - 1); }, + [&b, n] { b = fib(n - 2); } + ); + return a + b; } diff --git a/lib/context_switcher/CMakeLists.txt b/lib/context_switcher/CMakeLists.txt index 354cb26..f15027e 100644 --- a/lib/context_switcher/CMakeLists.txt +++ b/lib/context_switcher/CMakeLists.txt @@ -64,19 +64,31 @@ target_include_directories(context_switcher $ $ PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src # TODO: Set this up when we require private headers ) -# Installation on the system (we pack the context switcher with pls for now...) +# Rules for installing the library on a system +# ...binaries INSTALL(TARGETS context_switcher - EXPORT pls-targets + EXPORT context_switcher-targets LIBRARY DESTINATION lib/context_switcher ARCHIVE DESTINATION lib/context_switcher ) # ...all headers in `include` INSTALL( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/pls + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/context_switcher DESTINATION include FILES_MATCHING PATTERN "*.h*" ) +# ...allow our project to be a cmake dependency +install( + EXPORT context_switcher-targets + FILE context_switcherTargets.cmake + NAMESPACE context_switcher:: + DESTINATION lib/context_switcher +) +INSTALl( + FILES context_switcher-config.cmake + DESTINATION lib/context_switcher +) diff --git a/lib/context_switcher/context_switcher-config.cmake b/lib/context_switcher/context_switcher-config.cmake index 25d3a1f..40022ad 100644 --- a/lib/context_switcher/context_switcher-config.cmake +++ b/lib/context_switcher/context_switcher-config.cmake @@ -1,2 +1,2 @@ get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -include(${SELF_DIR}/plsTargets.cmake) +include(${SELF_DIR}/context_switcherTargets.cmake) diff --git a/lib/pls/CMakeLists.txt b/lib/pls/CMakeLists.txt index 3311e62..7c967fc 100644 --- a/lib/pls/CMakeLists.txt +++ b/lib/pls/CMakeLists.txt @@ -53,13 +53,6 @@ target_include_directories(pls ${CMAKE_CURRENT_SOURCE_DIR}/src # TODO: Set this up when we require private headers ) -# Enable warnings/tidy code checking from our compiler -target_compile_options(pls PRIVATE - $<$,$,$>: - -Wall> - $<$: - -W4>) - # Rules for installing the library on a system # ...binaries INSTALL(TARGETS pls @@ -84,10 +77,3 @@ INSTALl( FILES pls-config.cmake DESTINATION lib/pls ) -# ...add a custom target that will only build the library when installing. -# This can allow us to speed up the installation on embedded devices. -ADD_CUSTOM_TARGET(install.pls - ${CMAKE_COMMAND} - -DBUILD_TYPE=${CMAKE_BUILD_TYPE} - -P ${CMAKE_BINARY_DIR}/cmake_install.cmake) -ADD_DEPENDENCIES(install.pls context_switcher pls) diff --git a/lib/pls/pls-config.cmake b/lib/pls/pls-config.cmake index 25d3a1f..68792b9 100644 --- a/lib/pls/pls-config.cmake +++ b/lib/pls/pls-config.cmake @@ -1,2 +1,4 @@ +find_package(context_switcher REQUIRED) + get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) include(${SELF_DIR}/plsTargets.cmake)