• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "devmgr_service.h"
10 #include "devhost_service_clnt.h"
11 #include "device_token_clnt.h"
12 #include "devsvc_manager.h"
13 #include "hdf_attribute_manager.h"
14 #include "hdf_base.h"
15 #include "hdf_driver_installer.h"
16 #include "hdf_host_info.h"
17 #include "hdf_log.h"
18 #include "hdf_object_manager.h"
19 #include "osal_time.h"
20 
21 #define HDF_LOG_TAG devmgr_service
22 #define INVALID_PID (-1)
23 
DevmgrServiceDynamicDevInfoFound(const char * svcName,struct DevHostServiceClnt ** targetHostClnt,struct HdfDeviceInfo ** targetDeviceInfo)24 static bool DevmgrServiceDynamicDevInfoFound(
25     const char *svcName, struct DevHostServiceClnt **targetHostClnt, struct HdfDeviceInfo **targetDeviceInfo)
26 {
27     struct HdfSListIterator itDeviceInfo;
28     struct HdfDeviceInfo *deviceInfo = NULL;
29     struct DevHostServiceClnt *hostClnt = NULL;
30     struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
31     if (devMgrSvc == NULL) {
32         return false;
33     }
34 
35     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
36         HdfSListIteratorInit(&itDeviceInfo, &hostClnt->dynamicDevInfos);
37         while (HdfSListIteratorHasNext(&itDeviceInfo)) {
38             deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
39             if (strcmp(deviceInfo->svcName, svcName) == 0) {
40                 *targetDeviceInfo = deviceInfo;
41                 *targetHostClnt = hostClnt;
42                 return true;
43             }
44         }
45     }
46 
47     return false;
48 }
49 
50 #define WAIT_HOST_SLEEP_TIME    1 // ms
51 #define WAIT_HOST_SLEEP_CNT     1000
DevmgrServiceStartHostProcess(struct DevHostServiceClnt * hostClnt,bool sync,bool dynamic)52 static int DevmgrServiceStartHostProcess(struct DevHostServiceClnt *hostClnt, bool sync, bool dynamic)
53 {
54     int waitCount = WAIT_HOST_SLEEP_CNT;
55     struct IDriverInstaller *installer = DriverInstallerGetInstance();
56     if (installer == NULL || installer->StartDeviceHost == NULL) {
57         HDF_LOGE("invalid installer");
58         return HDF_FAILURE;
59     }
60 
61     hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName, dynamic);
62     if (hostClnt->hostPid == HDF_FAILURE) {
63         HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);
64         return HDF_FAILURE;
65     }
66     hostClnt->stopFlag = false;
67     if (!sync) {
68         return HDF_SUCCESS;
69     }
70 
71     while (hostClnt->hostService == NULL && waitCount > 0) {
72         OsalMSleep(WAIT_HOST_SLEEP_TIME);
73         waitCount--;
74     }
75 
76     if (waitCount <= 0) {
77         HDF_LOGE("wait host(%{public}s, %{public}d) attach timeout", hostClnt->hostName, hostClnt->hostId);
78         hostClnt->hostPid = -1;
79         return HDF_ERR_TIMEOUT;
80     }
81 
82     return HDF_SUCCESS;
83 }
84 
DevmgrServiceLoadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)85 static int DevmgrServiceLoadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
86 {
87     struct HdfDeviceInfo *deviceInfo = NULL;
88     struct DevHostServiceClnt *hostClnt = NULL;
89     bool dynamic = true;
90     int ret;
91     (void)devMgrSvc;
92 
93     if (serviceName == NULL) {
94         return HDF_ERR_INVALID_PARAM;
95     }
96 
97     if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo)) {
98         HDF_LOGE("device %{public}s not in configed device list", serviceName);
99         return HDF_DEV_ERR_NO_DEVICE;
100     }
101 
102     if (deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
103         HDF_LOGE("device %{public}s not an dynamic load device", serviceName);
104         return HDF_DEV_ERR_NORANGE;
105     }
106 
107     dynamic = HdfSListIsEmpty(&hostClnt->unloadDevInfos) && !HdfSListIsEmpty(&hostClnt->dynamicDevInfos);
108     OsalMutexLock(&hostClnt->hostLock);
109     if (hostClnt->hostPid < 0) {
110         OsalMutexUnlock(&hostClnt->hostLock);
111         if (DevmgrServiceStartHostProcess(hostClnt, true, dynamic) != HDF_SUCCESS) {
112             HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);
113             return HDF_FAILURE;
114         }
115         OsalMutexLock(&hostClnt->hostLock);
116     }
117 
118     if (hostClnt->hostService == NULL || hostClnt->hostService->AddDevice == NULL) {
119         OsalMutexUnlock(&hostClnt->hostLock);
120         HDF_LOGE("%{public}s load %{public}s failed, hostService is null", __func__, serviceName);
121         return HDF_FAILURE;
122     }
123     ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
124     OsalMutexUnlock(&hostClnt->hostLock);
125     if (ret == HDF_SUCCESS) {
126         deviceInfo->status = HDF_SERVICE_USABLE;
127     }
128     return ret;
129 }
130 
DevmgrServiceStopHost(struct DevHostServiceClnt * hostClnt)131 static int DevmgrServiceStopHost(struct DevHostServiceClnt *hostClnt)
132 {
133     struct IDriverInstaller *installer = DriverInstallerGetInstance();
134     if (installer == NULL || installer->StopDeviceHost == NULL) {
135         HDF_LOGE("invalid installer");
136         return HDF_FAILURE;
137     }
138     installer->StopDeviceHost(hostClnt->hostId, hostClnt->hostName);
139     hostClnt->stopFlag = true;
140     return HDF_SUCCESS;
141 }
142 
DevmgrServiceUnloadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)143 static int DevmgrServiceUnloadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
144 {
145     struct HdfDeviceInfo *deviceInfo = NULL;
146     struct DevHostServiceClnt *hostClnt = NULL;
147     int ret;
148     (void)devMgrSvc;
149 
150     if (serviceName == NULL) {
151         return HDF_ERR_INVALID_PARAM;
152     }
153 
154     if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo) ||
155         deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
156         HDF_LOGE("device %{public}s not in configed dynamic device list", serviceName);
157         return HDF_DEV_ERR_NO_DEVICE;
158     }
159     OsalMutexLock(&hostClnt->hostLock);
160     if (hostClnt->hostService == NULL || hostClnt->hostService->DelDevice == NULL) {
161         OsalMutexUnlock(&hostClnt->hostLock);
162         HDF_LOGE("%{public}s unload %{public}s failed, hostService is null", __func__, serviceName);
163         return HDF_FAILURE;
164     }
165     ret = hostClnt->hostService->DelDevice(hostClnt->hostService, deviceInfo->deviceId);
166     if (ret != HDF_SUCCESS) {
167         OsalMutexUnlock(&hostClnt->hostLock);
168         HDF_LOGI("%{public}s:unload service %{public}s delDevice failed", __func__, serviceName);
169         return ret;
170     }
171     deviceInfo->status = HDF_SERVICE_UNUSABLE;
172     if (!HdfSListIsEmpty(&hostClnt->devices)) {
173         OsalMutexUnlock(&hostClnt->hostLock);
174         HDF_LOGD("%{public}s host %{public}s devices is not empty", __func__, hostClnt->hostName);
175         return HDF_SUCCESS;
176     }
177     if (!HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
178         OsalMutexUnlock(&hostClnt->hostLock);
179         HDF_LOGD("%{public}s the hdf_devmgr need not to stop automatically started host %{public}s", __func__,
180             hostClnt->hostName);
181         return HDF_SUCCESS;
182     }
183     hostClnt->hostPid = INVALID_PID;
184     hostClnt->hostService = NULL; // old hostService will be recycled in CleanupDiedHostResources
185     HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete);
186     OsalMutexUnlock(&hostClnt->hostLock);
187     ret = DevmgrServiceStopHost(hostClnt);
188 
189     return ret;
190 }
191 
DevmgrServiceLoadLeftDriver(struct DevmgrService * devMgrSvc)192 int32_t DevmgrServiceLoadLeftDriver(struct DevmgrService *devMgrSvc)
193 {
194     int32_t ret;
195     struct HdfSListIterator itDeviceInfo;
196     struct HdfDeviceInfo *deviceInfo = NULL;
197     struct DevHostServiceClnt *hostClnt = NULL;
198     if (devMgrSvc == NULL) {
199         return HDF_FAILURE;
200     }
201 
202     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
203         HdfSListIteratorInit(&itDeviceInfo, &hostClnt->unloadDevInfos);
204         while (HdfSListIteratorHasNext(&itDeviceInfo)) {
205             deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
206             if (deviceInfo->preload == DEVICE_PRELOAD_ENABLE_STEP2) {
207                 ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
208                 if (ret != HDF_SUCCESS) {
209                     HDF_LOGE("%{public}s:failed to load driver %{public}s", __func__, deviceInfo->moduleName);
210                     continue;
211                 }
212                 deviceInfo->status = HDF_SERVICE_USABLE;
213                 HdfSListIteratorRemove(&itDeviceInfo);
214             }
215         }
216     }
217     return HDF_SUCCESS;
218 }
219 
DevmgrServiceFindDeviceHost(struct IDevmgrService * inst,uint16_t hostId)220 static struct DevHostServiceClnt *DevmgrServiceFindDeviceHost(struct IDevmgrService *inst, uint16_t hostId)
221 {
222     struct DevHostServiceClnt *hostClnt = NULL;
223     struct DevmgrService *dmService = (struct DevmgrService *)inst;
224     if (dmService == NULL) {
225         HDF_LOGE("failed to find device host, dmService is null");
226         return NULL;
227     }
228 
229     DLIST_FOR_EACH_ENTRY(hostClnt, &dmService->hosts, struct DevHostServiceClnt, node) {
230         if (hostClnt->hostId == hostId) {
231             return hostClnt;
232         }
233     }
234     HDF_LOGE("cannot find host %{public}u", hostId);
235     return NULL;
236 }
237 
DevmgrServiceAttachDevice(struct IDevmgrService * inst,struct IHdfDeviceToken * token)238 static int DevmgrServiceAttachDevice(struct IDevmgrService *inst, struct IHdfDeviceToken *token)
239 {
240     struct DevHostServiceClnt *hostClnt = NULL;
241     struct DeviceTokenClnt *tokenClnt = NULL;
242 
243     if (token == NULL) {
244         return HDF_FAILURE;
245     }
246     hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(token->devid));
247     if (hostClnt == NULL) {
248         HDF_LOGE("failed to attach device, hostClnt is null");
249         return HDF_FAILURE;
250     }
251     tokenClnt = DeviceTokenClntNewInstance(token);
252     if (tokenClnt == NULL) {
253         HDF_LOGE("failed to attach device, tokenClnt is null");
254         return HDF_FAILURE;
255     }
256 
257     HdfSListAdd(&hostClnt->devices, &tokenClnt->node);
258     return HDF_SUCCESS;
259 }
260 
HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode * tokenNode,uint32_t devid)261 static bool HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode *tokenNode, uint32_t devid)
262 {
263     struct DeviceTokenClnt *tokenClnt = CONTAINER_OF(tokenNode, struct DeviceTokenClnt, node);
264     return tokenClnt->tokenIf->devid == devid;
265 }
266 
DevmgrServiceDetachDevice(struct IDevmgrService * inst,devid_t devid)267 static int DevmgrServiceDetachDevice(struct IDevmgrService *inst, devid_t devid)
268 {
269     struct DevHostServiceClnt *hostClnt = NULL;
270     struct DeviceTokenClnt *tokenClnt = NULL;
271     struct HdfSListNode *tokenClntNode = NULL;
272 
273     hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(devid));
274     if (hostClnt == NULL) {
275         HDF_LOGE("failed to attach device, hostClnt is null");
276         return HDF_FAILURE;
277     }
278     tokenClntNode = HdfSListSearch(&hostClnt->devices, devid, HdfSListHostSearchDeviceTokenComparer);
279     if (tokenClntNode == NULL) {
280         HDF_LOGE("devmgr detach devic not found");
281         return HDF_DEV_ERR_NO_DEVICE;
282     }
283     tokenClnt = CONTAINER_OF(tokenClntNode, struct DeviceTokenClnt, node);
284     HdfSListRemove(&hostClnt->devices, &tokenClnt->node);
285     return HDF_SUCCESS;
286 }
287 
DevmgrServiceAttachDeviceHost(struct IDevmgrService * inst,uint16_t hostId,struct IDevHostService * hostService)288 static int DevmgrServiceAttachDeviceHost(
289     struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService)
290 {
291     struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);
292     if (hostClnt == NULL) {
293         HDF_LOGE("failed to attach device host, hostClnt is null");
294         return HDF_FAILURE;
295     }
296     if (hostService == NULL) {
297         HDF_LOGE("failed to attach device host, hostService is null");
298         return HDF_FAILURE;
299     }
300 
301     (void)OsalMutexLock(&hostClnt->hostLock);
302     hostClnt->hostService = hostService;
303     (void)OsalMutexUnlock(&hostClnt->hostLock);
304     return DevHostServiceClntInstallDriver(hostClnt);
305 }
306 
DevmgrServiceStartDeviceHost(struct DevmgrService * devmgr,struct HdfHostInfo * hostAttr)307 static int DevmgrServiceStartDeviceHost(struct DevmgrService *devmgr, struct HdfHostInfo *hostAttr)
308 {
309     struct DevHostServiceClnt *hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName);
310     if (hostClnt == NULL) {
311         HDF_LOGW("failed to create new device host client");
312         return HDF_FAILURE;
313     }
314 
315     if (HdfAttributeManagerGetDeviceList(hostClnt) != HDF_SUCCESS) {
316         HDF_LOGW("failed to get device list for host %{public}s", hostClnt->hostName);
317         return HDF_FAILURE;
318     }
319 
320     DListInsertTail(&hostClnt->node, &devmgr->hosts);
321 
322     // not start the host which only have dynamic devices
323     if (HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
324         return HDF_SUCCESS;
325     }
326 
327     if (DevmgrServiceStartHostProcess(hostClnt, false, false) != HDF_SUCCESS) {
328         HDF_LOGW("failed to start device host, host id is %{public}u", hostAttr->hostId);
329         DListRemove(&hostClnt->node);
330         DevHostServiceClntFreeInstance(hostClnt);
331         return HDF_FAILURE;
332     }
333     return HDF_SUCCESS;
334 }
335 
DevmgrServiceStartDeviceHosts(struct DevmgrService * inst)336 static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst)
337 {
338     int ret;
339     struct HdfSList hostList;
340     struct HdfSListIterator it;
341     struct HdfHostInfo *hostAttr = NULL;
342 
343     HdfSListInit(&hostList);
344     if (!HdfAttributeManagerGetHostList(&hostList)) {
345         HDF_LOGW("%{public}s: host list is null", __func__);
346         return HDF_SUCCESS;
347     }
348     HdfSListIteratorInit(&it, &hostList);
349     while (HdfSListIteratorHasNext(&it)) {
350         hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it);
351         ret = DevmgrServiceStartDeviceHost(inst, hostAttr);
352         if (ret != HDF_SUCCESS) {
353             HDF_LOGW("%{public}s failed to start device host, host id is %{public}u, host name is '%{public}s'",
354                 __func__, hostAttr->hostId, hostAttr->hostName);
355         }
356     }
357     HdfSListFlush(&hostList, HdfHostInfoDelete);
358     return HDF_SUCCESS;
359 }
360 
DevmgrServiceListAllDevice(struct IDevmgrService * inst,struct HdfSBuf * reply)361 static int32_t DevmgrServiceListAllDevice(struct IDevmgrService *inst, struct HdfSBuf *reply)
362 {
363     struct DevmgrService *devMgrSvc = (struct DevmgrService *)inst;
364     struct DevHostServiceClnt *hostClnt = NULL;
365     struct HdfSListIterator iterator;
366     struct HdfSListNode *node = NULL;
367     const char *name = NULL;
368 
369     if (devMgrSvc == NULL || reply == NULL) {
370         HDF_LOGE("%{public}s failed, parameter is null", __func__);
371         return HDF_FAILURE;
372     }
373 
374     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
375         HdfSbufWriteString(reply, hostClnt->hostName);
376         HdfSbufWriteUint32(reply, hostClnt->hostId);
377         HdfSbufWriteUint32(reply, HdfSListCount(&hostClnt->devices));
378 
379         HdfSListIteratorInit(&iterator, &hostClnt->devices);
380         while (HdfSListIteratorHasNext(&iterator)) {
381             node = HdfSListIteratorNext(&iterator);
382             struct DeviceTokenClnt *tokenClnt = (struct DeviceTokenClnt *)node;
383             if (tokenClnt != NULL && tokenClnt->tokenIf != NULL) {
384                 name = (tokenClnt->tokenIf->deviceName == NULL) ? "" : tokenClnt->tokenIf->deviceName;
385                 HdfSbufWriteString(reply, name);
386                 HdfSbufWriteUint32(reply, tokenClnt->tokenIf->devid);
387                 name = (tokenClnt->tokenIf->servName == NULL) ? "" : tokenClnt->tokenIf->servName;
388                 HdfSbufWriteString(reply, name);
389             } else {
390                 HDF_LOGI("%{public}s host:%{public}s token null", __func__, hostClnt->hostName);
391             }
392         }
393     }
394     return HDF_SUCCESS;
395 }
396 
DevmgrServiceStartService(struct IDevmgrService * inst)397 int DevmgrServiceStartService(struct IDevmgrService *inst)
398 {
399     int ret;
400     struct DevmgrService *dmService = (struct DevmgrService *)inst;
401     if (dmService == NULL) {
402         HDF_LOGE("failed to start device manager service, dmService is null");
403         return HDF_FAILURE;
404     }
405 
406     ret = DevmgrServiceStartDeviceHosts(dmService);
407     int startServiceRet = DevSvcManagerStartService();
408     HDF_LOGI("start svcmgr result %{public}d. Init DeviceHosts info result: %{public}d", startServiceRet, ret);
409     return ret;
410 }
411 
DevmgrServicePowerStateChange(struct IDevmgrService * devmgrService,enum HdfPowerState powerState)412 int DevmgrServicePowerStateChange(struct IDevmgrService *devmgrService, enum HdfPowerState powerState)
413 {
414     struct DevHostServiceClnt *hostClient = NULL;
415     struct DevmgrService *devmgr = NULL;
416     int result = HDF_SUCCESS;
417 
418     if (devmgrService == NULL) {
419         return HDF_ERR_INVALID_OBJECT;
420     }
421 
422     if (!IsValidPowerState(powerState)) {
423         HDF_LOGE("%{public}s:invalid power event %{public}u", __func__, powerState);
424         return HDF_ERR_INVALID_PARAM;
425     }
426     devmgr = CONTAINER_OF(devmgrService, struct DevmgrService, super);
427 
428     if (IsPowerWakeState(powerState)) {
429         HDF_LOGI("%{public}s:wake state %{public}u", __func__, powerState);
430         DLIST_FOR_EACH_ENTRY(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
431             if (hostClient->hostService != NULL) {
432                 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
433                     result = HDF_FAILURE;
434                 }
435             }
436         }
437     } else {
438         HDF_LOGI("%{public}s:suspend state %{public}u", __func__, powerState);
439         DLIST_FOR_EACH_ENTRY_REVERSE(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
440             if (hostClient->hostService != NULL) {
441                 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
442                     result = HDF_FAILURE;
443                 }
444             }
445         }
446     }
447 
448     return result;
449 }
450 
DevmgrServiceConstruct(struct DevmgrService * inst)451 bool DevmgrServiceConstruct(struct DevmgrService *inst)
452 {
453     if (inst == NULL) {
454         HDF_LOGE("%{public}s:inst is null ", __func__);
455         return false;
456     }
457     struct IDevmgrService *devMgrSvcIf = NULL;
458     if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) {
459         HDF_LOGE("%{public}s:failed to mutex init ", __func__);
460         return false;
461     }
462     devMgrSvcIf = (struct IDevmgrService *)inst;
463     if (devMgrSvcIf != NULL) {
464         devMgrSvcIf->AttachDevice = DevmgrServiceAttachDevice;
465         devMgrSvcIf->DetachDevice = DevmgrServiceDetachDevice;
466         devMgrSvcIf->LoadDevice = DevmgrServiceLoadDevice;
467         devMgrSvcIf->UnloadDevice = DevmgrServiceUnloadDevice;
468         devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;
469         devMgrSvcIf->StartService = DevmgrServiceStartService;
470         devMgrSvcIf->PowerStateChange = DevmgrServicePowerStateChange;
471         devMgrSvcIf->ListAllDevice = DevmgrServiceListAllDevice;
472         DListHeadInit(&inst->hosts);
473         return true;
474     } else {
475         return false;
476     }
477 }
478 
DevmgrServiceCreate(void)479 struct HdfObject *DevmgrServiceCreate(void)
480 {
481     static bool isDevMgrServiceInit = false;
482     static struct DevmgrService devmgrServiceInstance;
483     if (!isDevMgrServiceInit) {
484         if (!DevmgrServiceConstruct(&devmgrServiceInstance)) {
485             return NULL;
486         }
487         isDevMgrServiceInit = true;
488     }
489     return (struct HdfObject *)&devmgrServiceInstance;
490 }
491 
DevmgrServiceGetInstance(void)492 struct IDevmgrService *DevmgrServiceGetInstance(void)
493 {
494     static struct IDevmgrService *instance = NULL;
495     if (instance == NULL) {
496         instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);
497     }
498     return instance;
499 }
500 
DevmgrServiceRelease(struct HdfObject * object)501 void DevmgrServiceRelease(struct HdfObject *object)
502 {
503     struct DevmgrService *devmgrService = (struct DevmgrService *)object;
504     struct DevHostServiceClnt *hostClnt = NULL;
505     struct DevHostServiceClnt *hostClntTmp = NULL;
506     if (devmgrService == NULL) {
507         return;
508     }
509     DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &devmgrService->hosts, struct DevHostServiceClnt, node) {
510         DListRemove(&hostClnt->node);
511         DevHostServiceClntDelete(hostClnt);
512     }
513 
514     OsalMutexDestroy(&devmgrService->devMgrMutex);
515 }
516