[GEM] Add test_mode in gem driver API.
authorDongju Chae <dongju.chae@samsung.com>
Thu, 8 Aug 2019 06:01:01 +0000 (15:01 +0900)
committer함명주/On-Device Lab(SR)/Principal Engineer/삼성전자 <myungjoo.ham@samsung.com>
Fri, 9 Aug 2019 05:12:38 +0000 (14:12 +0900)
This commit adds the test mode in gem driver API.
It means that memory allocator can keep the same code semantics regardless the test mode.

Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
src/core/libgem-core/GEMdrvAPI.c
src/core/libgem-core/GEMdrvAPI.h
src/core/libgem-core/meson.build
src/core/npu-engine/ne-mem.c
src/test/libgem_test.cpp
src/test/meson.build

index 6d048bd..277417f 100644 (file)
@@ -12,7 +12,7 @@
  * @bug No known bugs except for NYI items
  */
 
-#include <GEMdrvAPI.h>
+#include "GEMdrvAPI.h"
 
 #include <stdio.h>
 #include <string.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
+/* npu-engine */
+#include <ne-conf.h>
+
 #define DRM_BASE_PATH "/dev/dri/card"
+#define ALIGN_SIZE    4096
+#define DUMMY_HANDLE  0xdeadbeef
+#define DUMMY_FD      2848
+
+static void *malloc_buf = NULL;  /* testing purpose */
 
 /* internal implementation functions */
 
@@ -232,6 +240,9 @@ gem_open (const char *name)
   uint64_t value;
   int offset, fd = -1;
 
+  if (conf->test_mode == 1)
+    return DUMMY_FD;
+
   for (offset = 0; offset < 16; offset++) {
     if ((fd = __gem_open_driver (offset, name)) > 0)
       break;
@@ -248,6 +259,17 @@ gem_open (const char *name)
 }
 
 /**
+ * @brief close gem driver
+ * @param[in] fd file descriptor
+ */
+void
+gem_close (int fd)
+{
+  if (conf->test_mode == 0)
+    close (fd);
+}
+
+/**
  * @brief create a dumb buffer for gem object
  * @param[in] fd the file descriptor of driver
  * @param[in] size_in the requested buffer size
@@ -260,6 +282,16 @@ gem_create (int fd, uint32_t size_in, uint32_t *size_out)
   assert (fd > 0);
   assert (size_in > 0);
 
+  if (conf->test_mode == 1) {
+    /* 4KB-aligned size */
+    *size_out = ((size_in - 1) / ALIGN_SIZE + 1) * ALIGN_SIZE;
+    malloc_buf = malloc (*size_out);
+    if (!malloc_buf)
+      return 0;
+
+    return DUMMY_HANDLE;
+  }
+
   return __gem_create (fd, size_in, size_out);
 }
 
@@ -275,6 +307,13 @@ gem_destroy (int fd, uint32_t handle)
   assert (fd > 0);
   assert (handle > 0);
 
+  if (conf->test_mode == 1) {
+    if (!malloc_buf)
+      return -EINVAL;
+    free (malloc_buf);
+    return 0;
+  }
+
   return __gem_destroy (fd, handle);
 }
 
@@ -296,12 +335,31 @@ gem_mmap (int fd, uint32_t handle, uint32_t size, int prot, bool dmabuf)
   assert (handle > 0);
   assert (size > 0);
 
