2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include "daemon/mm_resource_manager_daemon_priv.h"
24 #include "daemon/mm_resource_manager_daemon_conf.h"
25 #include "daemon/mm_resource_manager_daemon_dbus.h"
26 #include "daemon/backend/mm_resource_manager_backend.h"
27 #include "common/mm_resource_manager_utils.h"
31 #define MM_RESOURCE_MANAGER_RESERVED_RM_ARRAY_SIZE 64 /* preallocated size */
32 #define MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE 4 /* preallocated size */
33 #define MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE 32 /* preallocated size */
34 #define MM_RESOURCE_MANGER_NOT_FOUND -1
35 #define RELEASE_CB_SYNC_TIMEOUT 5 /* seconds */
42 /* NULL means, the resource is acquired fully or is not acquired at all */
45 } mm_resource_manager_dmn_res_s;
46 typedef mm_resource_manager_dmn_res_s *mm_resource_manager_dmn_res_p;
49 mm_resource_manager_id id;
50 mm_resource_manager_app_class_e app_class;
52 /* if an element is NULL, there is no such a resource for the current platform. */
53 mm_resource_manager_dmn_res_p resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
55 } mm_resource_manager_dmn_s;
56 typedef mm_resource_manager_dmn_s *mm_resource_manager_dmn_p;
59 mm_resource_manager_dmn_p manager;
60 mm_resource_manager_res_type_e type;
61 mm_resource_manager_res_volume volume;
62 } mm_resource_manager_dmn_release_cb_request_s;
66 static GPtrArray *managers = NULL;
70 static void __destroy_resource(mm_resource_manager_dmn_res_p res);
71 static void __destroy_manager(void *m);
72 static int __search_manager_index(mm_resource_manager_id id);
73 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id);
74 static mm_resource_manager_error_e __check_release_requests(
75 mm_resource_manager_dmn_p manager,
76 mm_resource_manager_dmn_res_request_s *requests);
77 static mm_resource_manager_dmn_res_request_s* __create_increase_requests(
78 mm_resource_manager_dmn_res_request_s *releases,
79 mm_resource_manager_dmn_res_request_s *acquires);
80 static mm_resource_manager_error_e __check_increase_requests(
81 mm_resource_manager_dmn_p manager,
82 mm_resource_manager_dmn_res_request_s *requests);
83 static void __sync_increase_acquire_requests(
84 mm_resource_manager_dmn_res_request_s *increases,
85 mm_resource_manager_dmn_res_request_s *acquires);
86 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
87 mm_resource_manager_dmn_res_request_s *requests);
88 static GArray* __handle_acquire_requests(mm_resource_manager_dmn_p manager,
89 mm_resource_manager_dmn_res_request_s *requests);
90 static void __handle_release_callbacks(GArray *requests);
91 static inline void __add_cb_request(GArray *cb_requests,
92 mm_resource_manager_dmn_p man,
93 mm_resource_manager_res_type_e type,
94 mm_resource_manager_res_volume volume);
95 static void __release_all_resources(mm_resource_manager_dmn_s *manager);
96 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id);
101 gboolean _mmrm_dmn_init(void)
103 unlink(RELEASE_CB_SYNC_PATH);
104 MM_RM_RETVM_IF(mkfifo(RELEASE_CB_SYNC_PATH,
105 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH) == -1, FALSE,
106 "Release callback sync cannot be created");
108 MM_RM_RETVM_IF(mm_resource_manager_backend_init() !=
109 MM_RESOURCE_MANAGER_ERROR_NONE, FALSE,
110 "Back-end cannot be initialized");
112 if (_mmrm_dmn_dbus_init() != MM_RESOURCE_MANAGER_ERROR_NONE) {
113 mm_resource_manager_backend_deinit();
114 MM_RM_ERROR("D-bus server cannot be created");
118 managers = g_ptr_array_new_full(MM_RESOURCE_MANAGER_RESERVED_RM_ARRAY_SIZE,
120 MM_RM_RETVM_IF(managers == NULL, FALSE, "Daemon cannot be initialized");
125 gboolean _mmrm_dmn_deinit()
129 if (mm_resource_manager_backend_deinit() != MM_RESOURCE_MANAGER_ERROR_NONE)
130 MM_RM_ERROR("Error during back-end deinitialization");
132 if (_mmrm_dmn_dbus_deinit() != MM_RESOURCE_MANAGER_ERROR_NONE)
133 MM_RM_ERROR("Error during d-bus server shutdown");
136 for (i = 0; i < managers->len; i++)
137 __release_all_resources((mm_resource_manager_dmn_s*)managers->pdata[i]);
139 mm_resource_manager_backend_commit_all();
140 g_ptr_array_free(managers, TRUE);
142 MM_RM_ERROR("Trying to deinit uninitialized daemon");
145 if (unlink(RELEASE_CB_SYNC_PATH) == -1)
146 MM_RM_ERROR("Release callback sync cannot be removed");
151 mm_resource_manager_error_e _mmrm_dmn_create(
152 mm_resource_manager_app_class_e app_class, mm_resource_manager_id *id)
154 mm_resource_manager_dmn_p man;
155 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
158 MM_RM_RETVM_IF(app_class < 0 ||
159 app_class >= MM_RESOURCE_MANAGER_APP_CLASS_MAX,
160 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Wrong app class");
162 MM_RM_RETVM_IF(conf->priority[app_class] ==
163 MM_RESOURCE_MANAGER_NO_APP_CLASS,
164 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
165 "App class is not supported for the platform");
167 man = g_new0(mm_resource_manager_dmn_s, 1);
168 MM_RM_RAND64(man->id);
169 man->app_class = app_class;
170 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
171 man->resources[i] = conf->max_volume[i] == MM_RESOURCE_MANAGER_NO_RES ?
172 NULL : g_malloc0(sizeof(mm_resource_manager_dmn_s));
175 g_ptr_array_add(managers, man);
179 return MM_RESOURCE_MANAGER_ERROR_NONE;
182 mm_resource_manager_error_e _mmrm_dmn_destroy(mm_resource_manager_id id)
184 int i_man = __search_manager_index(id);
186 MM_RM_RETVM_IF(i_man == MM_RESOURCE_MANGER_NOT_FOUND,
187 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
188 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
190 __release_all_resources((mm_resource_manager_dmn_s*)managers->pdata[i_man]);
191 mm_resource_manager_backend_commit_all();
193 g_ptr_array_remove_index_fast(managers, i_man);
195 return MM_RESOURCE_MANAGER_ERROR_NONE;
198 mm_resource_manager_error_e _mmrm_dmn_commit(mm_resource_manager_id id,
199 mm_resource_manager_dmn_res_request_s *releases,
200 mm_resource_manager_dmn_res_request_s *acquires)
202 mm_resource_manager_dmn_p manager = __search_manager(id);
203 mm_resource_manager_error_e ret = MM_RESOURCE_MANAGER_ERROR_NONE;
204 mm_resource_manager_dmn_res_request_s *increases = NULL;
207 MM_RM_RETVM_IF(manager == NULL,
208 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
209 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
211 (releases == NULL || releases[0].type == MM_RESOURCE_MANAGER_NO_RES) &&
212 (acquires == NULL || acquires[0].type == MM_RESOURCE_MANAGER_NO_RES),
213 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
214 "Commit request is empty");
216 ret = __check_release_requests(manager, releases);
217 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
219 increases = __create_increase_requests(releases, acquires);
220 if (increases == NULL)
221 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
223 ret = __check_increase_requests(manager, increases);
224 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
225 __sync_increase_acquire_requests(increases, acquires);
231 __handle_release_requests(manager, releases);
232 cb_requests = __handle_acquire_requests(manager, acquires);
233 __handle_release_callbacks(cb_requests);
234 if (!mm_resource_manager_backend_commit_all()) {
237 * function can fail only if resource management back-end is not solely
238 * used by mm-resource-manager or if the back-end cannot acquire/release
239 * a resource because of some internal error.
241 * Initiate status disconnected and reload the back-end and the RM
244 kill(getpid(), SIGHUP);
245 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
247 g_array_free(cb_requests, TRUE);
252 void _mmrm_dmn_status_callback(mm_resource_manager_status_e status)
254 _mmrm_dmn_dbus_status_callback(status);
259 static void __destroy_resource(mm_resource_manager_dmn_res_p res)
265 g_array_free(res->parts, TRUE);
270 static void __destroy_manager(void *m)
272 mm_resource_manager_dmn_p man = (mm_resource_manager_dmn_p) m;
275 MM_RM_RETM_IF(man == NULL, "NULL pointer");
277 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
278 __destroy_resource(man->resources[i]);
283 static int __search_manager_index(mm_resource_manager_id id)
287 for (i = managers->len - 1; i >= 0; i--)
288 if (((mm_resource_manager_dmn_p)managers->pdata[i])->id == id)
291 return MM_RESOURCE_MANGER_NOT_FOUND;
294 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id)
296 int i = __search_manager_index(id);
297 return i == MM_RESOURCE_MANGER_NOT_FOUND ? NULL : managers->pdata[i];
300 static mm_resource_manager_error_e __check_release_requests(
301 mm_resource_manager_dmn_p manager,
302 mm_resource_manager_dmn_res_request_s *requests)
304 mm_resource_manager_dmn_res_request_p request;
307 if (requests == NULL)
308 return MM_RESOURCE_MANAGER_ERROR_NONE;
310 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
313 const char *type_s = _mm_resource_manager_get_res_str(request->type);
315 MM_RM_RETVM_IF(manager->resources[request->type] == NULL,
316 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
317 "There is no resource %s for the platform", type_s);
319 if (manager->resources[request->type]->is_acquired) {
320 if (manager->resources[request->type]->parts == NULL) {
321 if (request->volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
322 MM_RM_ERROR("Resource %s is acquired fully,"
323 "but a resource part is tried to be released",
325 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
328 for (i = 0; i < manager->resources[request->type]->parts->len &&
329 ((mm_resource_manager_res_volume*)
330 manager->resources[request->type]->parts->data)[i] !=
331 request->volume; i++);
332 if (i == manager->resources[request->type]->parts->len) {
333 MM_RM_ERROR("Part of %s of volume %d is not acquired",
334 type_s, request->volume);
335 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
339 MM_RM_ERROR("Resource %s is not acquired", type_s);
340 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
344 MM_RM_DEBUG("Release requests are OK");
346 return MM_RESOURCE_MANAGER_ERROR_NONE;
349 static mm_resource_manager_dmn_res_request_s* __create_increase_requests(
350 mm_resource_manager_dmn_res_request_s *releases,
351 mm_resource_manager_dmn_res_request_s *acquires)
355 mm_resource_manager_dmn_res_request_s* result = NULL;
356 mm_resource_manager_dmn_res_request_s* result_iter = NULL;
357 mm_resource_manager_res_volume resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX] = {0};
358 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
360 for (; acquires->type != MM_RESOURCE_MANAGER_NO_RES; acquires++) {
362 if ((resources[acquires->type] > 0 || resources[acquires->type] ==
363 MM_RESOURCE_MANAGER_RES_VOLUME_FULL) && acquires->volume ==
364 MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
365 MM_RM_ERROR("The client tries to acquire %s by part and fully at once",
366 _mm_resource_manager_get_res_str(acquires->type));
370 if (acquires->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
371 resources[acquires->type] = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
373 resources[acquires->type] += acquires->volume;
375 if (resources[acquires->type] > conf->max_volume[acquires->type]) {
377 "The client tries to acquire %d units over max volume of %s",
378 resources[acquires->type] - conf->max_volume[acquires->type],
379 _mm_resource_manager_get_res_str(acquires->type));
384 for (; releases->type != MM_RESOURCE_MANAGER_NO_RES; releases++)
385 if (resources[releases->type] != MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
386 resources[releases->type] -= releases->volume;
388 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
389 if (resources[i] > 0 ||
390 resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
393 result_iter = result = g_new0(mm_resource_manager_dmn_res_request_s,
395 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
396 if (resources[i] > 0 ||
397 resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
398 result_iter->type = i;
399 result_iter->volume = resources[i];
403 result_iter->type = MM_RESOURCE_MANAGER_NO_RES;
408 static mm_resource_manager_error_e __check_increase_requests(
409 mm_resource_manager_dmn_p manager,
410 mm_resource_manager_dmn_res_request_s *requests)
412 mm_resource_manager_dmn_res_request_p request;
413 mm_resource_manager_res_volume remaining_volume;
414 mm_resource_manager_dmn_p i_man;
415 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
416 gboolean resource_conflict = FALSE;
419 if (requests == NULL)
420 return MM_RESOURCE_MANAGER_ERROR_NONE;
422 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
425 const char *type_s = _mm_resource_manager_get_res_str(request->type);
427 MM_RM_RETVM_IF(manager->resources[request->type] == NULL,
428 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
429 "There is no resource %s for the platform", type_s);
431 remaining_volume = conf->max_volume[request->type];
432 for (i = 0; i < managers->len; i++) {
433 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
434 if (i_man != manager && conf->priority[i_man->app_class] >
435 conf->priority[manager->app_class] &&
436 i_man->resources[request->type]->is_acquired) {
438 if (i_man->resources[request->type]->parts) {
439 if (request->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
441 request->priority_error = TRUE;
442 resource_conflict = TRUE;
443 MM_RM_DEBUG("Resource conflict. Full volume is "
444 "requested, but only part is available");
447 for (j = 0; j < i_man->resources[request->type]->parts->len; j++)
448 remaining_volume -= g_array_index(
449 i_man->resources[request->type]->parts,
450 mm_resource_manager_res_volume, j);
452 if (remaining_volume < request->volume) {
453 request->priority_error = TRUE;
454 resource_conflict = TRUE;
455 MM_RM_DEBUG("Resource conflict. %d of %s are "
456 "available, but %d required", remaining_volume,
457 type_s, request->volume);
463 request->priority_error = TRUE;
464 resource_conflict = TRUE;
465 MM_RM_DEBUG("Resource conflict. %s is already "
466 "acquired fully", type_s);
473 if (resource_conflict) {
474 MM_RM_DEBUG("There is resource conflict");
475 return MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY;
477 MM_RM_DEBUG("Increase requests are OK");
478 return MM_RESOURCE_MANAGER_ERROR_NONE;
482 static void __sync_increase_acquire_requests(
483 mm_resource_manager_dmn_res_request_s *increases,
484 mm_resource_manager_dmn_res_request_s *acquires)
486 mm_resource_manager_dmn_res_request_s *increase_iter;
487 mm_resource_manager_dmn_res_request_s *acquire_iter;
489 for (increase_iter = increases;
490 increase_iter->type != MM_RESOURCE_MANAGER_NO_RES;
492 for (acquire_iter = acquires;
493 acquire_iter->type != MM_RESOURCE_MANAGER_NO_RES;
495 if (acquire_iter->type == increase_iter->type)
496 acquire_iter->priority_error = increase_iter->priority_error;
499 static inline void __add_cb_request(GArray *cb_requests,
500 mm_resource_manager_dmn_p man,
501 mm_resource_manager_res_type_e type,
502 mm_resource_manager_res_volume volume)
504 mm_resource_manager_dmn_release_cb_request_s *cb_request;
506 g_array_set_size(cb_requests, cb_requests->len + 1);
507 cb_request = &g_array_index(cb_requests,
508 mm_resource_manager_dmn_release_cb_request_s, cb_requests->len - 1);
510 cb_request->manager = man;
511 cb_request->type = type;
512 cb_request->volume = volume;
515 static GArray* __handle_acquire_requests(mm_resource_manager_dmn_p manager,
516 mm_resource_manager_dmn_res_request_s *requests)
518 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
519 mm_resource_manager_dmn_res_request_p request;
520 mm_resource_manager_res_volume acquired_volume;
521 mm_resource_manager_dmn_p i_man;
523 GArray *cb_requests = NULL;
525 gboolean is_released_fully;
526 gboolean enough_volume;
529 if (requests == NULL)
532 cb_requests = g_array_sized_new(FALSE, FALSE,
533 sizeof(mm_resource_manager_dmn_release_cb_request_s),
534 MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE);
536 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
539 const char *res_name = _mm_resource_manager_get_res_str(request->type);
541 if (request->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
542 MM_RM_DEBUG("Full volume of %s is requested", res_name);
544 for (i = 0; i < managers->len; i++) {
545 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
547 if (!i_man->resources[request->type]->is_acquired ||
548 conf->priority[i_man->app_class] >
549 conf->priority[manager->app_class])
552 parts = i_man->resources[request->type]->parts;
554 for (j = 0; j < parts->len; j++) {
555 __add_cb_request(cb_requests, i_man, request->type,
557 mm_resource_manager_res_volume, j));
559 mm_resource_manager_backend_release(request->type);
562 g_array_free(parts, TRUE);
563 i_man->resources[request->type]->parts = NULL;
564 i_man->resources[request->type]->is_acquired = FALSE;
566 MM_RM_DEBUG("All parts of %s are released in RM %"PRIu64,
567 res_name, _mm_rm_hash64(i_man->id));
569 __add_cb_request(cb_requests, i_man, request->type,
570 MM_RESOURCE_MANAGER_RES_VOLUME_FULL);
572 mm_resource_manager_backend_release(request->type);
574 i_man->resources[request->type]->is_acquired = FALSE;
576 MM_RM_DEBUG("Full resource %s is released in RM %"PRIu64,
577 res_name, _mm_rm_hash64(i_man->id));
582 MM_RM_DEBUG("%d units of %s are requested", request->volume,
586 is_released_fully = FALSE;
587 for (i = 0; i < managers->len; i++) {
588 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
590 if (!i_man->resources[request->type]->is_acquired ||
591 conf->priority[i_man->app_class] >
592 conf->priority[manager->app_class])
595 parts = i_man->resources[request->type]->parts;
597 for (j = 0; j < parts->len; j++) {
598 acquired_volume += g_array_index(parts,
599 mm_resource_manager_res_volume, j);
602 __add_cb_request(cb_requests, i_man, request->type,
603 MM_RESOURCE_MANAGER_RES_VOLUME_FULL);
605 mm_resource_manager_backend_release(request->type);
607 i_man->resources[request->type]->is_acquired = FALSE;
608 is_released_fully = TRUE;
610 MM_RM_DEBUG("Full resource %s is released in RM %"PRIu64,
611 res_name, _mm_rm_hash64(i_man->id));
616 if (!is_released_fully) {
618 enough_volume = request->volume + acquired_volume <=
619 conf->max_volume[request->type];
620 i < managers->len && !enough_volume; i++) {
622 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
623 if (manager == i_man ||
624 !i_man->resources[request->type]->is_acquired ||
625 conf->priority[i_man->app_class] >
626 conf->priority[manager->app_class])
629 parts = i_man->resources[request->type]->parts;
630 while (parts->len > 0 && !enough_volume) {
632 __add_cb_request(cb_requests, i_man, request->type,
634 mm_resource_manager_res_volume, 0));
636 acquired_volume -= g_array_index(parts,
637 mm_resource_manager_res_volume, 0);
638 enough_volume = request->volume + acquired_volume <=
639 conf->max_volume[request->type];
641 MM_RM_DEBUG("%d units of %s are released in RM %"PRIu64,
643 mm_resource_manager_res_volume, 0), res_name,
644 _mm_rm_hash64(i_man->id));
646 g_array_remove_index_fast(parts, 0);
648 mm_resource_manager_backend_release(request->type);
652 MM_RM_DEBUG("Part array of %s is empty and will be "
653 "freed in RM %"PRIu64, res_name,
654 _mm_rm_hash64(i_man->id));
655 g_array_free(parts, TRUE);
656 i_man->resources[request->type]->parts = NULL;
657 i_man->resources[request->type]->is_acquired = FALSE;
662 parts = manager->resources[request->type]->parts;
664 parts = g_array_sized_new(FALSE, FALSE,
665 sizeof(mm_resource_manager_res_volume),
666 MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE);
667 manager->resources[request->type]->parts = parts;
669 g_array_append_val(parts, request->volume);
672 manager->resources[request->type]->is_acquired = TRUE;
673 mm_resource_manager_backend_acquire(request->type);
679 static void __handle_release_callbacks(GArray *requests)
682 mm_resource_manager_id id;
683 mm_resource_manager_dmn_release_cb_request_s *request;
685 for (i = 0; i < requests->len; i++) {
686 request = &g_array_index(requests,
687 mm_resource_manager_dmn_release_cb_request_s, i);
688 id = request->manager->id;
690 MM_RM_DEBUG("Sending release callback to RM #%"PRIu64" for %s of volume %d",
691 id, _mm_resource_manager_get_res_str(request->type),
693 _mmrm_dmn_dbus_release_callback(id, request->type, request->volume);
694 if (__wait_for_release_cb_sync(request->manager->id))
695 MM_RM_DEBUG("Release callback sync success");
697 MM_RM_ERROR("Wait for release callback sync failed");
701 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
702 mm_resource_manager_dmn_res_request_s *requests)
704 mm_resource_manager_dmn_res_request_p request;
708 if (requests == NULL)
711 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
715 if (request->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
716 manager->resources[request->type]->is_acquired = FALSE;
718 parts = manager->resources[request->type]->parts;
719 for (i = 0; i < parts->len &&
720 ((mm_resource_manager_res_volume*)parts->data)[i] !=
721 request->volume; i++);
723 g_array_remove_index_fast(parts, i);
725 if (parts->len == 0) {
726 g_array_free(parts, TRUE);
727 manager->resources[request->type]->parts = NULL;
728 manager->resources[request->type]->is_acquired = FALSE;
732 mm_resource_manager_backend_release(request->type);
736 static void __release_all_resources(mm_resource_manager_dmn_s *manager)
740 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
741 if (manager->resources[i] && manager->resources[i]->is_acquired) {
742 if (manager->resources[i]->parts) {
743 for (j = 0; j < manager->resources[i]->parts->len; j++)
744 mm_resource_manager_backend_release(i);
746 mm_resource_manager_backend_release(i);
748 manager->resources[i]->is_acquired = FALSE;
753 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id)
756 struct pollfd sync = {0};
757 mm_resource_manager_id recv_id;
760 sync.fd = open(RELEASE_CB_SYNC_PATH, O_RDONLY | O_NONBLOCK);
761 MM_RM_RETVM_IF(sync.fd == -1, FALSE, "Sync FIFO cannot be opened");
763 sync.events = POLLIN;
764 switch (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000)) {
766 MM_RM_ERROR("Polling is failed");
770 MM_RM_DEBUG("Wait timeout is elapsed");
774 read_size = read(sync.fd, &recv_id, sizeof(recv_id));
775 if (read_size == sizeof(recv_id)) {
778 MM_RM_ERROR("Sync is received from wrong client #%"PRIu64, recv_id);
780 * Wait POLLHUP to avoid situation when client sent last sync
781 * through the pipe, but not already closed the pipe handle and
782 * the daemon is already opened the pipe again and waiting for
786 if (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000) == 0 || (sync.revents & (POLLHUP | POLLERR)) == 0)
787 MM_RM_ERROR("The client didn't close the FIFO");
789 MM_RM_ERROR("Read is failed (revents=%hd,read_size=%zd)", sync.revents, read_size);