Refactor message_handler app to be more test friendly

Fix importing indexed models, the inclusion of header files was not
working.

Change-Id: Idab7e002abc31f57acc4eda6a2f1cf2defdfd5c4
diff --git a/applications/message_handler/CMakeLists.txt b/applications/message_handler/CMakeLists.txt
index 040b27d..8d4ef54 100644
--- a/applications/message_handler/CMakeLists.txt
+++ b/applications/message_handler/CMakeLists.txt
@@ -21,27 +21,6 @@
     return()
 endif()
 
-set(MESSAGE_HANDLER_ARENA_SIZE 2000000 CACHE STRING "Total size of all message handler tensor arenas")
-set(MESSAGE_HANDLER_MODEL_0 FALSE CACHE STRING "Path to built in model 0")
-set(MESSAGE_HANDLER_MODEL_1 FALSE CACHE STRING "Path to built in model 1")
-set(MESSAGE_HANDLER_MODEL_2 FALSE CACHE STRING "Path to built in model 2")
-set(MESSAGE_HANDLER_MODEL_3 FALSE CACHE STRING "Path to built in model 3")
-
-ethosu_add_executable(message_handler
-    SOURCES
-        main.cpp
-        message_handler.cpp
-        message_queue.cpp
-    LIBRARIES
-        cmsis_device
-        $<$<TARGET_EXISTS:ethosu_core_driver>:ethosu_core_driver>
-        ethosu_mailbox
-        freertos_kernel
-        inference_process)
-
-target_include_directories(message_handler PRIVATE
-    ${LINUX_DRIVER_STACK_PATH}/kernel)
-
 # Split total tensor arena equally for each NPU
 if (TARGET ethosu_core_driver AND ETHOSU_TARGET_NPU_COUNT GREATER 0)
     set(NUM_ARENAS ${ETHOSU_TARGET_NPU_COUNT})
@@ -49,8 +28,27 @@
     set(NUM_ARENAS 1)
 endif()
 
+set(MESSAGE_HANDLER_ARENA_SIZE 2000000 CACHE STRING "Total size of all message handler tensor arenas")
 math(EXPR TENSOR_ARENA_SIZE "${MESSAGE_HANDLER_ARENA_SIZE} / ${NUM_ARENAS}")
 