-  ptr = __gem_mmap(fd, handle, size, prot, dmabuf);
+  if (conf->test_mode == 0)
+    ptr = __gem_mmap(fd, handle, size, prot, dmabuf);
+  else
+    ptr = malloc_buf;
 
   return ptr != MAP_FAILED ? ptr : NULL;
 }
 
 /**
+ * @brief munmap operation for gem object
+ * @param[in] ptr mmapped pointer
+ * @param[in] size mmapped size
+ * @return 0 if no error, otherwise a negative errno
+ */
+int
+gem_munmap (void *ptr, uint32_t size)
+{
+  if (conf->test_mode == 0) {
+    if (munmap (ptr, size) != 0)
+      return -errno;
+  }
+  return 0;
+}
+
+/**
  * @brief export a GEM buffer object into a global dmabuf fd handle
  * @param[in] fd a file descriptor of driver
  * @param[in] handle a GEM buffer object handle
@@ -313,6 +371,9 @@ gem_prime_export (int fd, uint32_t handle)
   assert (fd > 0);
   assert (handle > 0);
 
+  if (conf->test_mode == 1)
+    return DUMMY_FD;
+
   return __gem_prime_export (fd, handle);
 }
 
@@ -328,5 +389,8 @@ gem_prime_import (int fd, int dmabuf_fd)
   assert (fd > 0);
   assert (dmabuf_fd > 0);
 
+  if (conf->test_mode == 1)
+    return DUMMY_HANDLE;
+
   return __gem_prime_import (fd, dmabuf_fd);
 }
index b3db57d..fc05d2a 100644 (file)
@@ -31,6 +31,13 @@ int
 gem_open (const char *name);
 
 /**
+ * @brief close gem driver
+ * @param[in] fd file descriptor
+ */
+void
+gem_close (int fd);
+
+/**
  * @brief create a dumb buffer for gem object
  * @param[in] fd the file descriptor of driver
  * @param[in] size_in the requested buffer size
@@ -62,6 +69,15 @@ void *
 gem_mmap (int fd, uint32_t handle, uint32_t size, int prot, bool dmabuf);
 
 /**
+ * @brief munmap operation for gem object
+ * @param[in] ptr mmapped pointer
+ * @param[in] size mmapped size
+ * @return 0 if no error, otherwise a negative errno
+ */
+int
+gem_munmap (void *ptr, uint32_t size);
+
+/**
  * @brief export a GEM buffer object into a global dmabuf fd handle
  * @param[in] fd a file descriptor of driver
  * @param[in] handle a GEM buffer object handle
index 14170e6..e7ebebd 100644 (file)
@@ -1,6 +1,6 @@
 libgem_src = ['GEMdrvAPI.c']
 libgem_inc = include_directories('.')
-libgem_dependencies = [libdrm_dep]
+libgem_dependencies = [libdrm_dep, libutils_dep]
 
 # Build library (static)
 libgem_build = static_library('gem-core',
index d8e4d0b..e871be0 100644 (file)
@@ -12,9 +12,8 @@
  * @bug No known bugs except for NYI items
  */
 
-#include <ne-mem.h>
-#include <ne-utils.h>
-#include <ne-conf.h>
+#include "ne-mem.h"
+#include "ne-utils.h"
 #include <GEMdrvAPI.h>
 
 #include <stdio.h>
