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.
24 #include "daemon/mm_resource_manager_daemon_priv.h"
25 #include "daemon/mm_resource_manager_daemon_conf.h"
26 #include "daemon/mm_resource_manager_daemon_dbus.h"
27 #include "daemon/backend/mm_resource_manager_backend.h"
28 #include "common/mm_resource_manager_utils.h"
32 #define MM_RESOURCE_MANAGER_RESERVED_RM_ARRAY_SIZE 64 /* preallocated size */
33 #define MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE 4 /* preallocated size */
34 #define MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE 32 /* preallocated size */
35 #define MM_RESOURCE_MANGER_NOT_FOUND -1
36 #define RELEASE_CB_SYNC_TIMEOUT 5 /* seconds */
43 /* NULL means, the resource is acquired fully or is not acquired at all */
46 } mm_resource_manager_dmn_res_s;
47 typedef mm_resource_manager_dmn_res_s *mm_resource_manager_dmn_res_p;
50 mm_resource_manager_id id;
51 mm_resource_manager_app_class_e app_class;
53 /* if an element is NULL, there is no such a resource for the current platform. */
54 mm_resource_manager_dmn_res_p resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
56 } mm_resource_manager_dmn_s;
57 typedef mm_resource_manager_dmn_s *mm_resource_manager_dmn_p;
60 mm_resource_manager_dmn_p manager;
61 mm_resource_manager_res_type_e type;
62 mm_resource_manager_res_volume volume;
63 } mm_resource_manager_dmn_release_cb_request_s;
67 static GPtrArray *managers = NULL;
71 static void __destroy_resource(mm_resource_manager_dmn_res_p res);
72 static void __destroy_manager(void *m);
73 static int __search_manager_index(mm_resource_manager_id id);
74 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id);
75 static mm_resource_manager_error_e __check_release_requests(
76 mm_resource_manager_dmn_p manager,
77 mm_resource_manager_dmn_res_request_s *requests);
78 static mm_resource_manager_dmn_res_request_s* __create_increase_requests(
79 mm_resource_manager_dmn_res_request_s *releases,
80 mm_resource_manager_dmn_res_request_s *acquires);
81 static mm_resource_manager_error_e __check_increase_requests(
82 mm_resource_manager_dmn_p manager,
83 mm_resource_manager_dmn_res_request_s *requests);
84 static void __sync_increase_acquire_requests(
85 mm_resource_manager_dmn_res_request_s *increases,
86 mm_resource_manager_dmn_res_request_s *acquires);
87 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
88 mm_resource_manager_dmn_res_request_s *requests);
89 static GArray* __handle_acquire_requests(mm_resource_manager_dmn_p manager,
90 mm_resource_manager_dmn_res_request_s *requests);
91 static void __handle_release_callbacks(GArray *requests);
92 static inline void __add_cb_request(GArray *cb_requests,
93 mm_resource_manager_dmn_p man,
94 mm_resource_manager_res_type_e type,
95 mm_resource_manager_res_volume volume);
96 static void __release_all_resources(mm_resource_manager_dmn_s *manager);
97 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id);
102 gboolean _mmrm_dmn_init(void)
104 unlink(RELEASE_CB_SYNC_PATH);
105 MM_RM_RETVM_IF(mkfifo(RELEASE_CB_SYNC_PATH,
106 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH) == -1, FALSE,
107 "Release callback sync cannot be created");
109 MM_RM_RETVM_IF(mm_resource_manager_backend_init() !=
110 MM_RESOURCE_MANAGER_ERROR_NONE, FALSE,
111 "Back-end cannot be initialized");
113 if (_mmrm_dmn_dbus_init() != MM_RESOURCE_MANAGER_ERROR_NONE) {
114 mm_resource_manager_backend_deinit();
115 MM_RM_ERROR("D-bus server cannot be created");
119 managers = g_ptr_array_new_full(MM_RESOURCE_MANAGER_RESERVED_RM_ARRAY_SIZE,
121 MM_RM_RETVM_IF(managers == NULL, FALSE, "Daemon cannot be initialized");
126 gboolean _mmrm_dmn_deinit()
130 if (mm_resource_manager_backend_deinit() != MM_RESOURCE_MANAGER_ERROR_NONE)
131 MM_RM_ERROR("Error during back-end deinitialization");
133 if (_mmrm_dmn_dbus_deinit() != MM_RESOURCE_MANAGER_ERROR_NONE)
134 MM_RM_ERROR("Error during d-bus server shutdown");
137 for (i = 0; i < managers->len; i++)
138 __release_all_resources((mm_resource_manager_dmn_s*)managers->pdata[i]);
140 mm_resource_manager_backend_commit_all();
141 g_ptr_array_free(managers, TRUE);
143 MM_RM_ERROR("Trying to deinit uninitialized daemon");
146 if (unlink(RELEASE_CB_SYNC_PATH) == -1)
147 MM_RM_ERROR("Release callback sync cannot be removed");
152 mm_resource_manager_error_e _mmrm_dmn_create(
153 mm_resource_manager_app_class_e app_class, mm_resource_manager_id *id)
155 mm_resource_manager_dmn_p man;
156 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
159 MM_RM_RETVM_IF(app_class < 0 ||
160 app_class >= MM_RESOURCE_MANAGER_APP_CLASS_MAX,
161 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Wrong app class");
163 MM_RM_RETVM_IF(conf->priority[app_class] ==
164 MM_RESOURCE_MANAGER_NO_APP_CLASS,
165 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
166 "App class is not supported for the platform");
168 man = g_new0(mm_resource_manager_dmn_s, 1);
169 MM_RM_RAND64(man->id);
170 man->app_class = app_class;
171 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
172 man->resources[i] = conf->max_volume[i] == MM_RESOURCE_MANAGER_NO_RES ?
173 NULL : g_malloc0(sizeof(mm_resource_manager_dmn_s));
176 g_ptr_array_add(managers, man);
180 return MM_RESOURCE_MANAGER_ERROR_NONE;
183 mm_resource_manager_error_e _mmrm_dmn_destroy(mm_resource_manager_id id)
185 int i_man = __search_manager_index(id);
187 MM_RM_RETVM_IF(i_man == MM_RESOURCE_MANGER_NOT_FOUND,
188 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
189 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
191 __release_all_resources((mm_resource_manager_dmn_s*)managers->pdata[i_man]);
192 mm_resource_manager_backend_commit_all();
194 g_ptr_array_remove_index_fast(managers, i_man);
196 return MM_RESOURCE_MANAGER_ERROR_NONE;
199 mm_resource_manager_error_e _mmrm_dmn_commit(mm_resource_manager_id id,
200 mm_resource_manager_dmn_res_request_s *releases,
201 mm_resource_manager_dmn_res_request_s *acquires)
203 mm_resource_manager_dmn_p manager = __search_manager(id);
204 mm_resource_manager_error_e ret = MM_RESOURCE_MANAGER_ERROR_NONE;
205 mm_resource_manager_dmn_res_request_s *increases = NULL;
208 MM_RM_RETVM_IF(manager == NULL,
209 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
210 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
212 (releases == NULL || releases[0].type == MM_RESOURCE_MANAGER_NO_RES) &&
213 (acquires == NULL || acquires[0].type == MM_RESOURCE_MANAGER_NO_RES),
214 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
215 "Commit request is empty");
217 ret = __check_release_requests(manager, releases);
218 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
220 increases = __create_increase_requests(releases, acquires);
221 if (increases == NULL)
222 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
224 ret = __check_increase_requests(manager, increases);
225 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
226 __sync_increase_acquire_requests(increases, acquires);
232 __handle_release_requests(manager, releases);
233 cb_requests = __handle_acquire_requests(manager, acquires);
234 __handle_release_callbacks(cb_requests);
235 if (!mm_resource_manager_backend_commit_all()) {
238 * function can fail only if resource management back-end is not solely
239 * used by mm-resource-manager or if the back-end cannot acquire/release
240 * a resource because of some internal error.
242 * Initiate status disconnected and reload the back-end and the RM
245 kill(getpid(), SIGHUP);
246 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
248 g_array_free(cb_requests, TRUE);
253 void _mmrm_dmn_status_callback(mm_resource_manager_status_e status)
255 _mmrm_dmn_dbus_status_callback(status);
260 static void __destroy_resource(mm_resource_manager_dmn_res_p res)
266 g_array_free(res->parts, TRUE);
271 static void __destroy_manager(void *m)
273 mm_resource_manager_dmn_p man = (mm_resource_manager_dmn_p) m;
276 MM_RM_RETM_IF(man == NULL, "NULL pointer");
278 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
279 __destroy_resource(man->resources[i]);
284 static int __search_manager_index(mm_resource_manager_id id)
288 for (i = managers->len - 1; i >= 0; i--)
289 if (((mm_resource_manager_dmn_p)managers->pdata[i])->id == id)
292 return MM_RESOURCE_MANGER_NOT_FOUND;
295 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id)
297 int i = __search_manager_index(id);
298 return i == MM_RESOURCE_MANGER_NOT_FOUND ? NULL : managers->pdata[i];
301 static mm_resource_manager_error_e __check_release_requests(
302 mm_resource_manager_dmn_p manager,
303 mm_resource_manager_dmn_res_request_s *requests)
305 mm_resource_manager_dmn_res_request_p request;
308 if (requests == NULL)
309 return MM_RESOURCE_MANAGER_ERROR_NONE;
311 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
314 const char *type_s = _mm_resource_manager_get_res_str(request->type);
316 MM_RM_RETVM_IF(manager->resources[request->type] == NULL,
317 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
318 "There is no resource %s for the platform", type_s);
320 if (manager->resources[request->type]->is_acquired) {
321 if (manager->resources[request->type]->parts == NULL) {
322 if (request->volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
323 MM_RM_ERROR("Resource %s is acquired fully,"
324 "but a resource part is tried to be released",
326 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
329 for (i = 0; i < manager->resources[request->type]->parts->len &&
330 ((mm_resource_manager_res_volume*)
331 manager->resources[request->type]->parts->data)[i] !=
332 request->volume; i++);
333 if (i == manager->resources[request->type]->parts->len) {
334 MM_RM_ERROR("Part of %s of volume %d is not acquired",
335 type_s, request->volume);
336 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
340 MM_RM_ERROR("Resource %s is not acquired", type_s);
341 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
345 MM_RM_DEBUG("Release requests are OK");
347 return MM_RESOURCE_MANAGER_ERROR_NONE;
350 static mm_resource_manager_dmn_res_request_s* __create_increase_requests(
351 mm_resource_manager_dmn_res_request_s *releases,
352 mm_resource_manager_dmn_res_request_s *acquires)
356 mm_resource_manager_dmn_res_request_s* result = NULL;
357 mm_resource_manager_dmn_res_request_s* result_iter = NULL;
358 mm_resource_manager_res_volume resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX] = {0};
359 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
361 for (; acquires->type != MM_RESOURCE_MANAGER_NO_RES; acquires++) {
363 if ((resources[acquires->type] > 0 || resources[acquires->type] ==
364 MM_RESOURCE_MANAGER_RES_VOLUME_FULL) && acquires->volume ==
365 MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
366 MM_RM_ERROR("The client tries to acquire %s by part and fully at once",
367 _mm_resource_manager_get_res_str(acquires->type));
371 if (acquires->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
372 resources[acquires->type] = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
374 resources[acquires->type] += acquires->volume;
376 if (resources[acquires->type] > conf->max_volume[acquires->type]) {
378 "The client tries to acquire %d units over max volume of %s",
379 resources[acquires->type] - conf->max_volume[acquires->type],
380 _mm_resource_manager_get_res_str(acquires->type));
385 for (; releases->type != MM_RESOURCE_MANAGER_NO_RES; releases++)
386 if (resources[releases->type] != MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
387 resources[releases->type] -= releases->volume;
389 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
390 if (resources[i] > 0 ||
391 resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
394 result_iter = result = g_new0(mm_resource_manager_dmn_res_request_s,
396 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
397 if (resources[i] > 0 ||
398 resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
399 result_iter->type = i;
400 result_iter->volume = resources[i];
404 result_iter->type = MM_RESOURCE_MANAGER_NO_RES;
409 static mm_resource_manager_error_e __check_increase_requests(
410 mm_resource_manager_dmn_p manager,
411 mm_resource_manager_dmn_res_request_s *requests)
413 mm_resource_manager_dmn_res_request_p request;
414 mm_resource_manager_res_volume remaining_volume;
415 mm_resource_manager_dmn_p i_man;
416 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
417 gboolean resource_conflict = FALSE;
420 if (requests == NULL)
421 return MM_RESOURCE_MANAGER_ERROR_NONE;
423 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
426 const char *type_s = _mm_resource_manager_get_res_str(request->type);
428 MM_RM_RETVM_IF(manager->resources[request->type] == NULL,
429 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
430 "There is no resource %s for the platform", type_s);
432 remaining_volume = conf->max_volume[request->type];
433 for (i = 0; i < managers->len; i++) {
434 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
435 if (i_man != manager && conf->priority[i_man->app_class] >
436 conf->priority[manager->app_class] &&
437 i_man->resources[request->type]->is_acquired) {
439 if (i_man->resources[request->type]->parts) {
440 if (request->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
442 request->priority_error = TRUE;
443 resource_conflict = TRUE;
444 MM_RM_DEBUG("Resource conflict. Full volume is "
445 "requested, but only part is available");
448 for (j = 0; j < i_man->resources[request->type]->parts->len; j++)
449 remaining_volume -= g_array_index(
450 i_man->resources[request->type]->parts,
451 mm_resource_manager_res_volume, j);
453 if (remaining_volume < request->volume) {
454 request->priority_error = TRUE;
455 resource_conflict = TRUE;
456 MM_RM_DEBUG("Resource conflict. %d of %s are "
457 "available, but %d required", remaining_volume,
458 type_s, request->volume);
464 request->priority_error = TRUE;
465 resource_conflict = TRUE;
466 MM_RM_DEBUG("Resource conflict. %s is already "
467 "acquired fully", type_s);
474 if (resource_conflict) {
475 MM_RM_DEBUG("There is resource conflict");
476 return MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY;
478 MM_RM_DEBUG("Increase requests are OK");
479 return MM_RESOURCE_MANAGER_ERROR_NONE;
483 static void __sync_increase_acquire_requests(
484 mm_resource_manager_dmn_res_request_s *increases,
485 mm_resource_manager_dmn_res_request_s *acquires)
487 mm_resource_manager_dmn_res_request_s *increase_iter;
488 mm_resource_manager_dmn_res_request_s *acquire_iter;
490 for (increase_iter = increases;
491 increase_iter->type != MM_RESOURCE_MANAGER_NO_RES;
493 for (acquire_iter = acquires;
494 acquire_iter->type != MM_RESOURCE_MANAGER_NO_RES;
496 if (acquire_iter->type == increase_iter->type)
497 acquire_iter->priority_error = increase_iter->priority_error;
500 static inline void __add_cb_request(GArray *cb_requests,
501 mm_resource_manager_dmn_p man,
502 mm_resource_manager_res_type_e type,
503 mm_resource_manager_res_volume volume)
505 mm_resource_manager_dmn_release_cb_request_s *cb_request;
507 g_array_set_size(cb_requests, cb_requests->len + 1);
508 cb_request = &g_array_index(cb_requests,
509 mm_resource_manager_dmn_release_cb_request_s, cb_requests->len - 1);
511 cb_request->manager = man;
512 cb_request->type = type;
513 cb_request->volume = volume;
516 static GArray* __handle_acquire_requests(mm_resource_manager_dmn_p manager,
517 mm_resource_manager_dmn_res_request_s *requests)
519 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
520 mm_resource_manager_dmn_res_request_p request;
521 mm_resource_manager_res_volume acquired_volume;
522 mm_resource_manager_dmn_p i_man;
524 GArray *cb_requests = NULL;
526 gboolean is_released_fully;
527 gboolean enough_volume;
530 if (requests == NULL)
533 cb_requests = g_array_sized_new(FALSE, FALSE,
534 sizeof(mm_resource_manager_dmn_release_cb_request_s),
535 MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE);
537 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
540 const char *res_name = _mm_resource_manager_get_res_str(request->type);
542 if (request->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
543 MM_RM_DEBUG("Full volume of %s is requested", res_name);
545 for (i = 0; i < managers->len; i++) {
546 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
548 if (!i_man->resources[request->type]->is_acquired ||
549 conf->priority[i_man->app_class] >
550 conf->priority[manager->app_class])
553 parts = i_man->resources[request->type]->parts;
555 for (j = 0; j < parts->len; j++) {
556 __add_cb_request(cb_requests, i_man, request->type,
558 mm_resource_manager_res_volume, j));
560 mm_resource_manager_backend_release(request->type);
563 g_array_free(parts, TRUE);
564 i_man->resources[request->type]->parts = NULL;
565 i_man->resources[request->type]->is_acquired = FALSE;
567 MM_RM_DEBUG("All parts of %s are released in RM %"PRIu64,
568 res_name, _mm_rm_hash64(i_man->id));
570 __add_cb_request(cb_requests, i_man, request->type,
571 MM_RESOURCE_MANAGER_RES_VOLUME_FULL);
573 mm_resource_manager_backend_release(request->type);
575 i_man->resources[request->type]->is_acquired = FALSE;
577 MM_RM_DEBUG("Full resource %s is released in RM %"PRIu64,
578 res_name, _mm_rm_hash64(i_man->id));
583 MM_RM_DEBUG("%d units of %s are requested", request->volume,
587 is_released_fully = FALSE;
588 for (i = 0; i < managers->len; i++) {
589 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
591 if (!i_man->resources[request->type]->is_acquired ||
592 conf->priority[i_man->app_class] >
593 conf->priority[manager->app_class])
596 parts = i_man->resources[request->type]->parts;
598 for (j = 0; j < parts->len; j++) {
599 acquired_volume += g_array_index(parts,
600 mm_resource_manager_res_volume, j);
603 __add_cb_request(cb_requests, i_man, request->type,
604 MM_RESOURCE_MANAGER_RES_VOLUME_FULL);
606 mm_resource_manager_backend_release(request->type);
608 i_man->resources[request->type]->is_acquired = FALSE;
609 is_released_fully = TRUE;
611 MM_RM_DEBUG("Full resource %s is released in RM %"PRIu64,
612 res_name, _mm_rm_hash64(i_man->id));
617 if (!is_released_fully) {
619 enough_volume = request->volume + acquired_volume <=
620 conf->max_volume[request->type];
621 i < managers->len && !enough_volume; i++) {
623 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
624 if (manager == i_man ||
625 !i_man->resources[request->type]->is_acquired ||
626 conf->priority[i_man->app_class] >
627 conf->priority[manager->app_class])
630 parts = i_man->resources[request->type]->parts;
631 while (parts->len > 0 && !enough_volume) {
633 __add_cb_request(cb_requests, i_man, request->type,
635 mm_resource_manager_res_volume, 0));
637 acquired_volume -= g_array_index(parts,
638 mm_resource_manager_res_volume, 0);
639 enough_volume = request->volume + acquired_volume <=
640 conf->max_volume[request->type];
642 MM_RM_DEBUG("%d units of %s are released in RM %"PRIu64,
644 mm_resource_manager_res_volume, 0), res_name,
645 _mm_rm_hash64(i_man->id));
647 g_array_remove_index_fast(parts, 0);
649 mm_resource_manager_backend_release(request->type);
653 MM_RM_DEBUG("Part array of %s is empty and will be "
654 "freed in RM %"PRIu64, res_name,
655 _mm_rm_hash64(i_man->id));
656 g_array_free(parts, TRUE);
657 i_man->resources[request->type]->parts = NULL;
658 i_man->resources[request->type]->is_acquired = FALSE;
663 parts = manager->resources[request->type]->parts;
665 parts = g_array_sized_new(FALSE, FALSE,
666 sizeof(mm_resource_manager_res_volume),
667 MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE);
668 manager->resources[request->type]->parts = parts;
670 g_array_append_val(parts, request->volume);
673 manager->resources[request->type]->is_acquired = TRUE;
674 mm_resource_manager_backend_acquire(request->type);
680 static void __handle_release_callbacks(GArray *requests)
683 mm_resource_manager_id id;
684 mm_resource_manager_dmn_release_cb_request_s *request;
686 for (i = 0; i < requests->len; i++) {
687 request = &g_array_index(requests,
688 mm_resource_manager_dmn_release_cb_request_s, i);
689 id = request->manager->id;
691 MM_RM_DEBUG("Sending release callback to RM #%"PRIu64" for %s of volume %d",
692 id, _mm_resource_manager_get_res_str(request->type),
694 _mmrm_dmn_dbus_release_callback(id, request->type, request->volume);
695 if (__wait_for_release_cb_sync(request->manager->id))
696 MM_RM_DEBUG("Release callback sync success");
698 MM_RM_ERROR("Wait for release callback sync failed");
702 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
703 mm_resource_manager_dmn_res_request_s *requests)
705 mm_resource_manager_dmn_res_request_p request;
709 if (requests == NULL)
712 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
716 if (request->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
717 manager->resources[request->type]->is_acquired = FALSE;
719 parts = manager->resources[request->type]->parts;
720 for (i = 0; i < parts->len &&
721 ((mm_resource_manager_res_volume*)parts->data)[i] !=
722 request->volume; i++);
724 g_array_remove_index_fast(parts, i);
726 if (parts->len == 0) {
727 g_array_free(parts, TRUE);
728 manager->resources[request->type]->parts = NULL;
729 manager->resources[request->type]->is_acquired = FALSE;
733 mm_resource_manager_backend_release(request->type);
737 static void __release_all_resources(mm_resource_manager_dmn_s *manager)
741 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
742 if (manager->resources[i] && manager->resources[i]->is_acquired) {
743 if (manager->resources[i]->parts) {
744 for (j = 0; j < manager->resources[i]->parts->len; j++)
745 mm_resource_manager_backend_release(i);
747 mm_resource_manager_backend_release(i);
749 manager->resources[i]->is_acquired = FALSE;
754 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id)
757 struct pollfd sync = {0};
758 mm_resource_manager_id recv_id;
761 sync.fd = open(RELEASE_CB_SYNC_PATH, O_RDONLY | O_NONBLOCK);
762 MM_RM_RETVM_IF(sync.fd == -1, FALSE, "Sync FIFO cannot be opened");
764 sync.events = POLLIN;
765 switch (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000)) {
767 MM_RM_ERROR("Polling is failed");
771 MM_RM_DEBUG("Wait timeout is elapsed");
775 read_size = read(sync.fd, &recv_id, sizeof(recv_id));
776 if (read_size == sizeof(recv_id)) {
779 MM_RM_ERROR("Sync is received from wrong client #%"PRIu64, recv_id);
781 * Wait POLLHUP to avoid situation when client sent last sync
782 * through the pipe, but not already closed the pipe handle and
783 * the daemon is already opened the pipe again and waiting for
787 if (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000) == 0 || (sync.revents & (POLLHUP | POLLERR)) == 0)
788 MM_RM_ERROR("The client didn't close the FIFO");
790 MM_RM_ERROR("Read is failed (revents=%hd,read_size=%zd)", sync.revents, read_size);