+add_subdirectory(lib)
+
+set(MESSAGE_HANDLER_MODEL_0 "" CACHE STRING "Path to built in model 0")
+set(MESSAGE_HANDLER_MODEL_1 "" CACHE STRING "Path to built in model 1")
+set(MESSAGE_HANDLER_MODEL_2 "" CACHE STRING "Path to built in model 2")
+set(MESSAGE_HANDLER_MODEL_3 "" CACHE STRING "Path to built in model 3")
+
+ethosu_add_executable(message_handler
+    SOURCES
+        main.cpp
+    LIBRARIES
+        message_handler_lib
+        freertos_kernel)
+
+target_include_directories(message_handler PRIVATE
+    indexed_networks
+    ${LINUX_DRIVER_STACK_PATH}/kernel)
+
 target_compile_definitions(message_handler PRIVATE
     TENSOR_ARENA_SIZE=${TENSOR_ARENA_SIZE}
     $<$<BOOL:${MESSAGE_HANDLER_MODEL_0}>:MODEL_0=${MESSAGE_HANDLER_MODEL_0}>
diff --git a/applications/message_handler/indexed_networks/indexed_networks.hpp b/applications/message_handler/indexed_networks/indexed_networks.hpp
new file mode 100644
index 0000000..0b6d62a
--- /dev/null
+++ b/applications/message_handler/indexed_networks/indexed_networks.hpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2022 Arm Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INDEXED_NETWORKS_H
+#define INDEXED_NETWORKS_H
+
+#include "networks.hpp"
+
+#include <cstdio>
+#include <inttypes.h>
+
+#define XSTRINGIFY(src) #src
+#define STRINGIFY(src)  XSTRINGIFY(src)
+
+namespace {
+#if defined(__has_include)
+
+#if defined(MODEL_0)
+namespace Model0 {
+#include STRINGIFY(MODEL_0)
+}
+#endif
+
+#if defined(MODEL_1)
+namespace Model1 {
+#include STRINGIFY(MODEL_1)
+}
+#endif
+
+#if defined(MODEL_2)
+namespace Model2 {
+#include STRINGIFY(MODEL_2)
+}
+#endif
+
+#if defined(MODEL_3)
+namespace Model3 {
+#include STRINGIFY(MODEL_3)
+}
+#endif
+
+#endif
+} // namespace
+
+namespace MessageHandler {
+
+class WithIndexedNetworks : public BaseNetworks<WithIndexedNetworks> {
+public:
+    static bool getIndexedNetwork(const uint32_t index, void *&data, size_t &size) {
+        switch (index) {
+#if defined(MODEL_0)
+        case 0:
+            data = reinterpret_cast<void *>(Model0::networkModel);
+            size = sizeof(Model0::networkModel);
+            break;
+#endif
+
+#if defined(MODEL_1)
+        case 1:
+            data = reinterpret_cast<void *>(Model1::networkModel);
+            size = sizeof(Model1::networkModel);
+            break;
+#endif
+
+#if defined(MODEL_2)
+        case 2:
+            data = reinterpret_cast<void *>(Model2::networkModel);
+            size = sizeof(Model2::networkModel);
+            break;
+#endif
+
+#if defined(MODEL_3)
+        case 3:
+            data = reinterpret_cast<void *>(Model3::networkModel);
+            size = sizeof(Model3::networkModel);
+            break;
+#endif
+
+        default:
+            printf("Error: Network model index out of range. index=%" PRIu32 "\n", index);
+            return true;
+        }
+
+        return false;
+    }
+};
+
+} // namespace MessageHandler
+
+#endif
diff --git a/applications/message_handler/model_template.hpp b/applications/message_handler/indexed_networks/network_template.hpp
similarity index 100%
rename from applications/message_handler/model_template.hpp
rename to applications/message_handler/indexed_networks/network_template.hpp
diff --git a/applications/message_handler/lib/CMakeLists.txt b/applications/message_handler/lib/CMakeLists.txt
new file mode 100644
index 0000000..7e2826b
--- /dev/null
+++ b/applications/message_handler/lib/CMakeLists.txt
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2020-2022 Arm Limited.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the License); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+add_library(message_handler_lib STATIC)
+
+target_include_directories(message_handler_lib PUBLIC include
+                           PRIVATE ${LINUX_DRIVER_STACK_PATH}/kernel)
+
+target_link_libraries(message_handler_lib PUBLIC ethosu_mailbox
+        PRIVATE
+        cmsis_device
+        $<$<TARGET_EXISTS:ethosu_core_driver>:ethosu_core_driver>
+        freertos_kernel
+        inference_process
+        tflu)
+
+target_sources(message_handler_lib PRIVATE
+        message_handler.cpp
+        message_queue.cpp
+        core_driver_mutex.cpp
+        freertos_allocator.cpp)
diff --git a/applications/message_handler/lib/core_driver_mutex.cpp b/applications/message_handler/lib/core_driver_mutex.cpp
new file mode 100644
index 0000000..bc043fa
--- /dev/null
+++ b/applications/message_handler/lib/core_driver_mutex.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2022 Arm Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(ETHOSU)
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+#include <ethosu_driver.h>
+#include <stdio.h>
+
+extern "C" {
+
+void *ethosu_mutex_create(void) {
+    return xSemaphoreCreateMutex();
+}
+
+int ethosu_mutex_lock(void *mutex) {
+    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(mutex);
+    if (xSemaphoreTake(handle, portMAX_DELAY) != pdTRUE) {
+        printf("Error: Failed to lock mutex.\n");
+        return -1;
+    }
+    return 0;
+}
+
+int ethosu_mutex_unlock(void *mutex) {
+    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(mutex);
+    if (xSemaphoreGive(handle) != pdTRUE) {
+        printf("Error: Failed to unlock mutex.\n");
+        return -1;
+    }
+    return 0;
+}
+
+void *ethosu_semaphore_create(void) {
+    return xSemaphoreCreateBinary();
+}
+
+int ethosu_semaphore_take(void *sem) {
+    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(sem);
+    if (xSemaphoreTake(handle, portMAX_DELAY) != pdTRUE) {
+        printf("Error: Failed to take semaphore.\n");
+        return -1;
+    }
+    return 0;
+}
+
+int ethosu_semaphore_give(void *sem) {
+    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(sem);
+    if (xPortIsInsideInterrupt()) {
+        if (xSemaphoreGiveFromISR(handle, NULL) != pdTRUE) {
+            printf("Error: Failed to give semaphore from ISR.\n");
+            return -1;
+        }
+    } else {
+        /* A FreeRTOS binary semaphore is fundamentally a queue that can only hold one item. If the queue is full,
+         * xSemaphoreGive will return a pdFALSE value. Ignoring the return value in here, as a semaphore give failure
+         * does not affect the application correctness. */
+        if (xSemaphoreGive(handle) != pdTRUE) {
+            // do nothing
+        }
+    }
+    return 0;
+}
+}
+
+#endif
diff --git a/applications/message_handler/lib/freertos_allocator.cpp b/applications/message_handler/lib/freertos_allocator.cpp
new file mode 100644
index 0000000..c7fdba6
--- /dev/null
+++ b/applications/message_handler/lib/freertos_allocator.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2022 Arm Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FreeRTOS.h"
+#include <cstddef>
+#include <new>
+
+void *operator new(size_t size) {
+    return pvPortMalloc(size);
+}
+
+void *operator new[](size_t size) {
+    return pvPortMalloc(size);
+}
+
+void operator delete(void *ptr) {
+    vPortFree(ptr);
+}
+
+void operator delete(void *ptr, std::size_t) {
+    vPortFree(ptr);
+}
+
+void operator delete[](void *ptr) {
+    vPortFree(ptr);
+}
+
+void operator delete[](void *ptr, std::size_t) {
+    vPortFree(ptr);
+}
diff --git a/applications/message_handler/message_handler.hpp b/applications/message_handler/lib/include/message_handler.hpp
similarity index 93%
rename from applications/message_handler/message_handler.hpp
rename to applications/message_handler/lib/include/message_handler.hpp
index dd05059..3c227be 100644
--- a/applications/message_handler/message_handler.hpp
+++ b/applications/message_handler/lib/include/message_handler.hpp
@@ -24,6 +24,7 @@
 #include "semphr.h"
 
 #include "message_queue.hpp"