@@ -66,8 +65,8 @@ typedef enum {
  * @brief memory chunk structure
  */
 typedef struct {
-  mem_size_t offset;          /**< chunk offset */
-  mem_size_t size;            /**< chunk size */
+  mem_size_t offset;        /**< chunk offset */
+  mem_size_t size;          /**< chunk size */
   chunk_state state;        /**< chunk state */
 
   list_node list;           /**< list element */
@@ -108,13 +107,13 @@ typedef struct {
   int fd;                              /**< file descriptor of a GEM driver */
   int dmabuf;                          /**< dmabuf fd handle */
   uint32_t handle;                     /**< GEM buffer object handle for memory pool */
-  mem_size_t size;                       /**< memory pool size */
+  mem_size_t size;                     /**< memory pool size */
 
   void* virtaddr;                      /**< base virtual address for memory pool */
 
   buffer *buffer [MEM_NUM_BUFFERS];    /**< buffer array */
   int buffer_head;                     /**< buffer head (changed by .switch_buffers()) */
-  mem_size_t buffer_size;                /**< buffer size for each */
+  mem_size_t buffer_size;              /**< buffer size for each */
 
   pthread_mutex_t mutex;               /**< mutex for locking */
   pthread_cond_t cond;                 /**< cond for broadcasting */
@@ -846,38 +845,29 @@ mem_init (uint64_t size_in, uint64_t *size_out)
   }
 
   if ((fd = gem_open (GEM_NAME)) <= 0) {
-    if (conf->test_mode == 0) {
-      logerr(MEM_TAG, "Fail to open a GEM driver\n");
-      return -EACCES;
-    } else {
-      logwarn(MEM_TAG, "Fail to open a GEM driver.. fall back to test mode using malloc()\n");
-    }
+    logerr(MEM_TAG, "Fail to open a GEM driver\n");
+    return -EACCES;
   }
 
-  if (conf->test_mode == 0) {
-    do {
-      /**
-       * the minimum size of allocation is MEM_BASE_SIZE
-       * note that gem_create() supports only 32bit allocation (currently)
-       */
-      uint32_t size_in_32 = size_in;
-      uint32_t size_out_32;
-
-      if ((handle = gem_create (fd, size_in_32, &size_out_32)) == 0)
-        /* if failed, retry with a smaller size */
-        size_in = size_in >> 1;
-      else
-        *size_out = size_out_32;
-    } while (handle == 0 && size_in >= MEM_BASE_SIZE);
-
-    if (handle == 0) {
-      close (fd);
-      logerr (MEM_TAG, "no available memory\n");
-      return -ENOMEM;
-    }
-  } else {
-    handle = fd = 1; /* dummy */
-    *size_out = size_in;
+  do {
+    /**
+     * the minimum size of allocation is MEM_BASE_SIZE
+     * note that gem_create() supports only 32bit allocation (currently)
+     */
+    uint32_t size_in_32 = size_in;
+    uint32_t size_out_32;
+
+    if ((handle = gem_create (fd, size_in_32, &size_out_32)) == 0)
+      /* if failed, retry with a smaller size */
+      size_in = size_in >> 1;
+    else
+      *size_out = size_out_32;
+  } while (handle == 0 && size_in >= MEM_BASE_SIZE);
+
+  if (handle == 0) {
+    gem_close (fd);
+    logerr (MEM_TAG, "no available memory\n");
+    return -ENOMEM;
   }
 
   /* setup private data */
@@ -886,26 +876,17 @@ mem_init (uint64_t size_in, uint64_t *size_out)
   mpriv.handle = handle;
   mpriv.buffer_size = 0;
 
-  if (conf->test_mode == 0) {
-    /* export the handle to dmabuf fd handle */
-    mpriv.dmabuf = gem_prime_export (fd, handle);
-    assert (mpriv.dmabuf > 0);
-    /**
-     * mmap() for the GEM buffer and assign its base addresses.
-     * The reason to mmap() for the whole CMA space is that
-     * frequent system calls for mmap()/munmap() may decrease the performance.
-     * So, we will just return a hwmem with offset/size to users.
-     */
-    mpriv.virtaddr = gem_mmap (mpriv.fd, mpriv.handle, mpriv.size,
-        PROT_WRITE | PROT_READ, false);
-  } else {
-    mpriv.dmabuf = 1; /* dummy */
-    mpriv.virtaddr = malloc (size_in);
-    if (mpriv.virtaddr == NULL) {
-      logerr (MEM_TAG, "no available memory\n");
-      return -ENOMEM;
-    }
-  }
+  /* export the handle to dmabuf fd handle */
+  mpriv.dmabuf = gem_prime_export (fd, handle);
+  assert (mpriv.dmabuf > 0);
+  /**
+   * mmap() for the GEM buffer and assign its base addresses.
+   * The reason to mmap() for the whole CMA space is that
+   * frequent system calls for mmap()/munmap() may decrease the performance.
+   * So, we will just return a hwmem with offset/size to users.
+   */
+  mpriv.virtaddr = gem_mmap (mpriv.fd, mpriv.handle, mpriv.size,
+      PROT_WRITE | PROT_READ, false);
 
   assert (mpriv.virtaddr != NULL);
 
@@ -962,20 +943,16 @@ mem_fini (void)
     chunk_free (chunk);
   }
 
-  if (conf->test_mode == 0) {
-    munmap (mpriv.virtaddr, mpriv.size);
+  gem_munmap (mpriv.virtaddr, mpriv.size);
 
-    /* close dmabuf handle */
-    close (mpriv.dmabuf);
+  /* close dmabuf handle */
+  gem_close (mpriv.dmabuf);
 
-    /* release the gem buffer object handle */
-    gem_destroy (mpriv.fd, mpriv.handle);
+  /* release the gem buffer object handle */
+  gem_destroy (mpriv.fd, mpriv.handle);
 
-    /* close gem driver */
-    close (mpriv.fd);
-  } else {
-    free (mpriv.virtaddr);
-  }
+  /* close gem driver */
+  gem_close (mpriv.fd);
 
   return 0;
 }
index 83ad4b9..1a9011e 100644 (file)
@@ -35,7 +35,7 @@ TEST (test_gem, open)
                      "did you load it? (i.e., sudo modprobe cgem)\n");
 
   ASSERT_GT (fd,  0);
