From 12b0ec309b6358c9cdb8639dbf7e31447c0b0fb5 Mon Sep 17 00:00:00 2001 From: yuanbo Date: Thu, 30 Dec 2021 19:59:08 +0800 Subject: [PATCH] feat: support shared mem queue for hdi Signed-off-by: yuanbo --- uhdf2/hdi/BUILD.gn | 2 + uhdf2/hdi/src/devmgr_client.c | 3 +- uhdf2/hdi/src/hdi_smq_syncer.cpp | 121 +++++ uhdf2/hdi/src/idevmgr_client.cpp | 6 +- uhdf2/hdi/test/BUILD.gn | 27 +- .../servmgr/service_manager_hdi_c_test.cpp | 37 +- .../test/servmgr/service_manager_hdi_test.cpp | 136 ++++- uhdf2/host/devhost.c | 2 +- .../host/test/unittest/sample_driver/BUILD.gn | 16 +- .../{sample_driver.c => sample_driver.cpp} | 17 +- .../test/unittest/sample_driver/sample_hdi.h | 34 +- ...e_hdi_service.c => sample_hdi_service.cpp} | 93 +++- ...ice_stub.c => sample_hdi_service_stub.cpp} | 50 +- uhdf2/include/hdi/base/hdi_smq.h | 476 ++++++++++++++++++ uhdf2/include/hdi/base/hdi_smq_meta.h | 213 ++++++++ uhdf2/include/hdi/base/hdi_smq_syncer.h | 47 ++ uhdf2/manager/src/devmgr_service_full.c | 71 ++- uhdf2/manager/src/devmgr_service_stub.c | 3 +- uhdf2/manager/src/devsvc_manager_stub.c | 75 ++- uhdf2/utils/BUILD.gn | 1 + uhdf2/utils/include/shared_mem.h | 33 ++ uhdf2/utils/src/shared_mem.cpp | 32 ++ 22 files changed, 1351 insertions(+), 144 deletions(-) create mode 100644 uhdf2/hdi/src/hdi_smq_syncer.cpp rename uhdf2/host/test/unittest/sample_driver/{sample_driver.c => sample_driver.cpp} (84%) rename uhdf2/host/test/unittest/sample_driver/{sample_hdi_service.c => sample_hdi_service.cpp} (51%) rename uhdf2/host/test/unittest/sample_driver/{sample_hdi_service_stub.c => sample_hdi_service_stub.cpp} (77%) create mode 100644 uhdf2/include/hdi/base/hdi_smq.h create mode 100644 uhdf2/include/hdi/base/hdi_smq_meta.h create mode 100644 uhdf2/include/hdi/base/hdi_smq_syncer.h create mode 100644 uhdf2/utils/include/shared_mem.h create mode 100644 uhdf2/utils/src/shared_mem.cpp diff --git a/uhdf2/hdi/BUILD.gn b/uhdf2/hdi/BUILD.gn index c9b01ec..148c3a1 100644 --- a/uhdf2/hdi/BUILD.gn +++ b/uhdf2/hdi/BUILD.gn @@ -27,6 +27,7 @@ config("libhdi_pub_config") { "$hdf_uhdf_path/ipc/include", "$hdf_uhdf_path/hdi/include", "$hdf_uhdf_path/include/hdi", + "$hdf_uhdf_path/include/hdi/base", "$hdf_uhdf_path/shared/include", ] } @@ -53,6 +54,7 @@ ohos_shared_library("libhdi") { "$hdf_framework_path/core/shared/src/service_status.c", "src/devmgr_client.c", "src/hdf_load_hdi.c", + "src/hdi_smq_syncer.cpp", "src/idevmgr_client.cpp", "src/iservmgr_client.cpp", "src/servmgr_client.c", diff --git a/uhdf2/hdi/src/devmgr_client.c b/uhdf2/hdi/src/devmgr_client.c index f555fde..0ad52c7 100644 --- a/uhdf2/hdi/src/devmgr_client.c +++ b/uhdf2/hdi/src/devmgr_client.c @@ -158,7 +158,7 @@ int32_t DevmgrLoadDevice(struct HDIDeviceManager *iDevMgr, const char *serviceNa if (iDevMgr == NULL || serviceName == NULL) { return HDF_ERR_INVALID_PARAM; } - + HDF_LOGI("load device: %{public}s", serviceName); struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC); do { if (data == NULL) { @@ -186,6 +186,7 @@ int32_t DevmgrUnloadDevice(struct HDIDeviceManager *iDevMgr, const char *service if (iDevMgr == NULL || serviceName == NULL) { return HDF_ERR_INVALID_PARAM; } + HDF_LOGI("unload device: %{public}s", serviceName); struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC); do { diff --git a/uhdf2/hdi/src/hdi_smq_syncer.cpp b/uhdf2/hdi/src/hdi_smq_syncer.cpp new file mode 100644 index 0000000..a5208d1 --- /dev/null +++ b/uhdf2/hdi/src/hdi_smq_syncer.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 + * + * http://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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HDF_LOG_TAG smq_syncer + +namespace OHOS { +namespace HDI { +namespace Base { +SharedMemQueueSyncer::SharedMemQueueSyncer(std::atomic *syncerPtr) : syncAddr_(syncerPtr) +{ +} + +int SharedMemQueueSyncer::Wait(uint32_t bitset, int64_t timeoutNanoSec) +{ + int ret; + while (true) { + ret = FutexWait(bitset, timeoutNanoSec); + if (ret == -EINTR || ret == -EAGAIN) { + HDF_LOGE("wait smq futex %{public}d,try again", ret); + continue; + } + break; + } + + return ret; +} + +int SharedMemQueueSyncer::FutexWait(uint32_t bitset, int64_t timeoutNanoSec) +{ + // clean wait bit + uint32_t syncWordOld = std::atomic_fetch_and(syncAddr_, ~bitset); + + // if sync bit already set, not nedd futex wait + if (syncWordOld & bitset) { + return HDF_SUCCESS; + } + // futex will check sync word equal this expected val or not. If equal, sleep to wait, else return EAGAIN. + uint32_t valParm = syncWordOld & (~bitset); + int status; + if (timeoutNanoSec > 0) { + struct timespec waitTime; + TimeoutToRealtime(timeoutNanoSec, waitTime); + status = syscall(__NR_futex, syncAddr_, FUTEX_WAIT_BITSET, valParm, &waitTime, NULL, bitset); + } else { + status = syscall(__NR_futex, syncAddr_, FUTEX_WAIT_BITSET, valParm, NULL, NULL, bitset); + } + if (status == 0) { + syncWordOld = std::atomic_fetch_and(syncAddr_, ~bitset); + if ((syncWordOld & bitset) == 0) { + return -EINTR; + } + + return status; + } + status = -errno; + if (status != ETIMEDOUT) { + HDF_LOGE("failed to wait smq futex, %{publich}d", status); + } + return status; +} + +int SharedMemQueueSyncer::Wake(uint32_t bitset) +{ + uint32_t syncWordOld = std::atomic_fetch_or(syncAddr_, bitset); + + // if sync bit already set, not nedd futex wake + if (syncWordOld & bitset) { + return HDF_SUCCESS; + } + + int ret = syscall(__NR_futex, syncAddr_, FUTEX_WAKE_BITSET, INT_MAX, 0, 0, bitset); + if (ret < 0) { + HDF_LOGE("failed to wakeup smq futex, %{public}d", errno); + return -errno; + } + + return HDF_SUCCESS; +} + +void SharedMemQueueSyncer::TimeoutToRealtime(int64_t timeout, struct timespec &realtime) +{ + constexpr int64_t nano = SEC_TO_NANOSEC; + + clock_gettime(CLOCK_MONOTONIC, &realtime); + int64_t timeoutNanoSec = timeout % nano; + int64_t timeoutSec = timeout / nano; + + if (timeoutNanoSec + realtime.tv_nsec >= nano) { + realtime.tv_nsec = (timeoutNanoSec + realtime.tv_nsec) - nano; + realtime.tv_sec += timeoutSec + 1; + } else { + realtime.tv_nsec += timeoutNanoSec; + realtime.tv_sec += timeoutSec; + } +} +} // namespace Base +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/uhdf2/hdi/src/idevmgr_client.cpp b/uhdf2/hdi/src/idevmgr_client.cpp index a827211..03f4cd1 100644 --- a/uhdf2/hdi/src/idevmgr_client.cpp +++ b/uhdf2/hdi/src/idevmgr_client.cpp @@ -20,11 +20,13 @@ #include "idevmgr_hdi.h" #include "iservmgr_hdi.h" +#define HDF_LOG_TAG idevmgr_client + namespace OHOS { namespace HDI { namespace DeviceManager { namespace V1_0 { -enum DevngrCmdId { +enum DevngrCmdId : uint32_t { DEVMGR_SERVICE_ATTACH_DEVICE_HOST = 1, DEVMGR_SERVICE_ATTACH_DEVICE, DEVMGR_SERVICE_DETACH_DEVICE, @@ -48,6 +50,7 @@ int32_t DeviceManagerProxy::LoadDevice(const std::string &serviceName) MessageParcel data; MessageParcel reply; MessageOption option; + HDF_LOGI("load device: %{public}s", serviceName.data()); if (!data.WriteCString(serviceName.data())) { return HDF_FAILURE; } @@ -64,6 +67,7 @@ int32_t DeviceManagerProxy::UnloadDevice(const std::string &serviceName) MessageParcel data; MessageParcel reply; MessageOption option; + HDF_LOGI("unload device: %{public}s", serviceName.data()); if (!data.WriteCString(serviceName.data())) { return HDF_FAILURE; } diff --git a/uhdf2/hdi/test/BUILD.gn b/uhdf2/hdi/test/BUILD.gn index 3899b4a..95a9a67 100644 --- a/uhdf2/hdi/test/BUILD.gn +++ b/uhdf2/hdi/test/BUILD.gn @@ -33,11 +33,10 @@ ohos_unittest("HdiServiceManagerTest") { include_dirs = [ "$hdf_uhdf_path/host/test/unittest/sample_driver" ] - if (is_standard_system) { - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - } else { - external_deps = [ "hilog:libhilog" ] - } + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] } ohos_unittest("HdiServiceManagerTestCC") { @@ -53,19 +52,11 @@ ohos_unittest("HdiServiceManagerTestCC") { ] include_dirs = [ "$hdf_uhdf_path/host/test/unittest/sample_driver" ] - if (is_standard_system) { - external_deps = [ - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - "samgr_standard:samgr_proxy", - ] - } else { - external_deps = [ - "hilog:libhilog", - "ipc:ipc_core", - "samgr:samgr_proxy", - ] - } + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_standard:samgr_proxy", + ] } ###########################end########################### diff --git a/uhdf2/hdi/test/servmgr/service_manager_hdi_c_test.cpp b/uhdf2/hdi/test/servmgr/service_manager_hdi_c_test.cpp index 753e941..0315ccd 100644 --- a/uhdf2/hdi/test/servmgr/service_manager_hdi_c_test.cpp +++ b/uhdf2/hdi/test/servmgr/service_manager_hdi_c_test.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "sample_hdi.h" #define HDF_LOG_TAG service_manager_test @@ -85,7 +87,7 @@ HWTEST_F(HdfServiceMangerHdiCTest, ServMgrTest002, TestSize.Level1) static int32_t g_callbackPayload = 0; -int ServiceManagerTestCallbackDispatch( +static int ServiceManagerTestCallbackDispatch( struct HdfRemoteService *service, int code, struct HdfSBuf *data, struct HdfSBuf *reply) { HDF_LOGI("ServiceManagerTestCallbackDispatch called, code = %{public}d", code); @@ -93,7 +95,7 @@ int ServiceManagerTestCallbackDispatch( return HDF_SUCCESS; } -struct HdfRemoteDispatcher g_callbackDispatcher { +static struct HdfRemoteDispatcher g_callbackDispatcher { .Dispatch = ServiceManagerTestCallbackDispatch, }; @@ -106,7 +108,7 @@ HWTEST_F(HdfServiceMangerHdiCTest, ServMgrTest003, TestSize.Level1) HDIServiceManagerRelease(servmgr); ASSERT_TRUE(sampleService != nullptr); - struct HdfRemoteService *callback = HdfRemoteServiceObtain(NULL, &g_callbackDispatcher); + struct HdfRemoteService *callback = HdfRemoteServiceObtain(nullptr, &g_callbackDispatcher); ASSERT_NE(callback, nullptr); struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC); struct HdfSBuf *reply = HdfSBufTypedObtain(SBUF_IPC); @@ -311,7 +313,7 @@ static void TestOnServiceStatusReceived(struct ServiceStatusListener *listener, return; } ssd->servName = servstat->serviceName; - ssd->servInfo = servstat->info != NULL ? servstat->info : ""; + ssd->servInfo = servstat->info != nullptr ? servstat->info : ""; ssd->devClass = servstat->deviceClass; ssd->servStatus = servstat->status; ssd->callbacked = true; @@ -492,4 +494,31 @@ HWTEST_F(HdfServiceMangerHdiCTest, ServMgrTest010, TestSize.Level1) ssd.callbacked = false; OsalMSleep(10); ASSERT_FALSE(ssd.callbacked); +} + +/* + * Test shared mem interface + */ +HWTEST_F(HdfServiceMangerHdiCTest, ServMgrTest011, TestSize.Level1) +{ + constexpr int mapSize = 128; + int memFd = SharedMemCreate("shared_mem_test", mapSize); + ASSERT_TRUE(memFd >= 0); + + void *ptr = mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, memFd, 0); + ASSERT_NE(ptr, MAP_FAILED); + + uint8_t *data = reinterpret_cast(ptr); + for (int i = 0; i < mapSize; i++) { + data[i] = i; + } + + for (int i = 0; i < mapSize; i++) { + ASSERT_EQ(data[i], i); + } + + auto ret = munmap(ptr, mapSize); + ASSERT_EQ(ret, 0); + + close(memFd); } \ No newline at end of file diff --git a/uhdf2/hdi/test/servmgr/service_manager_hdi_test.cpp b/uhdf2/hdi/test/servmgr/service_manager_hdi_test.cpp index 9e10f98..4850a9d 100644 --- a/uhdf2/hdi/test/servmgr/service_manager_hdi_test.cpp +++ b/uhdf2/hdi/test/servmgr/service_manager_hdi_test.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -30,14 +31,18 @@ using namespace testing::ext; using OHOS::IRemoteObject; using OHOS::sptr; +using OHOS::HDI::Base::SharedMemQueue; +using OHOS::HDI::Base::SharedMemQueueMeta; +using OHOS::HDI::Base::SmqType; using OHOS::HDI::DeviceManager::V1_0::IDeviceManager; using OHOS::HDI::ServiceManager::V1_0::IServiceManager; using OHOS::HDI::ServiceManager::V1_0::IServStatListener; using OHOS::HDI::ServiceManager::V1_0::ServiceStatus; using OHOS::HDI::ServiceManager::V1_0::ServStatListenerStub; - constexpr const char *TEST_SERVICE_NAME = "sample_driver_service"; constexpr int PAYLOAD_NUM = 1234; +constexpr int SMQ_TEST_QUEUE_SIZE = 10; +constexpr int SMQ_TEST_WAIT_TIME = 100; class HdfServiceMangerHdiTest : public testing::Test { public: @@ -87,8 +92,7 @@ HWTEST_F(HdfServiceMangerHdiTest, ServMgrTest002, TestSize.Level1) class IPCObjectStubTest : public OHOS::IPCObjectStub { public: - explicit IPCObjectStubTest() - : OHOS::IPCObjectStub(u"") {}; + explicit IPCObjectStubTest() : OHOS::IPCObjectStub(u"") {}; virtual ~IPCObjectStubTest() = default; int OnRemoteRequest( uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply, OHOS::MessageOption &option) override @@ -246,8 +250,7 @@ HWTEST_F(HdfServiceMangerHdiTest, ServMgrTest007, TestSize.Level1) class ServStatListener : public OHOS::HDI::ServiceManager::V1_0::ServStatListenerStub { public: using StatusCallback = std::function; - explicit ServStatListener(StatusCallback callback) - : callback_(std::move(callback)) + explicit ServStatListener(StatusCallback callback) : callback_(std::move(callback)) { } ~ServStatListener() = default; @@ -450,4 +453,127 @@ HWTEST_F(HdfServiceMangerHdiTest, ServMgrTest010, TestSize.Level1) OsalMSleep(10); ASSERT_FALSE(callbacked); + + ret = devmgr->LoadDevice(TEST_SERVICE_NAME); + ASSERT_EQ(ret, HDF_SUCCESS); } + +/* + * smq test normal read/write + */ +HWTEST_F(HdfServiceMangerHdiTest, ServMgrTest011, TestSize.Level1) +{ + HDF_LOGI("%{public}s:%{public}d", __func__, __LINE__); + auto servmgr = IServiceManager::Get(); + ASSERT_TRUE(servmgr != nullptr); + + auto sampleService = servmgr->GetService(TEST_SERVICE_NAME); + ASSERT_TRUE(sampleService != nullptr); + + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + std::unique_ptr> smq + = std::make_unique>(SMQ_TEST_QUEUE_SIZE, SmqType::SYNCED_SMQ); + ASSERT_TRUE(smq->IsGood()); + + auto ret = smq->GetMeta()->Marshalling(data); + ASSERT_TRUE(ret); + data.WriteUint32(1); + + int status = sampleService->SendRequest(SAMPLE_TRANS_SMQ, data, reply, option); + ASSERT_EQ(status, 0); + + constexpr int SEND_TIMES = 20; + for (size_t i = 0; i < SEND_TIMES; i++) { + SampleSmqElement t = { 0 }; + t.data32 = i; + t.data64 = i + 1; + + HDF_LOGI("%{public}s:write smq message %{public}zu", __func__, i); + auto status = smq->Write(&t, 1, OHOS::MillisecToNanosec(SMQ_TEST_WAIT_TIME)); + ASSERT_EQ(status, 0); + } +} + +/* + * smq test with overflow wait + */ +HWTEST_F(HdfServiceMangerHdiTest, ServMgrTest012, TestSize.Level1) +{ + auto servmgr = IServiceManager::Get(); + ASSERT_TRUE(servmgr != nullptr); + + auto sampleService = servmgr->GetService(TEST_SERVICE_NAME); + ASSERT_TRUE(sampleService != nullptr); + + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + std::unique_ptr> smq + = std::make_unique>(SMQ_TEST_QUEUE_SIZE, SmqType::SYNCED_SMQ); + ASSERT_TRUE(smq->IsGood()); + + constexpr uint32_t ELEMENT_SIZE = 2; + + auto ret = smq->GetMeta()->Marshalling(data); + ASSERT_TRUE(ret); + + data.WriteUint32(ELEMENT_SIZE); + int status = sampleService->SendRequest(SAMPLE_TRANS_SMQ, data, reply, option); + ASSERT_EQ(status, 0); + + constexpr int SEND_TIMES = 20; + for (int i = 0; i < SEND_TIMES; i++) { + SampleSmqElement t[ELEMENT_SIZE] = {}; + t[0].data32 = i; + t[0].data64 = i + 1; + t[1].data32 = i + 1; + t[1].data64 = i + 1; + HDF_LOGI("%{public}s:write smq message %{public}zu", __func__, i); + auto status = smq->Write(&t[0], ELEMENT_SIZE, OHOS::MillisecToNanosec(SMQ_TEST_WAIT_TIME)); + ASSERT_EQ(status, 0); + } +} + +/* + * smq test UNSYNC_SMQ + */ +HWTEST_F(HdfServiceMangerHdiTest, ServMgrTest013, TestSize.Level1) +{ + auto servmgr = IServiceManager::Get(); + ASSERT_TRUE(servmgr != nullptr); + + auto sampleService = servmgr->GetService(TEST_SERVICE_NAME); + ASSERT_TRUE(sampleService != nullptr); + + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + + std::unique_ptr> smq + = std::make_unique>(SMQ_TEST_QUEUE_SIZE, SmqType::UNSYNC_SMQ); + ASSERT_TRUE(smq->IsGood()); + + constexpr uint32_t ELEMENT_SIZE = 2; + + auto ret = smq->GetMeta()->Marshalling(data); + ASSERT_TRUE(ret); + data.WriteUint32(ELEMENT_SIZE); + auto status = sampleService->SendRequest(SAMPLE_TRANS_SMQ, data, reply, option); + ASSERT_EQ(status, 0); + + SampleSmqElement t[ELEMENT_SIZE] = {}; + status = smq->Write(&t[0], ELEMENT_SIZE); + EXPECT_NE(status, 0); + constexpr int SEND_TIMES = 20; + for (int i = 0; i < SEND_TIMES; i++) { + t[0].data32 = i; + t[0].data64 = i + 1; + t[1].data32 = i + 1; + t[1].data64 = i + 1; + HDF_LOGI("%{public}s:write smq message %{public}zu", __func__, i); + status = smq->WriteNonBlocking(&t[0], ELEMENT_SIZE); + ASSERT_EQ(status, 0); + } +} \ No newline at end of file diff --git a/uhdf2/host/devhost.c b/uhdf2/host/devhost.c index 62ec850..3978bf9 100644 --- a/uhdf2/host/devhost.c +++ b/uhdf2/host/devhost.c @@ -74,7 +74,7 @@ int main(int argc, char **argv) return HDF_ERR_INVALID_PARAM; } const char *hostName = argv[argc - 1]; - HDF_LOGD("hdf device host %{public}s start", hostName); + HDF_LOGD("hdf device host %{public}s %{public}d start", hostName, hostId); SetProcTitle(argv, hostName); struct IDevHostService *instance = DevHostServiceNewInstance(hostId, hostName); diff --git a/uhdf2/host/test/unittest/sample_driver/BUILD.gn b/uhdf2/host/test/unittest/sample_driver/BUILD.gn index 46bc657..566d423 100644 --- a/uhdf2/host/test/unittest/sample_driver/BUILD.gn +++ b/uhdf2/host/test/unittest/sample_driver/BUILD.gn @@ -19,23 +19,23 @@ group("sample_driver") { ohos_shared_library("libsample_driver") { sources = [ - "sample_driver.c", - "sample_hdi_service.c", - "sample_hdi_service_stub.c", + "sample_driver.cpp", + "sample_hdi_service.cpp", + "sample_hdi_service_stub.cpp", ] deps = [ + "//drivers/adapter/uhdf2/hdi:libhdi", "//drivers/adapter/uhdf2/host:libhdf_host", "//drivers/adapter/uhdf2/ipc:libhdf_ipc_adapter", "//drivers/adapter/uhdf2/utils:libhdf_utils", "//utils/native/base:utils", ] - if (is_standard_system) { - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - } else { - external_deps = [ "hilog:libhilog" ] - } + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] # install_images = [ "vendor" ] subsystem_name = "hdf" diff --git a/uhdf2/host/test/unittest/sample_driver/sample_driver.c b/uhdf2/host/test/unittest/sample_driver/sample_driver.cpp similarity index 84% rename from uhdf2/host/test/unittest/sample_driver/sample_driver.c rename to uhdf2/host/test/unittest/sample_driver/sample_driver.cpp index a591e4e..29eedc1 100644 --- a/uhdf2/host/test/unittest/sample_driver/sample_driver.c +++ b/uhdf2/host/test/unittest/sample_driver/sample_driver.cpp @@ -13,7 +13,6 @@ * limitations under the License. */ -#include "sample_hdi.h" #include #include #include @@ -22,6 +21,7 @@ #include #include #include +#include "sample_hdi.h" #define HDF_LOG_TAG sample_driver @@ -31,25 +31,25 @@ static int32_t SampleServiceDispatch( return SampleServiceOnRemoteRequest(client, cmdId, data, reply); } -void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) +static void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) { (void)deviceObject; return; } -int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) +static int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) { HDF_LOGE("HdfSampleDriverBind enter!"); static struct IDeviceIoService testService = { + .Open = nullptr, .Dispatch = SampleServiceDispatch, - .Open = NULL, - .Release = NULL, + .Release = nullptr, }; deviceObject->service = &testService; return HDF_SUCCESS; } -int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) +static int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) { HDF_LOGE("HdfSampleDriverInit enter, new hdi impl"); if (HdfDeviceObjectSetServInfo(deviceObject, "sample_driver_service") != HDF_SUCCESS) { @@ -58,7 +58,7 @@ int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) return HDF_SUCCESS; } -struct HdfDriverEntry g_sampleDriverEntry = { +static struct HdfDriverEntry g_sampleDriverEntry = { .moduleVersion = 1, .moduleName = "sample_driver", .Bind = HdfSampleDriverBind, @@ -66,5 +66,6 @@ struct HdfDriverEntry g_sampleDriverEntry = { .Release = HdfSampleDriverRelease, }; +extern "C" { HDF_INIT(g_sampleDriverEntry); - +} \ No newline at end of file diff --git a/uhdf2/host/test/unittest/sample_driver/sample_hdi.h b/uhdf2/host/test/unittest/sample_driver/sample_hdi.h index 96ae3b0..b0bd552 100644 --- a/uhdf2/host/test/unittest/sample_driver/sample_hdi.h +++ b/uhdf2/host/test/unittest/sample_driver/sample_hdi.h @@ -20,6 +20,7 @@ #include #include #include +#include struct HdfDeviceObject; struct HdfDeviceIoClient; @@ -31,6 +32,11 @@ struct DataBlock { int c; }; +struct SampleSmqElement { + int32_t data32; + uint64_t data64; +}; + enum { SAMPLE_SERVICE_PING = 0, SAMPLE_SERVICE_SUM, @@ -40,6 +46,7 @@ enum { SAMPLE_REGISTER_DEVICE, SAMPLE_UNREGISTER_DEVICE, SAMPLE_UPDATE_SERVIE, + SAMPLE_TRANS_SMQ, }; struct SampleHdi { @@ -49,9 +56,11 @@ struct SampleHdi { int32_t (*registerDevice)(struct HdfDeviceObject *device, const char *servName); int32_t (*unregisterDevice)(struct HdfDeviceObject *device, const char *servName); int32_t (*updateService)(struct HdfDeviceObject *device, const char *info); + int32_t (*tansSmq)(struct HdfDeviceObject *device, OHOS::HDI::Base::SharedMemQueueMeta *smqMeta, + uint32_t element); }; -const struct SampleHdi *SampleHdiImplInstance(); +const struct SampleHdi *SampleHdiImplInstance(void); int32_t SampleServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply); @@ -59,7 +68,7 @@ int32_t SampleServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId static inline void DataBlockFree(struct DataBlock *dataBlock) { - if (dataBlock != NULL) { + if (dataBlock != nullptr) { OsalMemFree((void *)dataBlock->str); OsalMemFree(dataBlock); } @@ -67,39 +76,39 @@ static inline void DataBlockFree(struct DataBlock *dataBlock) static inline struct DataBlock *DataBlockBlockUnmarshalling(struct HdfSBuf *data) { - const struct DataBlock *dataBlock_ = NULL; + const struct DataBlock *dataBlock_ = nullptr; uint32_t readSize = 0; if (!HdfSbufReadBuffer(data, (const void **)&dataBlock_, &readSize)) { HDF_LOGE("%{public}s: failed to read dataBlock", __func__); - return NULL; + return nullptr; } if (readSize != sizeof(struct DataBlock)) { HDF_LOGE("%{public}s: dataBlock size mismatch %{public}d", __func__, readSize); - return NULL; + return nullptr; } struct DataBlock *dataBlock = (struct DataBlock *)OsalMemAlloc(sizeof(struct DataBlock)); - if (dataBlock == NULL) { - return NULL; + if (dataBlock == nullptr) { + return nullptr; } HDF_LOGD("%{public}s: DataBlock mem: %{public}d %{public}d %{public}d", __func__, dataBlock_->a, dataBlock_->b, dataBlock_->c); if (memcpy_s(dataBlock, sizeof(*dataBlock), dataBlock_, sizeof(*dataBlock)) != EOK) { - return NULL; + return nullptr; } - const char *str = NULL; + const char *str = nullptr; if (!HdfSbufReadBuffer(data, (const void **)&str, &readSize)) { HDF_LOGE("%{public}s: failed to read dataBlock.str", __func__); - return NULL; + return nullptr; } dataBlock->str = strdup(str); - if (dataBlock->str == NULL) { + if (dataBlock->str == nullptr) { OsalMemFree(dataBlock); - return NULL; + return nullptr; } return dataBlock; @@ -118,5 +127,4 @@ static inline bool DataBlockBlockMarshalling(struct DataBlock *dataBlock, struct return true; } - #endif // SAMPLE_SERVICE_HDF_H \ No newline at end of file diff --git a/uhdf2/host/test/unittest/sample_driver/sample_hdi_service.c b/uhdf2/host/test/unittest/sample_driver/sample_hdi_service.cpp similarity index 51% rename from uhdf2/host/test/unittest/sample_driver/sample_hdi_service.c rename to uhdf2/host/test/unittest/sample_driver/sample_hdi_service.cpp index 29c447f..5f5fd07 100644 --- a/uhdf2/host/test/unittest/sample_driver/sample_hdi_service.c +++ b/uhdf2/host/test/unittest/sample_driver/sample_hdi_service.cpp @@ -13,23 +13,33 @@ * limitations under the License. */ -#include "sample_hdi.h" +#include #include #include #include #include #include +#include +#include +#include +#include "sample_hdi.h" #define HDF_LOG_TAG sample_driver +using OHOS::HDI::Base::SharedMemQueue; +using OHOS::HDI::Base::SharedMemQueueMeta; +using OHOS::HDI::Base::SmqType; + +constexpr int SMQ_TRANS_ELEMENT_MAX = 5; +constexpr int SMQ_TRANS_WAIT_TIME = 100; struct SampleDevice { struct DListHead listNode; struct HdfDeviceObject *devobj; }; -struct DListHead g_sampleDeviceList = { NULL }; +static struct DListHead g_sampleDeviceList = { nullptr }; -int32_t SampleServicePing(struct HdfDeviceObject *device, const char *info, char **infoOut) +static int32_t SampleServicePing(struct HdfDeviceObject *device, const char *info, char **infoOut) { (void)device; HDF_LOGI("Sample:info is %{public}s", info); @@ -37,19 +47,19 @@ int32_t SampleServicePing(struct HdfDeviceObject *device, const char *info, char return 0; } -int32_t SampleServiceSum(struct HdfDeviceObject *device, int32_t x0, int32_t x1, int32_t *result) +static int32_t SampleServiceSum(struct HdfDeviceObject *device, int32_t x0, int32_t x1, int32_t *result) { (void)device; *result = x0 + x1; return 0; } -int32_t SampleServiceCallback(struct HdfDeviceObject *device, struct HdfRemoteService *callback, int32_t code) +static int32_t SampleServiceCallback(struct HdfDeviceObject *device, struct HdfRemoteService *callback, int32_t code) { (void)device; struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC); HdfSbufWriteInt32(dataSbuf, code); - int ret = callback->dispatcher->Dispatch(callback, 0, dataSbuf, NULL); + int ret = callback->dispatcher->Dispatch(callback, 0, dataSbuf, nullptr); if (ret != HDF_SUCCESS) { HDF_LOGE("failed to do callback, ret = %{public}d", ret); } @@ -57,10 +67,10 @@ int32_t SampleServiceCallback(struct HdfDeviceObject *device, struct HdfRemoteSe return ret; } -int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char *servName) +static int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char *servName) { struct HdfDeviceObject *dev = HdfDeviceObjectAlloc(device, "libsample_driver.z.so"); - if (dev == NULL) { + if (dev == nullptr) { HDF_LOGE("failed to alloc device object"); return HDF_DEV_ERR_NO_DEVICE; } @@ -78,14 +88,14 @@ int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char * } HDF_LOGE("publish device service %{public}s success", servName); - struct SampleDevice *sampleDev = OsalMemAlloc(sizeof(struct SampleDevice)); - if (sampleDev == NULL) { + struct SampleDevice *sampleDev = (struct SampleDevice *)OsalMemAlloc(sizeof(struct SampleDevice)); + if (sampleDev == nullptr) { HdfDeviceObjectRelease(dev); return HDF_DEV_ERR_NO_MEMORY; } sampleDev->devobj = dev; - if (g_sampleDeviceList.next == NULL) { + if (g_sampleDeviceList.next == nullptr) { DListHeadInit(&g_sampleDeviceList); } DListInsertTail(&sampleDev->listNode, &g_sampleDeviceList); @@ -94,13 +104,14 @@ int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char * return HDF_SUCCESS; } -int32_t SampleServiceUnregisterDevice(struct HdfDeviceObject *device, const char *servName) +static int32_t SampleServiceUnregisterDevice(struct HdfDeviceObject *device, const char *servName) { - struct SampleDevice *sampleDev = NULL; - struct SampleDevice *sampleDevTmp = NULL; + struct SampleDevice *sampleDev = nullptr; + struct SampleDevice *sampleDevTmp = nullptr; HDF_LOGI("remove device %{public}s in", servName); - DLIST_FOR_EACH_ENTRY_SAFE(sampleDev, sampleDevTmp, &g_sampleDeviceList, struct SampleDevice, listNode) { - if (sampleDev->devobj == NULL || HdfDeviceGetServiceName(sampleDev->devobj) == NULL) { + DLIST_FOR_EACH_ENTRY_SAFE(sampleDev, sampleDevTmp, &g_sampleDeviceList, struct SampleDevice, listNode) + { + if (sampleDev->devobj == nullptr || HdfDeviceGetServiceName(sampleDev->devobj) == nullptr) { DListRemove(&sampleDev->listNode); OsalMemFree(sampleDev); continue; @@ -117,7 +128,7 @@ int32_t SampleServiceUnregisterDevice(struct HdfDeviceObject *device, const char return HDF_SUCCESS; } -int32_t SampleServiceUpdateDevice(struct HdfDeviceObject *device, const char *servInfo) +static int32_t SampleServiceUpdateDevice(struct HdfDeviceObject *device, const char *servInfo) { if (HdfDeviceObjectSetServInfo(device, servInfo) != HDF_SUCCESS) { HDF_LOGE("failed to set service info"); @@ -126,6 +137,51 @@ int32_t SampleServiceUpdateDevice(struct HdfDeviceObject *device, const char *se return HdfDeviceObjectUpdate(device); } +static int32_t SampleServiceTansSmq( + struct HdfDeviceObject *device, SharedMemQueueMeta *smqMeta, uint32_t element) +{ + HDF_LOGI("SampleServiceTansSmq in, element=%{public}u", element); + if (element > SMQ_TRANS_ELEMENT_MAX) { + return HDF_ERR_INVALID_PARAM; + } + static std::shared_ptr> smq = nullptr; + smq = std::make_shared>(*smqMeta); + if (!smq->IsGood()) { + HDF_LOGE("failed to create fmq from meta"); + return HDF_FAILURE; + } + static size_t elem = static_cast(element); + std::thread t([&]() { + HDF_LOGI("SampleServiceTansSmq:smq read thread start, elem=%{public}zu", elem); + std::shared_ptr> smqLocal = smq; + size_t elemLocal = elem; + smq = nullptr; + + while (true) { + SampleSmqElement t[SMQ_TRANS_ELEMENT_MAX] = {}; + int ret; + if (smqLocal->GetMeta()->GetType() == SmqType::SYNCED_SMQ) { + ret = smqLocal->Read(&t[0], elemLocal, OHOS::MillisecToNanosec(SMQ_TRANS_WAIT_TIME)); + } else { + ret = smqLocal->ReadNonBlocking(&t[0], elemLocal); + } + if (ret != HDF_SUCCESS) { + HDF_LOGE("failed to read message from smq, %{public}d", ret); + break; + } + for (size_t i = 0; i < elemLocal; i++) { + HDF_LOGI( + "read message from smq, info[%{public}zu]:%{public}d, %{public}llu", + i, t[i].data32, (unsigned long long)t[i].data64); + } + } + }); + t.detach(); + HDF_LOGI("YDEBUG:%{public}s %{public}d", __func__, __LINE__); + + return HDF_SUCCESS; +} + static const struct SampleHdi g_sampleHdiImpl = { .ping = SampleServicePing, .sum = SampleServiceSum, @@ -133,9 +189,10 @@ static const struct SampleHdi g_sampleHdiImpl = { .registerDevice = SampleServiceRegisterDevice, .unregisterDevice = SampleServiceUnregisterDevice, .updateService = SampleServiceUpdateDevice, + .tansSmq = SampleServiceTansSmq, }; -const struct SampleHdi *SampleHdiImplInstance() +const struct SampleHdi *SampleHdiImplInstance(void) { return &g_sampleHdiImpl; } \ No newline at end of file diff --git a/uhdf2/host/test/unittest/sample_driver/sample_hdi_service_stub.c b/uhdf2/host/test/unittest/sample_driver/sample_hdi_service_stub.cpp similarity index 77% rename from uhdf2/host/test/unittest/sample_driver/sample_hdi_service_stub.c rename to uhdf2/host/test/unittest/sample_driver/sample_hdi_service_stub.cpp index 231cb3c..5787118 100644 --- a/uhdf2/host/test/unittest/sample_driver/sample_hdi_service_stub.c +++ b/uhdf2/host/test/unittest/sample_driver/sample_hdi_service_stub.cpp @@ -14,11 +14,16 @@ */ #include +#include #include +#include +#include #include -#include +#include "hdf_sbuf_ipc.h" #include "sample_hdi.h" +using OHOS::HDI::Base::SharedMemQueueMeta; + static int32_t SampleServiceStubPing(struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) { char *outInfo = NULL; @@ -74,8 +79,8 @@ static int32_t SampleServiceStubCallback(struct HdfDeviceIoClient *client, struc return SampleHdiImplInstance()->callback(client->device, callback, code); } -static int32_t SampleServiceStubStructTrans(struct HdfDeviceIoClient *client, - struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t SampleServiceStubStructTrans( + struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) { HDF_LOGI("SampleServiceStubStructTrans: in"); struct DataBlock *dataBlock = DataBlockBlockUnmarshalling(data); @@ -95,12 +100,12 @@ static int32_t SampleServiceStubStructTrans(struct HdfDeviceIoClient *client, return ret; } -#define SAMPLE_TEST_BUFFER_SIZE 10 -static int32_t SampleServiceStubBufferTrans(struct HdfDeviceIoClient *client, - struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t SampleServiceStubBufferTrans( + struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) { HDF_LOGI("SampleServiceStubBufferTrans: in"); + constexpr int SAMPLE_TEST_BUFFER_SIZE = 10; const uint8_t *buffer = HdfSbufReadUnpadBuffer(data, SAMPLE_TEST_BUFFER_SIZE); if (buffer == NULL) { HDF_LOGI("SampleServiceStubBufferTrans: read buffer failed"); @@ -117,8 +122,8 @@ static int32_t SampleServiceStubBufferTrans(struct HdfDeviceIoClient *client, return HDF_SUCCESS; } -static int32_t SampleServiceRegisterDevice(struct HdfDeviceIoClient *client, - struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t SampleServiceRegisterDevice( + struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) { (void)reply; const char *deviceName = HdfSbufReadString(data); @@ -129,8 +134,8 @@ static int32_t SampleServiceRegisterDevice(struct HdfDeviceIoClient *client, return SampleHdiImplInstance()->registerDevice(client->device, deviceName); } -static int32_t SampleServiceUnregisterDevice(struct HdfDeviceIoClient *client, - struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t SampleServiceUnregisterDevice( + struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) { (void)reply; const char *deviceName = HdfSbufReadString(data); @@ -151,10 +156,27 @@ static int32_t SampleServiceUpdateDevice(struct HdfDeviceIoClient *client, struc return SampleHdiImplInstance()->updateService(client->device, servInfo); } -int32_t SampleServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId, - struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t SampleServiceSmqTrans(struct HdfDeviceIoClient *client, struct HdfSBuf *data) +{ + OHOS::MessageParcel *parcel = nullptr; + if (SbufToParcel(data, &parcel) != HDF_SUCCESS) { + return HDF_FAILURE; + } + SharedMemQueueMeta *smqMeta = SharedMemQueueMeta::UnMarshalling(*parcel); + if (smqMeta == nullptr) { + HDF_LOGE("failed to read smq meta form parcel"); + return HDF_ERR_INVALID_PARAM; + } + + uint32_t element = parcel->ReadUint32(); + + return SampleHdiImplInstance()->tansSmq(client->device, smqMeta, element); +} + +int32_t SampleServiceOnRemoteRequest( + struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) { - HDF_LOGI("SampleServiceDispatch: not support cmd %{public}d", cmdId); + HDF_LOGI("SampleServiceDispatch: cmd %{public}d", cmdId); switch (cmdId) { case SAMPLE_SERVICE_PING: return SampleServiceStubPing(client, data, reply); @@ -172,6 +194,8 @@ int32_t SampleServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId return SampleServiceUnregisterDevice(client, data, reply); case SAMPLE_UPDATE_SERVIE: return SampleServiceUpdateDevice(client, data); + case SAMPLE_TRANS_SMQ: + return SampleServiceSmqTrans(client, data); default: HDF_LOGE("SampleServiceDispatch: not support cmd %{public}d", cmdId); return HDF_ERR_INVALID_PARAM; diff --git a/uhdf2/include/hdi/base/hdi_smq.h b/uhdf2/include/hdi/base/hdi_smq.h new file mode 100644 index 0000000..8a7e9c2 --- /dev/null +++ b/uhdf2/include/hdi/base/hdi_smq.h @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 + * + * http://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 HDI_SHARED_MEM_QUEUE_INF_H +#define HDI_SHARED_MEM_QUEUE_INF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#ifndef HDF_LOG_TAG +#define HDF_LOG_TAG smq +#endif + +namespace OHOS { +namespace HDI { +namespace Base { +template +class SharedMemQueue { +public: + SharedMemQueue(uint32_t elementCount, SmqType type); + explicit SharedMemQueue(const SharedMemQueueMeta &meta); + ~SharedMemQueue(); + + int Write(const T *data, size_t count); + int Read(T *data, size_t count); + + int Write(const T *data); + int Read(T *data); + + int Write(const T *data, size_t count, int64_t waitTimeNanoSec); + int Read(T *data, size_t count, int64_t waitTimeNanoSec); + + int WriteNonBlocking(const T *data); + int ReadNonBlocking(T *data); + + int WriteNonBlocking(const T *data, size_t count); + int ReadNonBlocking(T *data, size_t count); + + size_t GetAvalidWriteSize(); + size_t GetAvalidReadSize(); + size_t GetSize(); + std::shared_ptr> GetMeta(); + bool IsGood(); + static inline int64_t GetNanoTime() + { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ts.tv_sec * SEC_TO_NANOSEC + ts.tv_nsec); + } + +private: + void Init(bool resetWriteOffset); + uintptr_t MapMemZone(uint32_t zoneType); + void UnMapMemZone(void *addr, uint32_t zoneType); + size_t Align(size_t num, size_t alignSize); + + int32_t status = HDF_FAILURE; + size_t alignedElmtSize_; + uint8_t *queueBuffer_ = nullptr; + std::atomic *readOffset_ = nullptr; + std::atomic *writeOffset_ = nullptr; + std::atomic *syncerPtr_ = nullptr; + std::unique_ptr syncer_ = nullptr; + std::shared_ptr> meta_ = nullptr; +}; + +template +SharedMemQueue::SharedMemQueue(uint32_t elementCount, SmqType type) : alignedElmtSize_(0) +{ + if (elementCount > UINT16_MAX) { + return; + } + + meta_ = std::make_shared>(elementCount, type); + HDF_LOGI("create SharedMemQueue, count=%{public}u, size=%{public}u", elementCount, meta_->GetSize()); + int ashmemFd = AshmemCreate("hdi_smq", Align(meta_->GetSize(), PAGE_SIZE)); + if (ashmemFd < 0) { + HDF_LOGE("failed to create ashmem"); + return; + } + meta_->SetFd(ashmemFd); + alignedElmtSize_ = meta_->GetElemenetSize(); + Init(true); +} + +template +SharedMemQueue::SharedMemQueue(const SharedMemQueueMeta &meta) : alignedElmtSize_(meta.GetElemenetSize()) +{ + meta_ = std::make_shared>(meta); + Init(false); +} + +template +SharedMemQueue::~SharedMemQueue() +{ + if (meta_ != nullptr && meta_->GetType() == SYNCED_SMQ && readOffset_ != nullptr) { + UnMapMemZone(readOffset_, SharedMemQueueMeta::MemZoneType::MEMZONE_RPTR); + } else { + delete readOffset_; + } + + if (writeOffset_ != nullptr) { + UnMapMemZone(writeOffset_, SharedMemQueueMeta::MEMZONE_WPTR); + } + + if (syncerPtr_ != nullptr) { + UnMapMemZone(syncerPtr_, SharedMemQueueMeta::MEMZONE_SYNCER); + } + + if (queueBuffer_ != nullptr) { + UnMapMemZone(queueBuffer_, SharedMemQueueMeta::MEMZONE_DATA); + } +} + +template +void SharedMemQueue::Init(bool resetWriteOffset) +{ + if (meta_ == nullptr || meta_->GetElemenetSize() != sizeof(T)) { + HDF_LOGE("invalid smq meta for init"); + return; + } + + if (meta_->GetType() == SYNCED_SMQ) { + readOffset_ = reinterpret_cast *>(MapMemZone(SharedMemQueueMeta::MEMZONE_RPTR)); + } else { + readOffset_ = new std::atomic; + } + + if (readOffset_ == nullptr) { + HDF_LOGE("failed to map read offset"); + return; + } + + writeOffset_ = reinterpret_cast *>(MapMemZone(SharedMemQueueMeta::MEMZONE_WPTR)); + if (writeOffset_ == nullptr) { + HDF_LOGE("failed to map write offset"); + return; + } + + syncerPtr_ = reinterpret_cast *>(MapMemZone(SharedMemQueueMeta::MEMZONE_SYNCER)); + if (syncerPtr_ == nullptr) { + HDF_LOGE("failed to map sync ptr"); + return; + } + + queueBuffer_ = reinterpret_cast(MapMemZone(SharedMemQueueMeta::MEMZONE_DATA)); + if (queueBuffer_ == nullptr) { + HDF_LOGE("failed to map queue buffer"); + return; + } + + syncer_ = std::make_unique(syncerPtr_); + + if (resetWriteOffset) { + writeOffset_->store(0, std::memory_order_release); + } + readOffset_->store(0, std::memory_order_release); + HDF_LOGI("smq init succ"); + status = HDF_SUCCESS; +} + +template +uintptr_t SharedMemQueue::MapMemZone(uint32_t zoneType) +{ + auto memzone = meta_->GetMemZone(zoneType); + if (memzone == nullptr) { + HDF_LOGE("invalid smq mem zone type %{public}u", zoneType); + return reinterpret_cast(nullptr); + } + + int offset = (memzone->offset / PAGE_SIZE) * PAGE_SIZE; + int length = memzone->offset - offset + memzone->size; + + void *ptr = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, meta_->GetFd(), offset); + if (ptr == MAP_FAILED) { + HDF_LOGE( + "failed to map memzone %{public}u, size %{public}u, offset %{public}u , fd %{public}d, errnor=%{public}d", + zoneType, length, offset, meta_->GetFd(), errno); + return reinterpret_cast(nullptr); + } + return (reinterpret_cast(ptr) + (memzone->offset - offset)); +} + +template +void SharedMemQueue::UnMapMemZone(void *addr, uint32_t zoneType) +{ + auto memzone = meta_->GetMemZone(zoneType); + if (memzone == nullptr) { + return; + } + int offset = (memzone->offset / PAGE_SIZE) * PAGE_SIZE; + int length = memzone->offset - offset + memzone->size; + uint8_t *ptr = reinterpret_cast(addr) - (memzone->offset - offset); + if (ptr == nullptr) { + return; + } + munmap(ptr, length); +} + +template +bool SharedMemQueue::IsGood() +{ + return status == HDF_SUCCESS; +} + +template +size_t SharedMemQueue::Align(size_t num, size_t alignSize) +{ + return (num + alignSize - 1) & ~(alignSize - 1); +} + +template +int SharedMemQueue::Write(const T *data, size_t count) +{ + return Write(data, count, 0); +} + +template +int SharedMemQueue::Read(T *data, size_t count) +{ + return Read(data, count, 0); +} + +template +int SharedMemQueue::Write(const T *data) +{ + return Write(data, 1, 0); +} + +template +int SharedMemQueue::Read(T *data) +{ + return Read(data, 1, 0); +} + +template +int SharedMemQueue::Write(const T *data, size_t count, int64_t waitTimeNanoSec) +{ + if (meta_->GetType() != SmqType::SYNCED_SMQ) { + HDF_LOGE("unsynecd smq not support blocking write"); + return HDF_ERR_NOT_SUPPORT; + } + + if (WriteNonBlocking(data, count) == 0) { + return syncer_->Wake(SharedMemQueueSyncer::SYNC_WORD_READ); + } + + int ret = 0; + auto startTime = GetNanoTime(); + uint64_t currentTime = startTime; + while (true) { + if (waitTimeNanoSec != 0) { + currentTime = GetNanoTime(); + if (GetNanoTime() - startTime >= waitTimeNanoSec) { + ret = WriteNonBlocking(data, count); + break; + } + waitTimeNanoSec -= currentTime - startTime; + } + ret = syncer_->Wait(SharedMemQueueSyncer::SYNC_WORD_WRITE, waitTimeNanoSec); + if (ret != 0 && ret != -ETIMEDOUT) { + break; + } + + ret = WriteNonBlocking(data, count); + if (ret == 0) { + break; + } + HDF_LOGE("failed to write %{public}zu, retry", count); + } + + if (ret == 0) { + ret = syncer_->Wake(SharedMemQueueSyncer::SYNC_WORD_READ); + } else { + HDF_LOGE("failed to write %{public}zu, ret=%{public}d", count, ret); + } + + return ret; +} + +template +int SharedMemQueue::Read(T *data, size_t count, int64_t waitTimeNanoSec) +{ + if (meta_->GetType() != SmqType::SYNCED_SMQ) { + HDF_LOGE("unsynecd smq not support blocking read"); + return HDF_ERR_NOT_SUPPORT; + } + + if (ReadNonBlocking(data, count) == 0) { + return syncer_->Wake(SharedMemQueueSyncer::SYNC_WORD_WRITE); + } + + int ret = -ENODATA; + auto startTime = GetNanoTime(); + int64_t currentTime; + while (true) { + if (waitTimeNanoSec != 0) { + currentTime = GetNanoTime(); + if (currentTime - startTime >= waitTimeNanoSec) { + ret = ReadNonBlocking(data, count); + break; + } + waitTimeNanoSec -= currentTime - startTime; + } + ret = syncer_->Wait(SharedMemQueueSyncer::SYNC_WORD_READ, waitTimeNanoSec); + if (ret != 0 && ret != -ETIMEDOUT) { + break; + } + + ret = ReadNonBlocking(data, count); + if (ret == 0) { + break; + } + } + if (ret == 0) { + ret = syncer_->Wake(SharedMemQueueSyncer::SYNC_WORD_WRITE); + } else { + HDF_LOGE("failed to read %{public}zu, ret=%{public}d", count, ret); + } + + return ret; +} + +template +int SharedMemQueue::WriteNonBlocking(const T *data) +{ + return WriteNonBlocking(data, 1); +} + +template +int SharedMemQueue::ReadNonBlocking(T *data) +{ + return ReadNonBlocking(data, 1); +} + +template +int SharedMemQueue::WriteNonBlocking(const T *data, size_t count) +{ + auto avalidWrite = GetAvalidWriteSize(); + if (count > avalidWrite) { + return -E2BIG; + } + + if (count == avalidWrite && meta_->GetType() == SmqType::SYNCED_SMQ) { + // synced smq can not overflow write + return -E2BIG; + } + + auto wOffset = writeOffset_->load(std::memory_order_acquire); + auto rOffset = readOffset_->load(std::memory_order_acquire); + uint64_t newWriteOffset; + auto qCount = meta_->GetElementCount(); + if (wOffset + count <= qCount) { + if (memcpy_s(queueBuffer_ + (wOffset * sizeof(T)), (qCount - wOffset) * sizeof(T), + data, count * sizeof(T)) != EOK) { + return HDF_FAILURE; + }; + newWriteOffset = (wOffset + count) % qCount; + } else { + size_t firstPartSize = qCount - wOffset; + size_t secParcSize = count - firstPartSize; + if (memcpy_s(queueBuffer_ + (wOffset * sizeof(T)), (qCount - wOffset) * sizeof(T), + data, firstPartSize * sizeof(T)) != EOK) { + return HDF_FAILURE; + } + if (memcpy_s(queueBuffer_, qCount * sizeof(T), data + firstPartSize, secParcSize * sizeof(T)) != EOK) { + return HDF_FAILURE; + } + newWriteOffset = secParcSize; + } + + writeOffset_->store(newWriteOffset, std::memory_order_release); + if (wOffset < rOffset && newWriteOffset >= rOffset) { + HDF_LOGW("warning:smp ring buffer overflow"); + } + return 0; +} + +template +int SharedMemQueue::ReadNonBlocking(T *data, size_t count) +{ + if (count == 0) { + return -EINVAL; + } + + if (count > GetAvalidReadSize()) { + return -ENODATA; + } + + auto qCount = meta_->GetElementCount(); + auto rOffset = readOffset_->load(std::memory_order_acquire); + if (rOffset + count <= qCount) { + if (memcpy_s(data, count * sizeof(T), queueBuffer_ + (rOffset * sizeof(T)), count * sizeof(T)) != EOK) { + return HDF_FAILURE; + } + readOffset_->store((rOffset + count) % qCount, std::memory_order_release); + return 0; + } + + size_t firstPartSize = qCount - rOffset; + size_t secPartSize = count - firstPartSize; + + if (memcpy_s(data, count * sizeof(T), queueBuffer_ + (rOffset * sizeof(T)), firstPartSize * sizeof(T)) != EOK) { + return HDF_FAILURE; + } + if (memcpy_s(data + firstPartSize, (count - firstPartSize) * sizeof(T), + queueBuffer_, secPartSize * sizeof(T)) != EOK) { + return HDF_FAILURE; + }; + readOffset_->store(secPartSize, std::memory_order_release); + + return 0; +} + +template +size_t SharedMemQueue::GetAvalidWriteSize() +{ + return meta_->GetElementCount() - GetAvalidReadSize(); +} + +template +size_t SharedMemQueue::GetAvalidReadSize() +{ + auto wOffset = writeOffset_->load(std::memory_order_acquire); + auto rOffset = readOffset_->load(std::memory_order_acquire); + auto size = wOffset >= rOffset ? (wOffset - rOffset) : (wOffset + meta_->GetElementCount() - rOffset); + return size; +} + +template +size_t SharedMemQueue::GetSize() +{ + return meta_->GetSize(); +} + +template +std::shared_ptr> SharedMemQueue::GetMeta() +{ + return meta_; +} +} // namespace Base +} // namespace HDI +} // namespace OHOS + +#ifdef HDF_LOG_TAG +#undef HDF_LOG_TAG +#endif + +#endif /* HDI_SHARED_MEM_QUEUEHDI_INF_H */ diff --git a/uhdf2/include/hdi/base/hdi_smq_meta.h b/uhdf2/include/hdi/base/hdi_smq_meta.h new file mode 100644 index 0000000..877f1fb --- /dev/null +++ b/uhdf2/include/hdi/base/hdi_smq_meta.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 + * + * http://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 HDI_SHARED_MEM_QUEUE_META_H +#define HDI_SHARED_MEM_QUEUE_META_H + +#include +#include +#include +#include + +#ifndef HDF_LOG_TAG +#define HDF_LOG_TAG smq +#endif + +namespace OHOS { +namespace HDI { +namespace Base { +enum SmqType : uint32_t { + SYNCED_SMQ = 0x01, + UNSYNC_SMQ = 0x02, +}; + +struct MemZone { + uint32_t size; + uint32_t offset; +}; + +template +class SharedMemQueueMeta { +public: + SharedMemQueueMeta() : SharedMemQueueMeta(-1, 0, 0) {}; + SharedMemQueueMeta(size_t elementCount, SmqType type) : SharedMemQueueMeta(-1, elementCount, type) {}; + SharedMemQueueMeta(int fd, size_t elementCount, SmqType type); + SharedMemQueueMeta(const SharedMemQueueMeta &other); + ~SharedMemQueueMeta() = default; + + void SetFd(int fd); + int GetFd(); + size_t GetSize(); + uint32_t GetType(); + size_t GetElementCount(); + size_t GetElemenetSize() const; + enum MemZoneType : uint32_t { + MEMZONE_RPTR = 0, + MEMZONE_WPTR, + MEMZONE_SYNCER, + MEMZONE_DATA, + MEMZONE_COUNT, + }; + + MemZone *GetMemZone(uint32_t type); + bool Marshalling(MessageParcel &parcel); + static SharedMemQueueMeta *UnMarshalling(MessageParcel &parcel); + + size_t AlignToWord(size_t num) + { + constexpr uint32_t alignByteSize = 8; + return (num + alignByteSize - 1) & (~(alignByteSize - 1)); + } + +private: + int ashmemFd_; + size_t size_; + size_t elementCount_; + size_t elementSize_; + SmqType type_; + MemZone memzone_[MEMZONE_COUNT]; +}; + +template +SharedMemQueueMeta::SharedMemQueueMeta(int fd, size_t elementCount, SmqType type) + : ashmemFd_(fd), size_(0), elementCount_(elementCount), elementSize_(AlignToWord(sizeof(T))), type_(type) +{ + // max size UIN32_MAX byte + if (elementCount_ > UINT32_MAX / elementSize_) { + return; + } + + size_t dataSize = elementCount_ * elementSize_; + size_t memZoneSize[] = { + sizeof(uint64_t), // read ptr + sizeof(uint64_t), // write ptr + sizeof(uint32_t), // sync word + dataSize, + }; + + size_t offset = 0; + for (size_t i = 0; i < MEMZONE_COUNT; offset += memZoneSize[i++]) { + memzone_[i].offset = AlignToWord(offset); + memzone_[i].size = memZoneSize[i]; + } + + size_ = memzone_[MEMZONE_DATA].offset + memzone_[MEMZONE_DATA].size; +} + +template +SharedMemQueueMeta::SharedMemQueueMeta(const SharedMemQueueMeta &other) +{ + if (ashmemFd_ >= 0) { + close(ashmemFd_); + } + + ashmemFd_ = dup(other.ashmemFd_); + if (ashmemFd_ < 0) { + HDF_LOGW("failed to dup ashmem fd for smq"); + } + elementCount_ = other.elementCount_; + elementSize_ = other.elementSize_; + size_ = other.size_; + type_ = other.type_; + memcpy(memzone_, other.memzone_, sizeof(memzone_)); +} + +template +void SharedMemQueueMeta::SetFd(int fd) +{ + if (ashmemFd_ >= 0) { + close(ashmemFd_); + } + ashmemFd_ = fd; +} + +template +int SharedMemQueueMeta::GetFd() +{ + return ashmemFd_; +} + +template +size_t SharedMemQueueMeta::GetSize() +{ + return size_; +} + +template +uint32_t SharedMemQueueMeta::GetType() +{ + return type_; +} + +template +size_t SharedMemQueueMeta::GetElementCount() +{ + return elementCount_; +} + +template +size_t SharedMemQueueMeta::GetElemenetSize() const +{ + return elementSize_; +} + +template +MemZone *SharedMemQueueMeta::GetMemZone(uint32_t type) +{ + if (type >= MEMZONE_COUNT) { + return nullptr; + } + + return &memzone_[type]; +} + +template +bool SharedMemQueueMeta::Marshalling(MessageParcel &parcel) +{ + if (!parcel.WriteBuffer(this, sizeof(SharedMemQueueMeta))) { + return false; + } + + return parcel.WriteFileDescriptor(ashmemFd_); +} + +template +SharedMemQueueMeta *SharedMemQueueMeta::UnMarshalling(MessageParcel &parcel) +{ + auto readMeta = reinterpret_cast *>(parcel.ReadBuffer(sizeof(SharedMemQueueMeta))); + if (readMeta == nullptr) { + HDF_LOGE("read invalid smq meta"); + return nullptr; + } + + auto fd = parcel.ReadFileDescriptor(); + if (fd < 0) { + HDF_LOGE("read invalid smq fd"); + return nullptr; + } + + auto meta = new SharedMemQueueMeta(*readMeta); + meta->SetFd(fd); + + return meta; +} +} // namespace Base +} // namespace HDI +} // namespace OHOS + +#ifdef HDF_LOG_TAG +#undef HDF_LOG_TAG +#endif + +#endif /* HDI_SHARED_MEM_QUEUE_META_H */ diff --git a/uhdf2/include/hdi/base/hdi_smq_syncer.h b/uhdf2/include/hdi/base/hdi_smq_syncer.h new file mode 100644 index 0000000..da76653 --- /dev/null +++ b/uhdf2/include/hdi/base/hdi_smq_syncer.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 + * + * http://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 HDI_SHARED_MEM_QUEUE_SYNCER_H +#define HDI_SHARED_MEM_QUEUE_SYNCER_H + +#include +#include +#include + +namespace OHOS { +namespace HDI { +namespace Base { +class SharedMemQueueSyncer { +public: + explicit SharedMemQueueSyncer(std::atomic *syncerPtr); + ~SharedMemQueueSyncer() = default; + enum SyncWord : uint32_t { + SYNC_WORD_WRITE = 0x01, + SYNC_WORD_READ = 0x02, + }; + + int Wait(uint32_t bitset, int64_t timeoutNanoSec); + int Wake(uint32_t bitset); + +private: + int FutexWait(uint32_t bitset, int64_t timeoutNanoSec); + void TimeoutToRealtime(int64_t timeout, struct timespec &realtime); + std::atomic *syncAddr_; +}; +} // namespace Base +} // namespace HDI +} // namespace OHOS + +#endif /* HDI_SHARED_MEM_QUEUE_SYNCER_H */ diff --git a/uhdf2/manager/src/devmgr_service_full.c b/uhdf2/manager/src/devmgr_service_full.c index 4bcd58e..335a7cf 100644 --- a/uhdf2/manager/src/devmgr_service_full.c +++ b/uhdf2/manager/src/devmgr_service_full.c @@ -16,6 +16,7 @@ #include "devmgr_service_full.h" #include "devhost_service.h" #include "devhost_service_clnt.h" +#include "devhost_service_proxy.h" #include "device_token_clnt.h" #include "hdf_device_token.h" #include "hdf_driver_installer.h" @@ -31,29 +32,48 @@ static Map g_hostMap = {0}; #define HOST_INIT_DIE_NUM 1 #define HOST_MAX_DIE_NUM 3 +static void CleanupDiedHostResources(struct DevHostServiceClnt *hostClnt) +{ + hostClnt->hostPid = INVALID_PID; + if (hostClnt->hostService != NULL) { + struct DevHostServiceProxy *hostProxy = (struct DevHostServiceProxy *)hostClnt->hostService; + DevHostServiceProxyRecycle(hostProxy); + hostClnt->hostService = NULL; + } + + HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete); +} + static int32_t DevmgrServiceFullHandleDeviceHostDied(struct DevHostServiceClnt *hostClnt) { - if (!HdfSListIsEmpty(&hostClnt->devices)) { - if (g_hostMap.nodeSize == 0) { - MapInit(&g_hostMap); - } - int *hostDieValue = (int *)MapGet(&g_hostMap, hostClnt->hostName); - if (hostDieValue == NULL) { - int hostDieNum = HOST_INIT_DIE_NUM; - MapSet(&g_hostMap, hostClnt->hostName, &hostDieNum, sizeof(int)); - } else { - if (*hostDieValue > HOST_MAX_DIE_NUM) { - HDF_LOGE("host %{public}s die 4 times, remove it", hostClnt->hostName); - *hostDieValue = 0; - return INVALID_PID; - } - (*hostDieValue)++; - } - struct IDriverInstaller *installer = DriverInstallerGetInstance(); - if (installer != NULL && installer->StartDeviceHost != NULL) { - hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName); - return hostClnt->hostPid; + bool isHostEmpty = HdfSListIsEmpty(&hostClnt->devices); + + CleanupDiedHostResources(hostClnt); + if (isHostEmpty) { + return INVALID_PID; + } + + if (g_hostMap.nodeSize == 0) { + MapInit(&g_hostMap); + } + int *hostDieValue = (int *)MapGet(&g_hostMap, hostClnt->hostName); + if (hostDieValue == NULL) { + int hostDieNum = HOST_INIT_DIE_NUM; + MapSet(&g_hostMap, hostClnt->hostName, &hostDieNum, sizeof(int)); + } else { + if (*hostDieValue > HOST_MAX_DIE_NUM) { + HDF_LOGE("host %{public}s die 4 times, remove it", hostClnt->hostName); + *hostDieValue = 0; + return INVALID_PID; } + (*hostDieValue)++; + } + HDF_LOGI("%{public}s:%{public}d", __func__, __LINE__); + struct IDriverInstaller *installer = DriverInstallerGetInstance(); + if (installer != NULL && installer->StartDeviceHost != NULL) { + HDF_LOGI("%{public}s:%{public}d", __func__, __LINE__); + hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName); + return hostClnt->hostPid; } return INVALID_PID; } @@ -70,9 +90,8 @@ void DevmgrServiceFullOnDeviceHostDied(struct DevmgrServiceFull *inst, uint32_t DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &inst->super.hosts, struct DevHostServiceClnt, node) { if (hostClnt->hostId == hostId) { int32_t ret = DevmgrServiceFullHandleDeviceHostDied(hostClnt); - if (ret == INVALID_PID && HdfSListIsEmpty(&hostClnt->dynamicDevInfos)) { - DListRemove(&hostClnt->node); - DevHostServiceClntFreeInstance(hostClnt); + if (ret == INVALID_PID) { + HDF_LOGE("%{public}s: failed to respawn host %{public}s", __func__, hostClnt->hostName); } break; } @@ -96,14 +115,14 @@ int32_t DevmgrServiceFullDispatchMessage(struct HdfMessageTask *task, struct Hdf break; } default: { - HDF_LOGE("Message is wrong, message is %{public}u", msg->messageId); + HDF_LOGE("wrong message(%{public}u)", msg->messageId); } } return HDF_SUCCESS; } -struct HdfMessageTask *DevmgrServiceFullGetMessageTask() +struct HdfMessageTask *DevmgrServiceFullGetMessageTask(void) { struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)DevmgrServiceGetInstance(); @@ -126,7 +145,7 @@ void DevmgrServiceFullConstruct(struct DevmgrServiceFull *inst) } } -struct HdfObject *DevmgrServiceFullCreate() +struct HdfObject *DevmgrServiceFullCreate(void) { static struct DevmgrServiceFull *instance = NULL; if (instance == NULL) { diff --git a/uhdf2/manager/src/devmgr_service_stub.c b/uhdf2/manager/src/devmgr_service_stub.c index 7032ab8..87cde38 100644 --- a/uhdf2/manager/src/devmgr_service_stub.c +++ b/uhdf2/manager/src/devmgr_service_stub.c @@ -124,7 +124,8 @@ int32_t DevmgrServiceStubDispatch( break; } if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s devmgr service stub dispach failed, cmd id is %{public}d", __func__, code); + HDF_LOGE("%{public}s devmgr service stub dispach failed, cmd id is %{public}d, ret = %{public}d", + __func__, code, ret); HdfSbufWriteInt32(reply, ret); } diff --git a/uhdf2/manager/src/devsvc_manager_stub.c b/uhdf2/manager/src/devsvc_manager_stub.c index a0db62d..f809107 100644 --- a/uhdf2/manager/src/devsvc_manager_stub.c +++ b/uhdf2/manager/src/devsvc_manager_stub.c @@ -14,10 +14,11 @@ */ #include "devsvc_manager_stub.h" -#include "devsvc_listener_holder.h" #include "device_token_proxy.h" #include "devmgr_service_stub.h" +#include "devsvc_listener_holder.h" #include "devsvc_manager_proxy.h" +#include "hdf_cstring.h" #include "hdf_log.h" #include "hdf_sbuf.h" #include "hdf_slist.h" @@ -49,9 +50,15 @@ static int32_t DevSvcManagerStubAddService(struct IDevSvcManager *super, struct HdfRemoteServiceAddDeathRecipient(service, &stub->recipient); struct HdfDeviceObject *deviceObject = OsalMemCalloc(sizeof(struct HdfDeviceObject)); if (deviceObject == NULL) { - return ret; + return HDF_ERR_MALLOC_FAIL; + } + deviceObject->priv = (void *)HdfStringCopy(name); + if (deviceObject->priv == NULL) { + OsalMemFree(deviceObject); + return HDF_ERR_MALLOC_FAIL; } deviceObject->service = (struct IDeviceIoService *)service; + service->target = (struct HdfObject *)deviceObject; ret = super->AddService(super, name, devClass, deviceObject, servInfo); if (ret != HDF_SUCCESS) { OsalMemFree(deviceObject); @@ -93,8 +100,7 @@ static int32_t DevSvcManagerStubUpdateService(struct IDevSvcManager *super, stru return ret; } -static int32_t DevSvcManagerStubGetService( - struct IDevSvcManager *super, struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t DevSvcManagerStubGetService(struct IDevSvcManager *super, struct HdfSBuf *data, struct HdfSBuf *reply) { int ret = HDF_FAILURE; const char *name = HdfSbufReadString(data); @@ -102,8 +108,7 @@ static int32_t DevSvcManagerStubGetService( HDF_LOGE("%{public}s failed, name is null", __func__); return ret; } - struct HdfRemoteService *remoteService = - (struct HdfRemoteService *)super->GetService(super, name); + struct HdfRemoteService *remoteService = (struct HdfRemoteService *)super->GetService(super, name); if (remoteService != NULL) { ret = HDF_SUCCESS; HdfSBufWriteRemoteService(reply, remoteService); @@ -139,8 +144,8 @@ static int32_t DevSvcManagerStubRegisterServListener(struct IDevSvcManager *supe return HDF_ERR_INVALID_PARAM; } - struct ServStatListenerHolder *listenerHolder = - ServStatListenerHolderCreate((uintptr_t)listenerRemote, listenClass); + struct ServStatListenerHolder *listenerHolder + = ServStatListenerHolderCreate((uintptr_t)listenerRemote, listenClass); if (listenerHolder == NULL) { return HDF_ERR_MALLOC_FAIL; } @@ -161,8 +166,7 @@ static int32_t DevSvcManagerStubUnregisterServListener(struct IDevSvcManager *su if (listenerRemote == NULL) { return HDF_ERR_INVALID_PARAM; } - struct ServStatListenerHolder *listenerHolder = - ServStatListenerHolderGet(listenerRemote->index); + struct ServStatListenerHolder *listenerHolder = ServStatListenerHolderGet(listenerRemote->index); if (listenerHolder == NULL) { HDF_LOGE("failed to unregister svcstat listener, unknown listener"); HdfRemoteServiceRecycle(listenerRemote); @@ -175,8 +179,7 @@ static int32_t DevSvcManagerStubUnregisterServListener(struct IDevSvcManager *su return HDF_SUCCESS; } -int DevSvcManagerStubDispatch( - struct HdfRemoteService* service, int code, struct HdfSBuf *data, struct HdfSBuf *reply) +int DevSvcManagerStubDispatch(struct HdfRemoteService *service, int code, struct HdfSBuf *data, struct HdfSBuf *reply) { int ret = HDF_FAILURE; struct DevSvcManagerStub *stub = (struct DevSvcManagerStub *)service; @@ -211,21 +214,42 @@ int DevSvcManagerStubDispatch( return ret; } -void DevSvcManagerOnServiceDied(struct HdfDeathRecipient *recipient, struct HdfRemoteService *service) +void DevSvcManagerOnServiceDied(struct HdfDeathRecipient *recipient, struct HdfRemoteService *remote) { - (void)service; - struct DevSvcManagerStub *stub = - HDF_SLIST_CONTAINER_OF(struct HdfDeathRecipient, recipient, struct DevSvcManagerStub, recipient); - if (stub != NULL) { - struct IDevSvcManager *svcOps = (struct IDevSvcManager *)stub; - if (svcOps->RemoveService != NULL) { - svcOps->RemoveService(svcOps, NULL); - } + struct DevSvcManagerStub *stub + = HDF_SLIST_CONTAINER_OF(struct HdfDeathRecipient, recipient, struct DevSvcManagerStub, recipient); + if (stub == NULL) { return; } + + struct IDevSvcManager *iSvcMgr = &stub->super.super; + struct HdfDeviceObject *serviceObject = (struct HdfDeviceObject *)remote->target; + + if (serviceObject == NULL || serviceObject->priv == NULL) { + HDF_LOGI("%{public}s:invalid service object", __func__); + return; + } + + if (iSvcMgr->GetService == NULL || iSvcMgr->RemoveService == NULL) { + HDF_LOGI("%{public}s:invalid svcmgr object", __func__); + return; + } + + char *serviceName = (char *)serviceObject->priv; + struct HdfObject *service = iSvcMgr->GetService(iSvcMgr, serviceName); + HDF_LOGI("service %{public}s died", serviceName); + + if ((uintptr_t)service == (uintptr_t)remote) { + HDF_LOGI("%{public}s: remove died service %{public}s", __func__, serviceName); + iSvcMgr->RemoveService(iSvcMgr, serviceName); + } + + OsalMemFree(serviceObject->priv); + OsalMemFree(serviceObject); + HdfRemoteServiceRecycle(remote); } -int DevSvcManagerStubStart(struct IDevSvcManager * svcmgr) +int DevSvcManagerStubStart(struct IDevSvcManager *svcmgr) { struct DevSvcManagerStub *inst = (struct DevSvcManagerStub *)svcmgr; if (inst == NULL) { @@ -237,9 +261,7 @@ int DevSvcManagerStubStart(struct IDevSvcManager * svcmgr) ServStatListenerHolderinit(); - static struct HdfRemoteDispatcher dispatcher = { - .Dispatch = DevSvcManagerStubDispatch - }; + static struct HdfRemoteDispatcher dispatcher = { .Dispatch = DevSvcManagerStubDispatch }; inst->remote = HdfRemoteServiceObtain((struct HdfObject *)inst, &dispatcher); if (inst->remote == NULL) { HDF_LOGE("failed to obtain device service manager remote service"); @@ -273,7 +295,7 @@ static bool DevSvcManagerStubConstruct(struct DevSvcManagerStub *inst) return true; } -struct HdfObject *DevSvcManagerStubCreate() +struct HdfObject *DevSvcManagerStubCreate(void) { static struct DevSvcManagerStub *instance; if (instance != NULL) { @@ -299,4 +321,3 @@ void DevSvcManagerStubRelease(struct HdfObject *object) } } } - diff --git a/uhdf2/utils/BUILD.gn b/uhdf2/utils/BUILD.gn index b2183d4..77ef9a8 100644 --- a/uhdf2/utils/BUILD.gn +++ b/uhdf2/utils/BUILD.gn @@ -76,6 +76,7 @@ ohos_shared_library("libhdf_utils") { "$hdf_uhdf_path/osal/src/osal_sysevent.c", "$hdf_uhdf_path/utils/src/hcs_parser/hcs_blob_load.c", "$hdf_uhdf_path/utils/src/hcs_parser/hcs_dm_parser.c", + "$hdf_uhdf_path/utils/src/shared_mem.cpp", ] deps = [ "//utils/native/base:utils" ] diff --git a/uhdf2/utils/include/shared_mem.h b/uhdf2/utils/include/shared_mem.h new file mode 100644 index 0000000..ed162e2 --- /dev/null +++ b/uhdf2/utils/include/shared_mem.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 + * + * http://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 HDF_SHARED_MEM_H +#define HDF_SHARED_MEM_H + +#include "hdf_base.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int SharedMemCreate(const char *name, size_t size); +int SharedMemSetProt(int fd, int prot); +int SharedMemGetSize(int fd); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // HDF_SHARED_MEM_H \ No newline at end of file diff --git a/uhdf2/utils/src/shared_mem.cpp b/uhdf2/utils/src/shared_mem.cpp new file mode 100644 index 0000000..73b9db2 --- /dev/null +++ b/uhdf2/utils/src/shared_mem.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 + * + * http://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 "shared_mem.h" +#include + +int SharedMemCreate(const char *name, size_t size) +{ + return OHOS::AshmemCreate(name, size); +} + +int SharedMemSetProt(int fd, int prot) +{ + return OHOS::AshmemSetProt(fd, prot); +} + +int SharedMemGetSize(int fd) +{ + return OHOS::AshmemGetSize(fd); +} \ No newline at end of file -- Gitee