+#include "networks.hpp"
 #include <ethosu_core_interface.h>
 #if defined(ETHOSU)
 #include <ethosu_driver.h>
@@ -35,6 +36,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdio>
+#include <inttypes.h>
 #include <list>
 #include <vector>
 
@@ -121,7 +123,8 @@
                            Mailbox::Mailbox &mailbox,
                            std::shared_ptr<Queue<EthosU::ethosu_core_inference_req>> inferenceInputQueue,
                            QueueHandle_t inferenceOutputQueue,
-                           SemaphoreHandle_t messageNotify);
+                           SemaphoreHandle_t messageNotify,
+                           std::shared_ptr<Networks> networks);
 
     void run();
 
@@ -148,6 +151,7 @@
     QueueHandle_t inferenceOutputQueue;
     SemaphoreHandle_t messageNotify;
     EthosU::ethosu_core_msg_capabilities_rsp capabilities;
+    std::shared_ptr<Networks> networks;
 };
 
 class InferenceHandler {
@@ -156,7 +160,8 @@
                      size_t arenaSize,
                      std::shared_ptr<Queue<EthosU::ethosu_core_inference_req>> inferenceInputQueue,
                      QueueHandle_t inferenceOutputQueue,
-                     SemaphoreHandle_t messageNotify);
+                     SemaphoreHandle_t messageNotify,
+                     std::shared_ptr<Networks> networks);
 
     void run();
 
@@ -174,6 +179,7 @@
     InferenceProcess::InferenceProcess inference;
     EthosU::ethosu_core_inference_req *currentReq;
     EthosU::ethosu_core_inference_rsp *currentRsp;
+    std::shared_ptr<Networks> networks;
 };
 
 } // namespace MessageHandler
