[InputService] Perform refactoring for input services
authorDongju Chae <dongju.chae@samsung.com>
Wed, 30 Jun 2021 05:37:44 +0000 (14:37 +0900)
committer채동주/On-Device Lab(SR)/Staff Engineer/삼성전자 <dongju.chae@samsung.com>
Thu, 1 Jul 2021 01:38:12 +0000 (10:38 +0900)
This patch performs refactoring for input services.

Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
src/core/meson.build
src/core/ne-handler.cc
src/core/ne-host-input-service.cc
src/core/ne-hw-input-service.cc
src/core/ne-inputservice.h
src/core/ne-request.cc [new file with mode: 0644]
src/core/ne-request.h [new file with mode: 0644]
src/core/ne-scheduler.cc
src/core/ne-scheduler.h
tests/unittests/ne_core_inputservice_test.cc

index c2c808b..cc54c65 100644 (file)
@@ -18,6 +18,7 @@ ne_core_sources = [
   'ne-handler.cc',
   'ne-profiler.cc',
   'ne-scheduler.cc',
+  'ne-request.cc',
   'ne-host-input-service.cc',
   'ne-hw-input-service.cc',
   'ne-thread-pool.cc'
index c4bb461..ceb5130 100644 (file)
@@ -1186,19 +1186,11 @@ TrinityVision2::removeRequest (int req_id) {
     return -ENOENT;
   }
 
-  if (req->isSubmitted ()) {
+  if (req->isSubmitted () && req->getOpmode () != NPUINPUT_HW_RECURRING) {
     logerr (TAG, "The request is not handled yet\n");
     return -EBUSY;
   }
 
-  if (req->getOpmode () == NPUINPUT_HW_RECURRING) {
-    int status = api_->stop_target (req_id);
-    if (status != 0) {
-      logerr (TAG, "Unable to stop the target request %d\n", req_id);
-      return status;
-    }
-  }
-
   scheduler_->removeRequest (req);
   return 0;
 }
index 4ccb0ba..aa5706e 100644 (file)
 std::unique_ptr<HostInputService> HostInputService::instance_;
 std::once_flag HostInputService::once_flag_;
 
+/**
+ * @brief get singleton instance
+ */
 HostInputService &
 HostInputService::getInstance () {
   call_once (once_flag_, []() { instance_.reset (new HostInputService); });
   return *(instance_.get ());
 }
 
-int
-HostInputService::submit (const DriverAPI *api, int id, const Model *model,
-                          HWmem *data, outputCallback callback,
-                          const npumgr_param *param) {
-  if (api == nullptr)
-    return -EINVAL;
-
-  if (dynamic_cast<Buffer *> (data)) {
-    /* empty model is possible */
-    return submit_buffer (api, id, model, dynamic_cast<Buffer *> (data),
-                          callback, param);
-  } else if (dynamic_cast<SegmentTable *> (data)) {
-    if (model == nullptr)
-      return -EINVAL;
-    return submit_segt (api, id, model, dynamic_cast<SegmentTable *> (data),
-                        callback, param);
-  } else {
-    return -EINVAL;
-  }
-}
-
 /**
  * @brief submit the request to the thread pool
- * @param[in] api the driver API
- * @param[in] id the request id
- * @param[in] model the target model
- * @param[in] buffer the target buffer
+ * @param[in] api device driver api
+ * @param[in] req request instance
  * @param[in] callback output callback
- * @return task id if no error, otherwise a negative errno.
+ * @return 0 if no error, otherwise a negative errno
  */
 int
-HostInputService::submit_buffer (const DriverAPI *api, int id,
-                                 const Model *model, Buffer *buffer,
-                                 outputCallback callback,
-                                 const npumgr_param *param) {
-  taskFunc func = std::bind (&HostInputService::invoke_buffer, this, api, model,
-                             buffer, callback, id, param);
-  ThreadTask *task = new ThreadTask (id, func);
+HostInputService::submit (const DriverAPI *api, const Request *req,
+                          outputCallback callback) {
+  if (api == nullptr || req == nullptr) {
+    logerr (TAG, "Invalid arguments\n");
+    return -EINVAL;
+  }
 
-  return ThreadPool::getInstance ().enqueueTask (task);
-}
+  if (req->getOpmode () != NPUINPUT_HOST) {
+    logerr (TAG, "Unmatched opmode\n");
+    return -EINVAL;
+  }
 
-/**
- * @brief submit the request to the thread pool
- * @param[in] api the driver API
- * @param[in] id the request id
- * @param[in] model the target model
- * @param[in] segt the target segment table
- * @param[in] callback output callback
- * @return 0 if no error, otherwise a negative errno.
- */
-int
-HostInputService::submit_segt (const DriverAPI *api, int id, const Model *model,
-                               SegmentTable *segt, outputCallback callback,
-                               const npumgr_param *param) {
-  taskFunc func = std::bind (&HostInputService::invoke_segt, this, api, model,
-                             segt, callback, id, param);
-  ThreadTask *task = new ThreadTask (id, func);
+  if (req->getInferData () == nullptr) {
+    logerr (TAG, "inference data is not set\n");
+    return -EINVAL;
+  }
 
+  taskFunc func =
+      std::bind (&HostInputService::invoke, this, api, req, callback);
+  ThreadTask *task = new ThreadTask (req->getID (), func);
   return ThreadPool::getInstance ().enqueueTask (task);
 }
 
 /**
  * @brief remove the submitted request (if possible)
+ * @param[in] api device driver api
  * @param[in] id the request id to be removed
  * @return 0 if no erorr. otherwise a negative errno
  */
 int
-HostInputService::remove (int id) {
+HostInputService::remove (const DriverAPI *api, int id) {
   return ThreadPool::getInstance ().removeTask (id);
 }
 
 /**
- * @brief invoke the request using APIs
- * @param[in] api the driver API
- * @param[in] model the target model
- * @param[in] buffer the target buffer
- * @param[in] callback output callback
- * @return 0 if no error, otherwise a negative errno
- * @note this function should be used with TRIV driver!
+ * @brief invoke inference with the buffer (TRIV-1)
+ * @param[in] api device driver api
+ * @param[in] req request instance
+ * @return 0 if no erorr. otherwise a negative errno
  */
-int
-HostInputService::invoke_buffer (const DriverAPI *api, const Model *model,
-                                 Buffer *buffer, outputCallback callback,
-                                 int req_id, const npumgr_param *param) {
-  input_config_t input_config;
-  device_state_t state;
-  int ret = -EINVAL;
-
-  state = api->isReady ();
-  if (state != device_state_t::TRINITY_STATE_READY) {
-    logerr (TAG, "device is not available to run inference %d\n", state);
-    goto handle_callback;
-  }
-
+static int
+invoke_buffer (const DriverAPI *api, const Request *req) {
   /** internal logic error */
-  assert (buffer != nullptr);
+  assert (api != nullptr);
+  assert (req != nullptr);
 
-  if (model != nullptr) {
-    /** consider NOP cases */
-    if (model->getProgramData () == nullptr) {
-      ret = 0;
-      goto handle_callback;
-    }
+  Buffer *buffer = dynamic_cast<Buffer *> (req->getInferData ());
+  assert (buffer != nullptr);
 
-    input_config.model_id = model->getInternalID ();
-  } else {
-    input_config.model_id = 0;
-  }
+  const Model *model = req->getModel ();
+  assert (model != nullptr);
 
+  input_config_t input_config;
+  input_config.model_id = model->getInternalID ();
   input_config.dbuf_fd = buffer->getDmabuf ();
+  input_config.req_id = req->getID ();
   input_config.activation_offset_addr0 = buffer->getOffset ();
   input_config.activation_offset_addr1 = buffer->getOffset ();
-  input_config.req_id = req_id;
+
+  /** npumgr-specific parameters */
+  const npumgr_param *param = req->getNpumgrParam ();
+  if (param != nullptr) {
+    input_config.task_handle = param->task_handle;
+    input_config.subtask_idx = param->subtask_idx;
+  } else {
+    input_config.task_handle = UINT32_MAX;
+    input_config.subtask_idx = UINT32_MAX;
+  }
 
   /** run the inference with the input */
-  ret = api->runInput (&input_config);
+  int ret = api->runInput (&input_config);
   if (ret < 0 && ret != -ECANCELED)
     logerr (TAG, "Failed to run the NPU inference: %d\n", ret);
 
-handle_callback:
-  /** should call the callback regardless of failure, to avoid deadlock */
-  if (callback != nullptr)
-    callback ();
-
   return ret;
 }
 
 /**
- * @brief invoke the request using APIs
- * @param[in] api the driver API
- * @param[in] model the target model
- * @param[in] segt the target segment table
- * @param[in] callback output callback
- * @return 0 if no error, otherwise a negative errno
- * @note this function should be used with TRIV2 driver!
+ * @brief invoke inference with the segment table (TRIV-2)
+ * @param[in] api device driver api
+ * @param[in] req request instance
+ * @return 0 if no erorr. otherwise a negative errno
  */
-int
-HostInputService::invoke_segt (const DriverAPI *api, const Model *model,
-                               SegmentTable *segt, outputCallback callback,
-                               int req_id, const npumgr_param *param) {
-  input_config_t input_config;
-  device_state_t state;
-  npuConstraint constraint;
-  int ret = -EINVAL;
+static int
+invoke_segt (const DriverAPI *api, const Request *req) {
+  /** internal logic error */
+  assert (api != nullptr);
+  assert (req != nullptr);
 
-  state = api->isReady ();
-  if (state != device_state_t::TRINITY_STATE_READY) {
-    logerr (TAG, "device is not available to run inference %d\n", state);
-    goto handle_callback;
-  }
+  SegmentTable *segt = dynamic_cast<SegmentTable *> (req->getInferData ());
+  assert (segt != nullptr);
 
-  /** internal logic error */
+  const Model *model = req->getModel ();
   assert (model != nullptr);
-  assert (segt != nullptr);
 
-  /** consider NOP cases */
-  if (model->getProgramData () == nullptr) {
-    ret = 0;
-    goto handle_callback;
-  }
+  input_config_t input_config;
+  input_config.model_id = model->getInternalID ();
+  input_config.dbuf_fd = segt->getDmabuf ();
+  input_config.req_id = req->getID ();
+  input_config.num_segments = segt->getNumTotalSegments ();
 
-  /** npumgr parameter setting if exists */
+  /** npumgr-specific parameters */
+  const npumgr_param *param = req->getNpumgrParam ();
   if (param != nullptr) {
     input_config.task_handle = param->task_handle;
     input_config.subtask_idx = param->subtask_idx;
@@ -198,18 +149,12 @@ HostInputService::invoke_segt (const DriverAPI *api, const Model *model,
     input_config.subtask_idx = UINT32_MAX;
   }
 
-  input_config.model_id = model->getInternalID ();
-  input_config.dbuf_fd = segt->getDmabuf ();
-  input_config.num_segments = segt->getNumTotalSegments ();
-
   /** set constraints */
-  constraint = model->getConstraint ();
+  npu_constraint constraint = model->getConstraint ();
   input_config.timeout_ms = constraint.timeout_ms;
   input_config.priority = constraint.priority;
-
   /** input handling by CPU. host inputservice only supports CPU mode */
   input_config.input_mode = TRINITY_INPUT_CPU;
-
   /** output handling by CPU, host inputservice only supports either interrupt or polling */
   if (constraint.notimode == NPU_POLLING) {
     input_config.output_mode = TRINITY_OUTPUT_CPU_POLL;
@@ -217,14 +162,59 @@ HostInputService::invoke_segt (const DriverAPI *api, const Model *model,
     input_config.output_mode = TRINITY_OUTPUT_CPU_INTR;
   }
 
-  input_config.req_id = req_id;
   /** run the inference with the input */
-  ret = api->runInput (&input_config);
+  int ret = api->runInput (&input_config);
   if (ret < 0 && ret != -ECANCELED)
     logerr (TAG, "Failed to run the NPU inference: %d\n", ret);
 
+  return ret;
+}
+
+/**
+ * @brief invoke the given request using the driver API
+ * @param[in] api device driver api
+ * @param[in] req request instance
+ * @param[in] callback output callback
+ * @return 0 if no error, otherwise a negative errno
+ */
+int
+HostInputService::invoke (const DriverAPI *api, const Request *req,
+                          outputCallback callback) {
+  device_state_t state;
+  const Model *model;
+  HWmem *data;
+  int ret = -EINVAL;
+
+  /** internal logic error */
+  assert (api != nullptr);
+  assert (req != nullptr);
+
+  model = req->getModel ();
+  if (model == nullptr) {
+    logerr (TAG, "unable to find the target model\n");
+    goto handle_callback;
+  }
+
+  state = api->isReady ();
+  if (state != device_state_t::TRINITY_STATE_READY) {
+    logerr (TAG, "device is not available to run inference %d\n", state);
+    goto handle_callback;
+  }
+
+  if (model->getProgramData () == nullptr) {
+    ret = 0;
+    goto handle_callback;
+  }
+
+  data = req->getInferData ();
+  if (dynamic_cast<Buffer *> (data))
+    ret = invoke_buffer (api, req);
+  else if (dynamic_cast<SegmentTable *> (data))
+    ret = invoke_segt (api, req);
+  else /* no inference data; skip */
+    ret = 0;
+
 handle_callback:
-  /** should call the callback regardless of failure, to avoid deadlock */
   if (callback != nullptr)
     callback ();
 
index 3315122..bea01b8 100644 (file)
@@ -30,74 +30,84 @@ HwInputService::getInstance () {
 }
 
 /**
- * @brief submit the request to the thread pool
- * @param[in] api the driver API
- * @param[in] id the request id
- * @param[in] model the target model
- * @param[in] data the inference data
+ * @brief submit the request directly
+ * @param[in] api device driver api
+ * @param[in] req request instance
  * @param[in] callback output callback
- * @return req_id if no error, otherwise a negative errno.
+ * @return 0 if no error, otherwise a negativ errno
  */
 int
-HwInputService::submit (const DriverAPI *api, int id, const Model *model,
-                        HWmem *data, outputCallback callback,
-                        const npumgr_param *param) {
-  if (api == nullptr || model == nullptr)
+HwInputService::submit (const DriverAPI *api, const Request *req,
+                        outputCallback callback) {
+  if (api == nullptr || req == nullptr) {
+    logerr (TAG, "Invalid arguments\n");
     return -EINVAL;
+  }
+
+  if (req->getOpmode () != NPUINPUT_HW_RECURRING) {
+    logerr (TAG, "Unmatched opmode\n");
+    return -EINVAL;
+  }
 
-  SegmentTable *segt = dynamic_cast<SegmentTable *> (data);
-  if (segt == nullptr)
+  if (req->getInferData () == nullptr) {
+    logerr (TAG, "inference data is not set\n");
     return -EINVAL;
+  }
 
-  return invoke (api, model, segt, callback, id, param);
+  return invoke (api, req, callback);
 }
 
 /**
- * @brief invoke the request using APIs
- * @param[in] api the driver API
- * @param[in] model the target model
- * @param[in] segt the target segment table
- * @param[in] callback output callback
- * @return req_id if no error, otherwise a negative errno
+ * @brief remove the submitted request (if possible)
+ * @param[in] api device driver api
+ * @param[in] id the request id to be removed
+ * @return 0 if no erorr. otherwise a negative errno
  */
 int
-HwInputService::invoke (const DriverAPI *api, const Model *model,
-                        SegmentTable *segt, outputCallback callback, int req_id,
-                        const npumgr_param *param) {
-  input_config_t input_config;
-  device_state_t state;
-  npuConstraint constraint;
-  int ret = -EINVAL;
-
-  state = api->isReady ();
-  if (state != device_state_t::TRINITY_STATE_READY) {
-    logerr (TAG, "device is not available to run inference %d\n", state);
-    goto handle_callback;
+HwInputService::remove (const DriverAPI *api, int id) {
+  if (api == nullptr || id < 0) {
+    logerr (TAG, "Invalid arguments\n");
+    return -EINVAL;
   }
 
-  if (model == nullptr) {
-    logerr (TAG, "No valid model provided\n");
-    goto handle_callback;
-  }
+  return api->stop_target (id);
+}
 
-  /** consider NOP cases */
-  if (model->getProgramData () == nullptr) {
-    ret = 0;
-    goto handle_callback;
-  }
+/**
+ * @brief invoke inference with the segment table (TRIV-2)
+ * @param[in] api device driver api
+ * @param[in] req request instance
+ * @return 0 if no erorr. otherwise a negative errno
+ */
+static int
+invoke_segt (const DriverAPI *api, const Request *req) {
+  /** internal logic error */
+  assert (api != nullptr);
+  assert (req != nullptr);
 
+  SegmentTable *segt = dynamic_cast<SegmentTable *> (req->getInferData ());
+  assert (segt != nullptr);
+
+  const Model *model = req->getModel ();
+  assert (model != nullptr);
+
+  input_config_t input_config;
   input_config.model_id = model->getInternalID ();
-  if (segt != nullptr) {
-    input_config.dbuf_fd = segt->getDmabuf ();
-    input_config.num_segments = segt->getNumTotalSegments ();
+  input_config.dbuf_fd = segt->getDmabuf ();
+  input_config.req_id = req->getID ();
+  input_config.num_segments = segt->getNumTotalSegments ();
+
+  /** npumgr-specific parameters */
+  const npumgr_param *param = req->getNpumgrParam ();
+  if (param != nullptr) {
+    input_config.task_handle = param->task_handle;
+    input_config.subtask_idx = param->subtask_idx;
   } else {
-    /** some instructions do not require the segment table (e.g., nop) */
-    input_config.dbuf_fd = -1;
-    input_config.num_segments = 0;
+    input_config.task_handle = UINT32_MAX;
+    input_config.subtask_idx = UINT32_MAX;
   }
 
   /** set constraints */
-  constraint = model->getConstraint ();
   input_config.timeout_ms = 0; /* immediatedly handled */
   input_config.priority = NPU_PRIORITY_HIGH;
   input_config.input_mode = TRINITY_INPUT_HW;
@@ -107,23 +117,52 @@ HwInputService::invoke (const DriverAPI *api, const Model *model,
   input_config.hw_input_seg = model->getMetadata ()->getInputSegmentIndex (0);
   input_config.hw_output_seg = model->getMetadata ()->getOutputSegmentIndex (0);
 
-  /** npumgr parameter setting if exists */
-  if (param != nullptr) {
-    input_config.task_handle = param->task_handle;
-    input_config.subtask_idx = param->subtask_idx;
-  } else {
-    input_config.task_handle = UINT32_MAX;
-    input_config.subtask_idx = UINT32_MAX;
-  }
-  input_config.req_id = req_id;
-
   /** run the inference with the input */
-  ret = api->runInput (&input_config);
+  int ret = api->runInput (&input_config);
   if (ret < 0 && ret != -ECANCELED)
     logerr (TAG, "Failed to run the NPU inference: %d\n", ret);
 
+  return ret;
+}
+
+/**
+ * @brief invoke the given request using the driver API
+ * @param[in] api device driver api
+ * @param[in] req request instance
+ * @param[in] callback output callback
+ * @return req_id if no error, otherwise a negative errno
+ */
+int
+HwInputService::invoke (const DriverAPI *api, const Request *req,
+                        outputCallback callback) {
+  device_state_t state;
+  const Model *model;
+  HWmem *data;
+  int ret = -EINVAL;
+
+  /** internal logic error */
+  assert (api != nullptr);
+  assert (req != nullptr);
+
+  model = req->getModel ();
+  if (model == nullptr || model->getProgramData () == nullptr) {
+    logerr (TAG, "unable to find the target model\n");
+    goto handle_callback;
+  }
+
+  state = api->isReady ();
+  if (state != device_state_t::TRINITY_STATE_READY) {
+    logerr (TAG, "device is not available to run inference %d\n", state);
+    goto handle_callback;
+  }
+
+  data = req->getInferData ();
+  if (dynamic_cast<SegmentTable *> (data))
+    ret = invoke_segt (api, req);
+  else /* no inference data; skip */
+    ret = 0;
+
 handle_callback:
-  /** should call the callback regardless of failure, to avoid deadlock */
   if (callback != nullptr)
     callback ();
 
index e97f076..0df702f 100644 (file)
@@ -22,6 +22,7 @@
 #include "ne-model.h"
 #include "ne-buffer.h"
 #include "ne-segment-table.h"
+#include "ne-request.h"
 
 #include <memory>
 #include <mutex>
 class InputService {
  public:
   /** @brief submit request to somewhere (depends on each impl.) */
-  virtual int submit (const DriverAPI *api, int request_id, const Model *model,
-                      HWmem *data, outputCallback callback = nullptr,
-                      const npumgr_param *param = nullptr) {
+  virtual int submit (const DriverAPI *api, const Request *request,
+                      outputCallback callback = nullptr) {
     return -EPERM;
   }
-  /** @brief [OPTIONAL] remove the submitted request (if possible) */
-  virtual int remove (int request_id) { return -EINVAL; }
-
+  /** @brief remove the submitted request (if possible) */
+  virtual int remove (const DriverAPI *api, int request_id) { return -EPERM; }
   virtual ~InputService () {}
 
  protected:
@@ -49,27 +48,15 @@ class HostInputService : public InputService {
  public:
   static HostInputService &getInstance ();
 
-  int submit (const DriverAPI *api, int request_id, const Model *model,
-              HWmem *data, outputCallback callback = nullptr,
-              const npumgr_param *param = nullptr);
-  int remove (int request_id);
+  int submit (const DriverAPI *api, const Request *request,
+              outputCallback callback = nullptr);
+  int remove (const DriverAPI *api, int request_id);
 
  private:
-  int submit_buffer (const DriverAPI *api, int request_id, const Model *model,
-                     Buffer *buffer, outputCallback callback = nullptr,
-                     const npumgr_param *param = nullptr);
-  int submit_segt (const DriverAPI *api, int request_id, const Model *model,
-                   SegmentTable *segt, outputCallback callback = nullptr,
-                   const npumgr_param *param = nullptr);
-
   /** do not allow to directly call invoke () */
-  int invoke_buffer (const DriverAPI *api, const Model *model, Buffer *buffer,
-                     outputCallback callback, int task_id,
-                     const npumgr_param *param);
-  int invoke_segt (const DriverAPI *api, const Model *model, SegmentTable *segt,
-                   outputCallback callback, int task_id,
-                   const npumgr_param *param);
-
+  int invoke (const DriverAPI *api, const Request *request,
+              outputCallback callback = nullptr);
+  /** singleton pattern */
   static std::unique_ptr<HostInputService> instance_;
   static std::once_flag once_flag_;
 };
@@ -79,16 +66,14 @@ class HwInputService : public InputService {
  public:
   static HwInputService &getInstance ();
 
-  int submit (const DriverAPI *api, int request_id, const Model *model,
-              HWmem *data, outputCallback callback = nullptr,
-              const npumgr_param *param = nullptr);
+  int submit (const DriverAPI *api, const Request *request,
+              outputCallback callback = nullptr);
+  int remove (const DriverAPI *api, int request_id);
 
  private:
-  /** do not allow to directly call invoke () */
-  int invoke (const DriverAPI *api, const Model *model, SegmentTable *segt,
-              outputCallback callback, int task_id,
-              const npumgr_param *param = nullptr);
-
+  int invoke (const DriverAPI *api, const Request *request,
+              outputCallback callback = nullptr);
+  /** singleton pattern */
   static std::unique_ptr<HwInputService> instance_;
   static std::once_flag once_flag_;
 };
diff --git a/src/core/ne-request.cc b/src/core/ne-request.cc
new file mode 100644 (file)
index 0000000..6f24640
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * Proprietary
+ * Copyright (C) 2021 Samsung Electronics
+ * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file ne-request.cc
+ * @date 30 June 2021
+ * @brief Implementation of the request class
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include "ne-request.h"
+
+std::atomic<int> Request::global_request_id_ (1);
+
+/** @brief constructor of request class */
+Request::Request ()
+    : opmode_ (NPUINPUT_HOST),
+      force_stop_ (false),
+      stopped_ (false),
+      preserved_ (false),
+      submitted_ (false),
+      model_ (nullptr),
+      data_ (nullptr),
+      cb_ (nullptr),
+      out_bufs_ (nullptr),
+      infer_mode_ (NPU_INFER_BLOCKING /* default */),
+      npumgr_param_ (nullptr) {
+  request_id_ = Request::global_request_id_.fetch_add (1);
+}
+
+/** @brief destructor of request class */
+Request::~Request () {
+  if (npumgr_param_ != nullptr)
+    delete npumgr_param_;
+
+  if (data_ != nullptr)
+    delete data_;
+}
diff --git a/src/core/ne-request.h b/src/core/ne-request.h
new file mode 100644 (file)
index 0000000..2559aef
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Proprietary
+ * Copyright (C) 2021 Samsung Electronics
+ * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file ne-request.h
+ * @date 30 June 2021
+ * @brief Internal data structure for requests.
+ * @see https://code.sec.samsung.net/confluence/display/ODLC/2020+Overall+Software+Stack
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+#ifndef NE_REQUEST_H__
+#define NE_REQUEST_H__
+
+#include <atomic>
+
+#include <typedef.h>
+
+#include "ne-model.h"
+#include "ne-hwmem.h"
+
+/** @brief class def. of requests created from host handler */
+
+class Request {
+ public:
+  Request ();
+  ~Request ();
+
+  void setModel (const Model *model) { model_ = model; }
+  const Model *getModel () const { return model_; }
+
+  void setInferData (HWmem *data) { data_ = data; }
+  HWmem *getInferData () const { return data_; }
+
+  void setCallback (outputCallback cb) { cb_ = cb; }
+  outputCallback getCallback () const { return cb_; }
+
+  void setForceStop (bool force_stop) { force_stop_ = force_stop; }
+  bool getForceStop () const { return force_stop_; }
+
+  void setPreserved (bool preserved) { preserved_ = preserved; }
+  bool isPreserved () const { return preserved_; }
+
+  void setSubmitted (bool submitted) { submitted_ = submitted; }
+  bool isSubmitted () const { return submitted_; }
+
+  void setOpmode (npu_input_opmode opmode) { opmode_ = opmode; }
+  npu_input_opmode getOpmode () const { return opmode_; }
+  int getID () const { return request_id_; }
+
+  void setStopped () { stopped_ = true; }
+  bool isStopped () const { return stopped_; }
+
+  void setHwDevice (std::string hw_dev) { hw_dev_ = hw_dev; }
+  std::string getHwDevice () const { return hw_dev_; }
+
+  void setOutputBuffers (output_buffers *out_bufs) { out_bufs_ = out_bufs; }
+  output_buffers *getOutputBuffers () const { return out_bufs_; }
+
+  void setInferMode (npu_infer_mode infer_mode) { infer_mode_ = infer_mode; }
+  npu_infer_mode getInferMode () const { return infer_mode_; }
+
+  void setNpumgrParam (const npumgr_param &param) {
+    if (npumgr_param_ == nullptr)
+      npumgr_param_ = new npumgr_param;
+    memcpy (npumgr_param_, &param, sizeof (npumgr_param));
+  }
+  const npumgr_param *getNpumgrParam () const { return npumgr_param_; }
+
+ private:
+  static std::atomic<int> global_request_id_;
+  int request_id_; /**< request id */
+
+  npu_input_opmode opmode_; /**< opmode of the request */
+  bool force_stop_;         /**< indicates force stop */
+  bool stopped_;            /**< stopped request */
+  bool preserved_;          /**< preserved request */
+  bool submitted_;          /**< submitted request */
+
+  const Model *model_; /**< model of the request */
+  HWmem *data_;        /**< inference data of the request */
+
+  outputCallback cb_;        /**< request callback */
+  output_buffers *out_bufs_; /**< output buffers */
+  std::string hw_dev_;       /**< HW device path */
+
+  npu_infer_mode infer_mode_;
+  npumgr_param *npumgr_param_;
+};
+
+#endif /* NE_REQUEST_H__ */
index 290cb9a..9dacc6a 100644 (file)
 
 #define TAG _N3
 
-std::atomic<int> Request::global_request_id_ (1);
-
-/** @brief constructor of request class */
-Request::Request ()
-    : opmode_ (NPUINPUT_HOST),
-      force_stop_ (false),
-      stopped_ (false),
-      preserved_ (false),
-      submitted_ (false),
-      model_ (nullptr),
-      data_ (nullptr),
-      cb_ (nullptr),
-      out_bufs_ (nullptr),
-      infer_mode_ (NPU_INFER_BLOCKING /* default */),
-      npumgr_param_ (nullptr) {
-  request_id_ = Request::global_request_id_.fetch_add (1);
-}
-
-/** @brief destructor of request class */
-Request::~Request () {
-  if (npumgr_param_ != nullptr)
-    delete npumgr_param_;
-
-  if (data_ != nullptr)
-    delete data_;
-}
-
 /** @brief destructor of scheduler class */
 Scheduler::~Scheduler () {
   /** wait until all callbacks are called */
@@ -77,11 +50,11 @@ getInputService (npu_input_opmode opmode) {
 int
 Scheduler::handleStop (Request *req) {
   if (req->getForceStop ()) {
-    std::function<bool(Request *)> functor = [](Request *r) -> bool {
+    std::function<bool(Request *)> functor = [this](Request *r) -> bool {
       InputService *service = getInputService (r->getOpmode ());
 
       /* remove a request if it's not scheduled */
-      if (service->remove (r->getID ()) != 0) {
+      if (service->remove (api_, r->getID ()) != 0) {
         /* In case of already-served requests, let's mark it as stopped */
         r->setStopped ();
         return false;
@@ -106,47 +79,6 @@ Scheduler::handleStop (Request *req) {
 }
 
 /**
- * @brief handle inference request with input data from host
- * @param[in] req the request instance
- * @param[in] service the input service
- * @return 0 if no error. otherwise a negative errno.
- */
-int
-Scheduler::handleHostInput (Request *req, InputService *service) {
-  int req_id = req->getID ();
-  const Model *model = req->getModel ();
-  HWmem *data = req->getInferData ();
-  auto callback = std::bind (&Scheduler::handleCallback, this, req);
-  const npumgr_param *param = req->getNpumgrParam ();
-
-  req->setSubmitted (true);
-
-  int status = service->submit (api_, req_id, model, data, callback, param);
-  if (status < 0)
-    req->setSubmitted (false);
-
-  return status;
-}
-
-/**
- * @brief handle inference request with input data from hw device
- * @param[in] req the request instance
- * @param[in] service the input service
- * @return 0 if no error. otherwise a negative errno.
- */
-int
-Scheduler::handleHwInput (Request *req, InputService *service) {
-  int req_id = req->getID ();
-  const Model *model = req->getModel ();
-  HWmem *data = req->getInferData ();
-  auto callback = std::bind (&Scheduler::handleCallback, this, req);
-  const npumgr_param *param = req->getNpumgrParam ();
-
-  /* task id is obtained from a device driver */
-  return service->submit (api_, req_id, model, data, callback, param);
-}
-
-/**
  * @brief create a request to be scheduled
  * @return new request instance
  */
@@ -164,8 +96,16 @@ Scheduler::createRequest () {
  */
 void
 Scheduler::removeRequest (Request *req) {
-  if (req)
-    request_map_.remove (req->getID ());
+  if (!req)
+    return;
+
+  InputService *service;
+  int req_id = req->getID ();
+
+  service = getInputService (req->getOpmode ());
+  if (service)
+    service->remove (api_, req_id);
+  request_map_.remove (req_id);
 }
 
 /**
@@ -187,20 +127,22 @@ Scheduler::submitRequest (Request *req) {
   }
 
   npu_input_opmode opmode = req->getOpmode ();
-  InputService *service = getInputService (opmode);
+  if (opmode == NPUINPUT_STOP)
+    return handleStop (req);
 
-  switch (opmode) {
-    case NPUINPUT_STOP:
-      return handleStop (req);
-    case NPUINPUT_HOST:
-      return handleHostInput (req, service);
-      break;
-    case NPUINPUT_HW_RECURRING:
-      return handleHwInput (req, service);
-      break;
-    default:
-      return -EINVAL;
+  InputService *service = getInputService (opmode);
+  if (!service) {
+    logerr (TAG, "No available input service for opmode %d\n", opmode);
+    return -ENOENT;
   }
+
+  req->setSubmitted (true);
+  int ret = service->submit (api_, req,
+                             std::bind (&Scheduler::handleCallback, this, req));
+  if (ret != 0)
+    req->setSubmitted (false);
+
+  return ret;
 }
 
 /**
index 4c889a2..b462dbe 100644 (file)
 #include "ne-utils.h"
 #include "ne-common.h"
 #include "ne-inputservice.h"
+#include "ne-request.h"
 
 #include <atomic>
 
-/** @brief class def. of requests created from host handler */
-
-class Request {
- public:
-  Request ();
-  ~Request ();
-
-  void setModel (const Model *model) { model_ = model; }
-  const Model *getModel () { return model_; }
-
-  void setInferData (HWmem *data) { data_ = data; }
-  HWmem *getInferData () { return data_; }
-
-  void setCallback (outputCallback cb) { cb_ = cb; }
-  outputCallback getCallback () { return cb_; }
-
-  void setForceStop (bool force_stop) { force_stop_ = force_stop; }
-  bool getForceStop () { return force_stop_; }
-
-  void setPreserved (bool preserved) { preserved_ = preserved; }
-  bool isPreserved () { return preserved_; }
-
-  void setSubmitted (bool submitted) { submitted_ = submitted; }
-  bool isSubmitted () { return submitted_; }
-
-  void setOpmode (npu_input_opmode opmode) { opmode_ = opmode; }
-  npu_input_opmode getOpmode () { return opmode_; }
-  int getID () { return request_id_; }
-
-  void setStopped () { stopped_ = true; }
-  bool isStopped () { return stopped_; }
-
-  void setHwDevice (std::string hw_dev) { hw_dev_ = hw_dev; }
-  std::string getHwDevice () { return hw_dev_; }
-
-  void setOutputBuffers (output_buffers *out_bufs) { out_bufs_ = out_bufs; }
-  output_buffers *getOutputBuffers () { return out_bufs_; }
-
-  void setInferMode (npu_infer_mode infer_mode) { infer_mode_ = infer_mode; }
-  npu_infer_mode getInferMode () { return infer_mode_; }
-
-  void setNpumgrParam (const npumgr_param &param) {
-    if (npumgr_param_ == nullptr)
-      npumgr_param_ = new npumgr_param;
-    memcpy (npumgr_param_, &param, sizeof (npumgr_param));
-  }
-  const npumgr_param *getNpumgrParam () { return npumgr_param_; }
-
- private:
-  static std::atomic<int> global_request_id_;
-  int request_id_; /**< request id */
-
-  npu_input_opmode opmode_; /**< opmode of the request */
-  bool force_stop_;         /**< indicates force stop */
-  bool stopped_;            /**< stopped request */
-  bool preserved_;          /**< preserved request */
-  bool submitted_;          /**< submitted request */
-
-  const Model *model_; /**< model of the request */
-  HWmem *data_;        /**< inference data of the request */
-
-  outputCallback cb_;        /**< request callback */
-  output_buffers *out_bufs_; /**< output buffers */
-  std::string hw_dev_;       /**< HW device path */
-
-  npu_infer_mode infer_mode_;
-  npumgr_param *npumgr_param_;
-};
-
 /** @brief class def. of scheduler to handle requests */
 class Scheduler {
  public:
index bd0ef3b..e0428b4 100644 (file)
@@ -32,26 +32,27 @@ TEST (ne_core_inputservice_test, instance_singleton) {
 }
 
 /**
- * @brief test features of submit() with a buffer
+ * @brief test features of submit() with host input service
  */
-TEST (ne_core_inputservice_test, host_submit) {
+TEST (ne_core_inputservice_test, submit_host_service) {
   std::unique_ptr<DriverAPI> api;
+  npu_input_opmode opmode = NPUINPUT_HOST;
 
   api = DriverAPI::createDriverAPI (NPUCOND_TRIV2_CONN_SOCIP, 0);
   ASSERT_NE (api.get (), nullptr);
 
-  /** create dummy model & buffer */
-
-  Model *model = new Model (new HWmemDevice);
+  /** create dummy model */
+  std::unique_ptr<Model> model (new Model (new HWmemDevice));
   model->setDriverAPI (api.get ());
   EXPECT_EQ (model->alloc (4096), 0);
 
-  Buffer *buffer = new Buffer (new HWmemDevice);
-  buffer->setDriverAPI (api.get ());
-  EXPECT_EQ (buffer->alloc (4096), 0);
+  std::unique_ptr<Request> req (new Request ());
+  req->setOpmode (opmode);
+  req->setModel (model.get ());
+  req->setInferData (new SegmentTable (new HWmemDevice));
 
   HostInputService &service = HostInputService::getInstance ();
-  EXPECT_EQ (service.submit (api.get (), 1, model, buffer), 0);
+  EXPECT_EQ (service.submit (api.get (), req.get ()), 0);
 
   usleep (TEST_SLEEP_MS);
 
@@ -60,116 +61,131 @@ TEST (ne_core_inputservice_test, host_submit) {
   std::mutex m;
 
   auto callback = std::bind (test_callback, &num_called, &m, &cv);
-  EXPECT_EQ (service.submit (api.get (), 2, model, buffer, callback), 0);
-  EXPECT_EQ (service.submit (api.get (), 3, model, buffer, callback), 0);
-  EXPECT_EQ (service.submit (api.get (), 4, model, buffer, callback), 0);
+
+  EXPECT_EQ (service.submit (api.get (), req.get (), callback), 0);
+
+  std::unique_ptr<Request> req2 (new Request ());
+  req2->setOpmode (opmode);
+  req2->setModel (model.get ());
+  req2->setInferData (new Buffer (new HWmemDevice));
+
+  EXPECT_EQ (service.submit (api.get (), req2.get (), callback), 0);
+
+  std::unique_ptr<Request> req3 (new Request ());
+  req3->setOpmode (opmode);
+  req3->setModel (model.get ());
+  req3->setInferData (new SegmentTable (new HWmemDevice));
+
+  EXPECT_EQ (service.submit (api.get (), req3.get (), callback), 0);
 
   wait_callbacks (num_called, 3, m, cv);
   EXPECT_EQ (num_called, 3);
-
-  delete model;
-  delete buffer;
 }
 
 /**
  * @brief test features of submit() with error handling
  */
-TEST (ne_core_inputservice_test, host_submit_args_n) {
+TEST (ne_core_inputservice_test, submit_host_service_args_n) {
   std::unique_ptr<DriverAPI> api;
+  npu_input_opmode opmode = NPUINPUT_HOST;
+
   api = DriverAPI::createDriverAPI (NPUCOND_TRIV2_CONN_SOCIP, 0);
   ASSERT_NE (api.get (), nullptr);
 
   /** create dummy model */
-  Model *model = new Model (new HWmemDevice);
+  std::unique_ptr<Model> model (new Model (new HWmemDevice));
   model->setDriverAPI (api.get ());
   EXPECT_EQ (model->alloc (4096), 0);
 
   HostInputService &service = HostInputService::getInstance ();
 
+  /** using buffer */
+  std::unique_ptr<Request> req (new Request ());
+  req->setOpmode (opmode);
+  req->setModel (model.get ());
+
+  EXPECT_NE (service.submit (nullptr, nullptr), 0);
+  EXPECT_NE (service.submit (api.get (), nullptr), 0);
+  EXPECT_NE (service.submit (nullptr, req.get ()), 0);
+  EXPECT_NE (service.submit (api.get (), req.get ()), 0);
+
   Buffer *buffer = new Buffer (new HWmemDevice);
   buffer->setDriverAPI (api.get ());
   EXPECT_EQ (buffer->alloc (4096), 0);
 
-  EXPECT_NE (service.submit (nullptr, 0, nullptr, buffer), 0);
-  EXPECT_NE (service.submit (nullptr, 0, model, buffer), 0);
-  EXPECT_EQ (service.submit (api.get (), 0, nullptr, buffer), 0);
-  EXPECT_EQ (service.submit (api.get (), 1, model, buffer), 0);
+  req->setInferData (buffer);
+  EXPECT_EQ (service.submit (api.get (), req.get ()), 0);
+
+  /** using segment table */
+  std::unique_ptr<Request> req2 (new Request ());
+  req2->setOpmode (opmode);
+  req2->setModel (model.get ());
+
+  EXPECT_NE (service.submit (nullptr, nullptr), 0);
+  EXPECT_NE (service.submit (api.get (), nullptr), 0);
+  EXPECT_NE (service.submit (nullptr, req2.get ()), 0);
+  EXPECT_NE (service.submit (api.get (), req2.get ()), 0);
 
   SegmentTable *segt = new SegmentTable (new HWmemDevice);
   segt->setDriverAPI (api.get ());
   EXPECT_EQ (segt->alloc (4096), 0);
 
-  EXPECT_NE (service.submit (nullptr, 2, nullptr, segt), 0);
-  EXPECT_NE (service.submit (nullptr, 2, model, segt), 0);
-  EXPECT_NE (service.submit (api.get (), 2, nullptr, segt), 0);
-  EXPECT_EQ (service.submit (api.get (), 2, model, segt), 0);
+  req2->setInferData (segt);
+  EXPECT_EQ (service.submit (api.get (), req2.get ()), 0);
 
   usleep (TEST_SLEEP_MS);
-
-  delete model;
-  delete buffer;
-  delete segt;
-}
-
-class TestInputService : public InputService {
- public:
-  TestInputService (){};
-};
-
-/**
- * @brief test features of submit() with unsupported input service
- */
-TEST (ne_core_inputservice_test, host_submit_unsupported_n) {
-  InputService *service = new TestInputService;
-
-  EXPECT_NE (service->submit (nullptr, 0, nullptr, (Buffer *) nullptr), 0);
-  EXPECT_NE (service->submit (nullptr, 0, nullptr, (SegmentTable *) nullptr),
-             0);
-
-  delete service;
 }
 
 /**
  * @brief test features of submit() with error handling
  */
-TEST (ne_core_inputservice_test, host_submit_same_id_n) {
+TEST (ne_core_inputservice_test, submit_hw_service_args_n) {
   std::unique_ptr<DriverAPI> api;
+  npu_input_opmode opmode = NPUINPUT_HW_RECURRING;
+
   api = DriverAPI::createDriverAPI (NPUCOND_TRIV2_CONN_SOCIP, 0);
   ASSERT_NE (api.get (), nullptr);
 
   /** create dummy model */
-  Model *model = new Model (new HWmemDevice);
+  std::unique_ptr<Model> model (new Model (new HWmemDevice));
   model->setDriverAPI (api.get ());
   EXPECT_EQ (model->alloc (4096), 0);
 
-  HostInputService &service = HostInputService::getInstance ();
+  HwInputService &service = HwInputService::getInstance ();
 
-  int num_called = 0;
-  std::condition_variable cv;
-  std::mutex m;
+  /** using segment table */
+  std::unique_ptr<Request> req (new Request ());
+  req->setOpmode (opmode);
+  req->setModel (model.get ());
 
-  auto callback = std::bind (test_callback_sleep, &num_called, &m, &cv);
+  EXPECT_NE (service.submit (nullptr, nullptr), 0);
+  EXPECT_NE (service.submit (api.get (), nullptr), 0);
+  EXPECT_NE (service.submit (nullptr, req.get ()), 0);
+  EXPECT_NE (service.submit (api.get (), req.get ()), 0);
 
-  /** saturate requests up to the maximum (in thread pool) */
-  uint32_t num_threads = ThreadPool::getInstance ().getNumThreads ();
+  SegmentTable *segt = new SegmentTable (new HWmemDevice);
+  segt->setDriverAPI (api.get ());
+  EXPECT_EQ (segt->alloc (4096), 0);
 
-  Buffer *buffer = new Buffer (new HWmemDevice);
-  buffer->setDriverAPI (api.get ());
-  EXPECT_EQ (buffer->alloc (4096), 0);
+  req->setInferData (segt);
+  EXPECT_NE (service.submit (api.get (), req.get ()), 0);
+}
 
-  for (uint32_t i = 0; i < num_threads + 1; i++)
-    EXPECT_EQ (service.submit (api.get (), i, model, buffer, callback), 0);
+class TestInputService : public InputService {
+ public:
+  TestInputService (){};
+};
 
-  /** there's a pending task with the same ID */
-  EXPECT_NE (service.submit (api.get (), num_threads, model, buffer, callback),
-             0);
-  EXPECT_NE (service.submit (api.get (), num_threads, model, buffer, callback),
-             0);
+/**
+ * @brief test features of submit() with unsupported input service
+ */
+TEST (ne_core_inputservice_test, host_submit_unsupported_n) {
+  InputService *service = new TestInputService;
 
-  wait_callbacks (num_called, num_threads + 1, m, cv);
+  EXPECT_EQ (service->submit (nullptr, nullptr), -EPERM);
+  EXPECT_EQ (service->remove (nullptr, 0), -EPERM);
 
-  delete model;
-  delete buffer;
+  delete service;
 }
 
 /**
@@ -181,11 +197,12 @@ TEST (ne_core_inputservice_test, host_remove) {
   ASSERT_NE (api.get (), nullptr);
 
   /** create dummy model */
-  Model *model = new Model (new HWmemDevice);
+  std::unique_ptr<Model> model (new Model (new HWmemDevice));
   model->setDriverAPI (api.get ());
   EXPECT_EQ (model->alloc (4096), 0);
 
   HostInputService &service = HostInputService::getInstance ();
+  npu_input_opmode opmode = NPUINPUT_HOST;
 
   int num_called = 0;
   std::condition_variable cv;
@@ -195,20 +212,20 @@ TEST (ne_core_inputservice_test, host_remove) {
 
   /** saturate requests up to the maximum (in thread pool) */
   uint32_t num_threads = ThreadPool::getInstance ().getNumThreads ();
+  int req_id = 0;
+  for (uint32_t i = 0; i < num_threads + 1; i++) {
+    std::unique_ptr<Request> req (new Request ());
+    req->setOpmode (opmode);
+    req->setModel (model.get ());
+    req->setInferData (new SegmentTable (new HWmemDevice));
 
-  Buffer *buffer = new Buffer (new HWmemDevice);
-  buffer->setDriverAPI (api.get ());
-  EXPECT_EQ (buffer->alloc (4096), 0);
-
-  for (uint32_t i = 0; i < num_threads + 1; i++)
-    EXPECT_EQ (service.submit (api.get (), i, model, buffer, callback), 0);
+    req_id = req->getID ();
+    EXPECT_EQ (service.submit (api.get (), req.get (), callback), 0);
+  }
 
   /** remove un-resolved task */
-  EXPECT_EQ (service.remove (num_threads), 0);
+  EXPECT_EQ (service.remove (nullptr, req_id), 0);
   wait_callbacks (num_called, num_threads, m, cv);
-
-  delete model;
-  delete buffer;
 }
 
 /**
@@ -218,88 +235,9 @@ TEST (ne_core_inputservice_test, host_remove_n) {
   HostInputService &service = HostInputService::getInstance ();
 
   /** no such tasks */
-  EXPECT_NE (service.remove (0), 0);
-  EXPECT_NE (service.remove (1), 0);
-  EXPECT_NE (service.remove (2), 0);
-}
-
-/**
- * TODO: add testcases for HwInputService when implemeneted
- */
-
-/**
- * @brief test features of HW inputservice's submit()
- */
-TEST (ne_core_inputservice_test, hw_recurring_submit) {
-  std::unique_ptr<DriverAPI> api;
-  api = DriverAPI::createDriverAPI (NPUCOND_TRIV2_CONN_SOCIP, 0);
-  ASSERT_NE (api.get (), nullptr);
-
-  /** create dummy model */
-  Model *model = new Model (new HWmemDevice);
-  model->setDriverAPI (api.get ());
-  EXPECT_EQ (model->alloc (4096), 0);
-
-  HwInputService &service = HwInputService::getInstance ();
-
-  int num_called = 0;
-  std::condition_variable cv;
-  std::mutex m;
-
-  auto callback = std::bind (test_callback_sleep, &num_called, &m, &cv);
-
-  SegmentTable *segt = new SegmentTable (new HWmemDevice);
-  segt->setDriverAPI (api.get ());
-  EXPECT_EQ (segt->alloc (4096), 0);
-
-  EXPECT_EQ (service.submit (api.get (), 0, model, segt, callback), 0);
-  EXPECT_EQ (service.submit (api.get (), 1, model, segt, callback), 0);
-  EXPECT_EQ (service.submit (api.get (), 2, model, segt, nullptr), 0);
-
-  /** remove is unsupported (it's designed to handle high priority tasks) */
-  EXPECT_NE (service.remove (0), 0);
-
-  wait_callbacks (num_called, 2, m, cv);
-
-  delete model;
-  delete segt;
-}
-
-/**
- * @brief test features of HW inputservice with error handling
- */
-TEST (ne_core_inputservice_test, hw_recurring_n) {
-  std::unique_ptr<DriverAPI> api;
-  api = DriverAPI::createDriverAPI (NPUCOND_TRIV2_CONN_SOCIP, 0);
-  ASSERT_NE (api.get (), nullptr);
-
-  /** create dummy model */
-  Model *model = new Model (new HWmemDevice);
-  model->setDriverAPI (api.get ());
-  EXPECT_EQ (model->alloc (4096), 0);
-
-  HwInputService &service = HwInputService::getInstance ();
-
-  int num_called = 0;
-  std::condition_variable cv;
-  std::mutex m;
-
-  auto callback = std::bind (test_callback_sleep, &num_called, &m, &cv);
-
-  SegmentTable *segt = new SegmentTable (new HWmemDevice);
-  segt->setDriverAPI (api.get ());
-  EXPECT_EQ (segt->alloc (4096), 0);
-
-  EXPECT_NE (service.submit (nullptr, 0, nullptr, segt, nullptr), 0);
-  EXPECT_NE (service.submit (api.get (), 0, nullptr, segt, callback), 0);
-  EXPECT_EQ (service.submit (api.get (), 0, model, segt, callback), 0);
-  /** remove is unsupported (it's designed to handle high priority tasks) */
-  EXPECT_NE (service.remove (0), 0);
-
-  wait_callbacks (num_called, 1, m, cv);
-
-  delete model;
-  delete segt;
+  EXPECT_NE (service.remove (nullptr, 0), 0);
+  EXPECT_NE (service.remove (nullptr, 1), 0);
+  EXPECT_NE (service.remove (nullptr, 2), 0);
 }
 
 /**