1 /* Copyright 2021 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 #ifndef TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_MINI_BENCHMARK_LIBC_HANDLE_H_ 16 #define TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_MINI_BENCHMARK_LIBC_HANDLE_H_ 17 18 #ifdef __ANDROID__ 19 #include <dlfcn.h> 20 #endif 21 22 #include <cstdio> 23 #include <memory> 24 #include <utility> 25 26 #include "tensorflow/lite/experimental/acceleration/mini_benchmark/decode_jpeg_status.h" 27 28 namespace tflite { 29 namespace acceleration { 30 namespace decode_jpeg_kernel { 31 32 // This class offers a handle to C Standard Library (LibC) shared object 33 // library on Android. It offers pointers to functions in LibC. 34 // Fmemopen is available as native API from Android SDK 23 onwards. In order to 35 // support Android devices from SDK 21 onwards, we load fmemopen dynamically 36 // from the libc shared object library. 37 // TODO(b/172544567): Support Apple. 38 class LibCHandle { 39 public: 40 // Factory to get an initialised instance of LibCHandle. 41 // Loads the libc dynamic library and gets handle to all the 42 // required functions. Stores the initialisation status in `status`. 43 static LibCHandle Create(Status& status); 44 LibCHandle(LibCHandle const&) = delete; 45 LibCHandle& operator=(const LibCHandle&) = delete; LibCHandle(LibCHandle && other)46 LibCHandle(LibCHandle&& other) 47 : libc_(std::exchange(other.libc_, nullptr)), 48 fmemopen_(std::exchange(other.fmemopen_, nullptr)) {} 49 LibCHandle& operator=(LibCHandle&& other) { 50 if (&other != this) { 51 CloseHandle(); 52 libc_ = std::exchange(other.libc_, nullptr); 53 fmemopen_ = std::exchange(other.fmemopen_, nullptr); 54 } 55 return *this; 56 } ~LibCHandle()57 ~LibCHandle() { CloseHandle(); } 58 // Definition can be found here 59 // https://man7.org/linux/man-pages/man3/fmemopen.3.html 60 FILE* fmemopen(void* buf, size_t size, const char* mode) const; 61 62 private: 63 using FmemopenPtr = FILE* (*)(void*, size_t, const char*); LibCHandle(void * libc,FmemopenPtr ptr)64 LibCHandle(void* libc, FmemopenPtr ptr) : libc_(libc), fmemopen_(ptr) {} 65 // Closes the dynamic library loaded in libc_. CloseHandle()66 void CloseHandle() { 67 #ifdef __ANDROID__ 68 if (libc_ != nullptr) { 69 dlclose(libc_); 70 } 71 #endif 72 } 73 void* libc_ = nullptr; 74 FmemopenPtr fmemopen_ = nullptr; 75 }; 76 77 } // namespace decode_jpeg_kernel 78 } // namespace acceleration 79 } // namespace tflite 80 81 #endif // TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_MINI_BENCHMARK_LIBC_HANDLE_H_ 82