diff --git a/applications/message_handler/message_queue.hpp b/applications/message_handler/lib/include/message_queue.hpp
similarity index 100%
rename from applications/message_handler/message_queue.hpp
rename to applications/message_handler/lib/include/message_queue.hpp
diff --git a/applications/message_handler/lib/include/networks.hpp b/applications/message_handler/lib/include/networks.hpp
new file mode 100644
index 0000000..eb01d10
--- /dev/null
+++ b/applications/message_handler/lib/include/networks.hpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022 Arm Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETWORKS_H
+#define NETWORKS_H
+
+#include <ethosu_core_interface.h>
+
+#include <cstdio>
+#include <inttypes.h>
+
+using namespace EthosU;
+
+namespace MessageHandler {
+
+class Networks {
+public:
+    virtual ~Networks() {}
+    virtual bool getNetwork(const ethosu_core_network_buffer &buffer, void *&data, size_t &size) = 0;
+};
+
+template <typename T>
+class BaseNetworks : public Networks {
+public:
+    bool getNetwork(const ethosu_core_network_buffer &buffer, void *&data, size_t &size) override {
+        switch (buffer.type) {
+        case ETHOSU_CORE_NETWORK_BUFFER:
+            data = reinterpret_cast<void *>(buffer.buffer.ptr);
+            size = buffer.buffer.size;
+            return false;
+        case ETHOSU_CORE_NETWORK_INDEX:
+            return T::getIndexedNetwork(buffer.index, data, size);
+        default:
+            printf("Error: Unsupported network model type. type=%" PRIu32 "\n", buffer.type);
+            return true;
+        }
+    }
+};
+
+class NoIndexedNetworks : public BaseNetworks<NoIndexedNetworks> {
+    static bool getIndexedNetwork(const uint32_t index, void *&data, size_t &size) {
+        printf("Error: Network model index out of range. index=%" PRIu32 "\n", index);
+        return true;
+    }
+};
+
+} // namespace MessageHandler
+
+#endif
diff --git a/applications/message_handler/message_handler.cpp b/applications/message_handler/lib/message_handler.cpp
similarity index 86%
rename from applications/message_handler/message_handler.cpp
rename to applications/message_handler/lib/message_handler.cpp
index 4a3938e..7b6377f 100644
--- a/applications/message_handler/message_handler.cpp
+++ b/applications/message_handler/lib/message_handler.cpp
@@ -30,124 +30,28 @@
 #include "semphr.h"
 
 #include <cstring>
-#include <inttypes.h>
 #include <vector>
 
-#define XSTRINGIFY(src) #src
-#define STRINGIFY(src)  XSTRINGIFY(src)
-
 using namespace EthosU;
 using namespace MessageQueue;
 
-/****************************************************************************
- * Models
- ****************************************************************************/
-
-namespace {
-#if defined(__has_include)
-
-#if __has_include(STRINGIFY(MODEL_0))
-namespace Model0 {
-#include STRINGIFY(MODEL_0)
-}
-#endif
-
-#if __has_include(STRINGIFY(MODEL_1))
-namespace Model1 {
-#include STRINGIFY(MODEL_1)
-}
-#endif
-
-#if __has_include(STRINGIFY(MODEL_2))
-namespace Model2 {
-#include STRINGIFY(MODEL_2)
-}
-#endif
-
-#if __has_include(STRINGIFY(MODEL_3))
-namespace Model3 {
-#include STRINGIFY(MODEL_3)
-}
-#endif
-
-#endif
-} // namespace
-
 namespace MessageHandler {
 
 /****************************************************************************
  * IncomingMessageHandler
  ****************************************************************************/
 
-namespace {
-bool getNetwork(const ethosu_core_buffer &buffer, void *&data, size_t &size) {
-    data = reinterpret_cast<void *>(buffer.ptr);
-    size = buffer.size;
-    return false;
-}
-
-bool getNetwork(const uint32_t index, void *&data, size_t &size) {
-    switch (index) {
-#if __has_include(STRINGIFY(MODEL_0))
-    case 0:
-        data = reinterpret_cast<void *>(Model0::networkModel);
-        size = sizeof(Model0::networkModel);
-        break;
-#endif
-
-#if __has_include(STRINGIFY(MODEL_1))
-    case 1:
-        data = reinterpret_cast<void *>(Model1::networkModel);
-        size = sizeof(Model1::networkModel);
-        break;
-#endif
-
-#if __has_include(STRINGIFY(MODEL_2))
-    case 2:
-        data = reinterpret_cast<void *>(Model2::networkModel);
-        size = sizeof(Model2::networkModel);
-        break;
-#endif
-
-#if __has_include(STRINGIFY(MODEL_3))
-    case 3:
-        data = reinterpret_cast<void *>(Model3::networkModel);
-        size = sizeof(Model3::networkModel);
-        break;
-#endif
-
-    default:
-        printf("Error: Network model index out of range. index=%" PRIu32 "\n", index);
-        return true;
-    }
-
-    return false;
-}
-
-bool getNetwork(const ethosu_core_network_buffer &buffer, void *&data, size_t &size) {
-    switch (buffer.type) {
-    case ETHOSU_CORE_NETWORK_BUFFER:
-        return getNetwork(buffer.buffer, data, size);
-    case ETHOSU_CORE_NETWORK_INDEX:
-        return getNetwork(buffer.index, data, size);
-    default:
-        printf("Error: Unsupported network model type. type=%" PRIu32 "\n", buffer.type);
-        return true;
-    }
-}
-
-}; // namespace
-
 IncomingMessageHandler::IncomingMessageHandler(
     EthosU::ethosu_core_queue &_inputMessageQueue,
     EthosU::ethosu_core_queue &_outputMessageQueue,
     Mailbox::Mailbox &_mailbox,
     std::shared_ptr<Queue<EthosU::ethosu_core_inference_req>> _inferenceInputQueue,
     QueueHandle_t _inferenceOutputQueue,
-    SemaphoreHandle_t _messageNotify) :
+    SemaphoreHandle_t _messageNotify,
+    std::shared_ptr<Networks> _networks) :
     inputMessageQueue(_inputMessageQueue),
     outputMessageQueue(_outputMessageQueue), mailbox(_mailbox), inferenceInputQueue(_inferenceInputQueue),