-  close (fd);
+  gem_close (fd);
 }
 
 /**
@@ -64,7 +64,7 @@ TEST (test_gem, create)
   ASSERT_EQ (size, 1 << 22);
   gem_destroy (fd, handle);
 
-  close (fd);
+  gem_close (fd);
 }
 
 /**
@@ -90,11 +90,11 @@ TEST (test_gem, mmap)
   for (page = 0; page < size >> 2; page += 1 << 10)
     ptr[page] = 0;
 
-  munmap (ptr, size);
+  gem_munmap (ptr, size);
 
   gem_destroy (fd, handle);
   
-  close (fd);
+  gem_close (fd);
 }
 
 /**
@@ -123,9 +123,9 @@ TEST (test_gem, export_dmabuf)
 
   for (page = 0; page < (size >> 2); page += 1 << 10)
     ptr[page] = page;
-  munmap (ptr, size);
+  gem_munmap (ptr, size);
 
-  close (dmabuf_fd);
+  gem_close (dmabuf_fd);
 
   /* mmap */
   ptr = (uint32_t *) gem_mmap (fd, handle, size, PROT_READ, false);
@@ -134,11 +134,11 @@ TEST (test_gem, export_dmabuf)
   /* compare data */
   for (page = 0; page < (size >> 2); page += 1 << 10)
     ASSERT_EQ (ptr[page], page);
-  munmap (ptr, size);
+  gem_munmap (ptr, size);
 
   gem_destroy (fd, handle);
 
-  close (fd);
+  gem_close (fd);
 }
 
 /**
index 9b0b27a..e509787 100644 (file)
@@ -5,20 +5,20 @@ add_languages('cpp')
 
 gtest_dep = dependency('gtest', required: false)
 if gtest_dep.found()
-#### TODO libgem unittest is not working on gbs because cgem driver is not installed
-#### Therefore, we skip the build this UnitTest temporally.
-#  libgem_unittest_deps = [
-#    libgem_dep,
-#    gtest_dep
-#  ]
-#
-#  unittest_libgem = executable('unittest_libgem',
-#    ['libgem_test.cpp'],
-#    dependencies: [libgem_unittest_deps],
-#    cpp_args : '-std=c++11'
-#  )
-#
- test('unittest_libgem', unittest_libgem)
+  libgem_unittest_deps = [
+    libgem_dep,
+    gtest_dep
+  ]
+
+  unittest_libgem = executable('unittest_libgem',
+    ['libgem_test.cpp'],
+    dependencies: [libgem_unittest_deps],
+    cpp_args : '-std=c++11',
+    install : true,
+    install_dir : join_paths(ne_bindir, 'unittests')
+  )
+
+ test('unittest_libgem', unittest_libgem)
 
   libnpu_unittest_deps = [
     libnpucore_dep,