-    inferenceOutputQueue(_inferenceOutputQueue), messageNotify(_messageNotify) {
+    inferenceOutputQueue(_inferenceOutputQueue), messageNotify(_messageNotify), networks(_networks) {
     mailbox.registerCallback(handleIrq, reinterpret_cast<void *>(this));
     readCapabilties(capabilities);
 }
@@ -384,7 +288,7 @@
     void *buffer;
     size_t size;
 
-    bool failed = getNetwork(network, buffer, size);
+    bool failed = networks->getNetwork(network, buffer, size);
 
     if (!failed) {
         failed = parser.parseModel(buffer,
@@ -467,9 +371,11 @@
                                    size_t arenaSize,
                                    std::shared_ptr<Queue<EthosU::ethosu_core_inference_req>> _inferenceInputQueue,
                                    QueueHandle_t _inferenceOutputQueue,
-                                   SemaphoreHandle_t _messageNotify) :
+                                   SemaphoreHandle_t _messageNotify,
+                                   std::shared_ptr<Networks> _networks) :
     inferenceInputQueue(_inferenceInputQueue),
-    inferenceOutputQueue(_inferenceOutputQueue), messageNotify(_messageNotify), inference(tensorArena, arenaSize) {}
+    inferenceOutputQueue(_inferenceOutputQueue), messageNotify(_messageNotify), inference(tensorArena, arenaSize),
+    networks(_networks) {}
 
 void InferenceHandler::run() {
     ethosu_core_inference_req req;
@@ -537,7 +443,7 @@
 }
 
 bool InferenceHandler::getInferenceJob(const ethosu_core_inference_req &req, InferenceProcess::InferenceJob &job) {
-    bool failed = getNetwork(req.network, job.networkModel.data, job.networkModel.size);
+    bool failed = networks->getNetwork(req.network, job.networkModel.data, job.networkModel.size);
     if (failed) {
         return true;
     }
diff --git a/applications/message_handler/message_queue.cpp b/applications/message_handler/lib/message_queue.cpp
similarity index 100%
rename from applications/message_handler/message_queue.cpp
rename to applications/message_handler/lib/message_queue.cpp
diff --git a/applications/message_handler/main.cpp b/applications/message_handler/main.cpp
index 0b4860a..caa778b 100644
--- a/applications/message_handler/main.cpp
+++ b/applications/message_handler/main.cpp
@@ -29,10 +29,12 @@
 #include <stdio.h>
 
 #include "ethosu_core_interface.h"
+#include "indexed_networks.hpp"
 #include "message_handler.hpp"
 #include "message_queue.hpp"
-#include <mailbox.hpp>
+#include "networks.hpp"
 
+#include <mailbox.hpp>
 #if defined(MHU_V2)
 #include <mhu_v2.hpp>
 #elif defined(MHU_JUNO)
@@ -83,94 +85,6 @@
 } // namespace
 
 /****************************************************************************
- * Override new operators to call in FreeRTOS allocator
- ****************************************************************************/
-
-void *operator new(size_t size) {
-    return pvPortMalloc(size);
-}
-
-void *operator new[](size_t size) {
-    return pvPortMalloc(size);
-}
-
-void operator delete(void *ptr) {
-    vPortFree(ptr);
-}
-
-void operator delete(void *ptr, std::size_t) {
-    vPortFree(ptr);
-}
-
-void operator delete[](void *ptr) {
-    vPortFree(ptr);
-}
-
-void operator delete[](void *ptr, std::size_t) {
-    vPortFree(ptr);
-}
-
-/****************************************************************************
- * Mutex & Semaphore
- ****************************************************************************/
-
-extern "C" {
-
-void *ethosu_mutex_create(void) {
-    return xSemaphoreCreateMutex();
-}
-
-int ethosu_mutex_lock(void *mutex) {
-    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(mutex);
-    if (xSemaphoreTake(handle, portMAX_DELAY) != pdTRUE) {
-        printf("Error: Failed to lock mutex.\n");
-        return -1;
-    }
-    return 0;
-}
-
-int ethosu_mutex_unlock(void *mutex) {
-    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(mutex);
-    if (xSemaphoreGive(handle) != pdTRUE) {
-        printf("Error: Failed to unlock mutex.\n");
-        return -1;
-    }
-    return 0;
-}
-
-void *ethosu_semaphore_create(void) {
-    return xSemaphoreCreateBinary();
-}
-
-int ethosu_semaphore_take(void *sem) {
-    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(sem);
-    if (xSemaphoreTake(handle, portMAX_DELAY) != pdTRUE) {
-        printf("Error: Failed to take semaphore.\n");
-        return -1;
-    }
-    return 0;
-}
-
-int ethosu_semaphore_give(void *sem) {
-    SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(sem);
-    if (xPortIsInsideInterrupt()) {
-        if (xSemaphoreGiveFromISR(handle, NULL) != pdTRUE) {
-            printf("Error: Failed to give semaphore from ISR.\n");
-            return -1;
-        }
-    } else {
-        /* A FreeRTOS binary semaphore is fundamentally a queue that can only hold one item. If the queue is full,
-         * xSemaphoreGive will return a pdFALSE value. Ignoring the return value in here, as a semaphore give failure
-         * does not affect the application correctness. */
-        if (xSemaphoreGive(handle) != pdTRUE) {
-            // do nothing
-        }
-    }
-    return 0;
-}
-}
-
-/****************************************************************************
  * Application
  ****************************************************************************/
 namespace {
@@ -179,13 +93,16 @@
     TaskParams() :
         messageNotify(xSemaphoreCreateBinary()),
         inferenceInputQueue(std::make_shared<Queue<ethosu_core_inference_req>>()),
-        inferenceOutputQueue(xQueueCreate(10, sizeof(ethosu_core_inference_rsp))) {}
+        inferenceOutputQueue(xQueueCreate(10, sizeof(ethosu_core_inference_rsp))),
+        networks(std::make_shared<WithIndexedNetworks>()) {}
 
     SemaphoreHandle_t messageNotify;
     // Used to pass inference requests to the inference runner task
     std::shared_ptr<Queue<ethosu_core_inference_req>> inferenceInputQueue;
     // Queue for message responses to the remote host
     QueueHandle_t inferenceOutputQueue;
+    // Networks provider
+    std::shared_ptr<Networks> networks;
 };
 
 struct InferenceTaskParams {
@@ -207,7 +124,8 @@
                              arenaSize,
                              params->taskParams->inferenceInputQueue,
                              params->taskParams->inferenceOutputQueue,
-                             params->taskParams->messageNotify);
+                             params->taskParams->messageNotify,
+                             params->taskParams->networks);
 
     process.run();
 }
@@ -221,7 +139,8 @@
                                    mailbox,
                                    params->inferenceInputQueue,
                                    params->inferenceOutputQueue,
-                                   params->messageNotify);
+                                   params->messageNotify,
+                                   params->networks);
 
 #ifdef MHU_IRQ
     // Register mailbox interrupt handler