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;
51 mm_resource_manager_res_type_e type;
54 /* if an element is NULL, there is no such a resource for the current platform. */
55 mm_resource_manager_dmn_res_p resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
57 } mm_resource_manager_dmn_s;
58 typedef mm_resource_manager_dmn_s *mm_resource_manager_dmn_p;
61 mm_resource_manager_dmn_p manager;
62 mm_resource_manager_res_type_e type;
63 mm_resource_manager_res_volume volume;
64 } mm_resource_manager_dmn_release_cb_request_s;
68 static GPtrArray *managers;
69 static int res_count[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
72 static void __destroy_resource(mm_resource_manager_dmn_res_p res);
73 static void __destroy_manager(void *m);
74 static int __search_manager_index(mm_resource_manager_id id);
75 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id);
76 static mm_resource_manager_error_e __check_release_requests(
77 mm_resource_manager_dmn_p manager,
78 mm_resource_manager_dmn_res_request_s *requests);
79 static mm_resource_manager_dmn_res_request_s *__create_increase_requests(
80 mm_resource_manager_dmn_res_request_s *releases,
81 mm_resource_manager_dmn_res_request_s *acquires);
82 static mm_resource_manager_error_e __check_increase_requests(
83 mm_resource_manager_dmn_p manager,
84 mm_resource_manager_dmn_res_request_s *requests);
85 static void __sync_increase_acquire_requests(
86 mm_resource_manager_dmn_res_request_s *increases,
87 mm_resource_manager_dmn_res_request_s *acquires);
88 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
89 mm_resource_manager_dmn_res_request_s *requests);
90 static GArray* __handle_acquire_requests(mm_resource_manager_dmn_p manager,
91 mm_resource_manager_dmn_res_request_s *requests);
92 static void __handle_release_callbacks(GArray *requests);
93 static inline void __add_cb_request(GArray *cb_requests, mm_resource_manager_dmn_p man,
94 mm_resource_manager_res_type_e type, 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_p)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);
177 MM_RM_INFO("managers length %d", managers->len);
181 return MM_RESOURCE_MANAGER_ERROR_NONE;
184 mm_resource_manager_error_e _mmrm_dmn_destroy(mm_resource_manager_id id)
186 int idx = __search_manager_index(id);
187 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
188 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
189 mm_resource_manager_dmn_p i_man = __search_manager(id);
191 MM_RM_RETVM_IF(idx == MM_RESOURCE_MANGER_NOT_FOUND, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
192 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
193 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
195 i_man = (mm_resource_manager_dmn_p)managers->pdata[idx];
197 __release_all_resources((mm_resource_manager_dmn_s *)managers->pdata[idx]);
198 mm_resource_manager_backend_commit_all();
200 g_ptr_array_remove_index_fast(managers, idx);
204 MM_RM_INFO("managers length #%d type %d available volume %d", managers->len, type, conf->max_volume[type]);
206 return MM_RESOURCE_MANAGER_ERROR_NONE;
209 mm_resource_manager_error_e _mmrm_dmn_commit(mm_resource_manager_id id,
210 mm_resource_manager_dmn_res_request_s *releases,
211 mm_resource_manager_dmn_res_request_s *acquires)
213 mm_resource_manager_dmn_p manager = __search_manager(id);
214 mm_resource_manager_error_e ret = MM_RESOURCE_MANAGER_ERROR_NONE;
215 mm_resource_manager_dmn_res_request_s *increases = NULL;
218 MM_RM_RETVM_IF(manager == NULL,
219 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
220 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
222 (releases == NULL || releases[0].type == MM_RESOURCE_MANAGER_NO_RES)
223 && (acquires == NULL || acquires[0].type == MM_RESOURCE_MANAGER_NO_RES),
224 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
225 "Commit request is empty");
227 ret = __check_release_requests(manager, releases);
228 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
230 increases = __create_increase_requests(releases, acquires);
231 if (increases == NULL)
232 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
234 ret = __check_increase_requests(manager, increases);
235 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
236 __sync_increase_acquire_requests(increases, acquires);
242 __handle_release_requests(manager, releases);
243 cb_requests = __handle_acquire_requests(manager, acquires);
244 MM_RM_RETVM_IF(cb_requests == NULL, MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH,
245 "not enough free resource volume");
246 __handle_release_callbacks(cb_requests);
247 if (!mm_resource_manager_backend_commit_all()) {
250 * function can fail only if resource management back-end is not solely
251 * used by mm-resource-manager or if the back-end cannot acquire/release
252 * a resource because of some internal error.
254 * Initiate status disconnected and reload the back-end and the RM
257 kill(getpid(), SIGHUP);
258 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
260 g_array_free(cb_requests, TRUE);
265 void _mmrm_dmn_status_callback(mm_resource_manager_status_e status)
267 _mmrm_dmn_dbus_status_callback(status);
270 static void __destroy_resource(mm_resource_manager_dmn_res_p res)
276 g_array_free(res->parts, TRUE);
281 static void __destroy_manager(void *m)
283 mm_resource_manager_dmn_p man = (mm_resource_manager_dmn_p) m;
286 MM_RM_RETM_IF(man == NULL, "NULL pointer");
288 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
289 __destroy_resource(man->resources[i]);
294 static int __search_manager_index(mm_resource_manager_id id)
298 for (i = managers->len - 1; i >= 0; i--) {
299 if (((mm_resource_manager_dmn_p)managers->pdata[i])->id == id)
303 return MM_RESOURCE_MANGER_NOT_FOUND;
306 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id)
308 int i = __search_manager_index(id);
309 return i == MM_RESOURCE_MANGER_NOT_FOUND ? NULL : managers->pdata[i];
312 static mm_resource_manager_error_e __check_release_requests(mm_resource_manager_dmn_p manager,
313 mm_resource_manager_dmn_res_request_s *requests)
316 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
317 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
319 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
320 MM_RM_RETVM_IF(requests == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "requests is null");
322 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
324 type = requests->type;
325 const char *type_s = _mm_resource_manager_get_res_str(type);
327 MM_RM_RETVM_IF(manager->resources[type] == NULL,
328 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED, "There is no resource %s for the platform", type_s);
330 if (manager->resources[type]->is_acquired) {
331 if (manager->resources[type]->parts == NULL) {
332 if (requests->volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
333 MM_RM_ERROR("Resource %s is acquired fully, but a resource part is tried to be released", type_s);
334 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
337 for (i = 0; i < manager->resources[type]->parts->len
338 && ((mm_resource_manager_res_volume*)manager->resources[type]->parts->data)[i]
339 != requests->volume; i++);
340 if (i == manager->resources[type]->parts->len) {
341 MM_RM_ERROR("Part of %s of volume %d is not acquired", type_s, requests->volume);
342 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
346 MM_RM_ERROR("Resource %s is not acquired", type_s);
347 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
349 MM_RM_DEBUG("Release requests are OK type %d available volume %d", type, conf->max_volume[type]);
352 return MM_RESOURCE_MANAGER_ERROR_NONE;
355 static mm_resource_manager_dmn_res_request_s *__create_increase_requests(
356 mm_resource_manager_dmn_res_request_s *releases, mm_resource_manager_dmn_res_request_s *acquires)
360 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
361 mm_resource_manager_dmn_res_request_s *result = NULL;
362 mm_resource_manager_dmn_res_request_s *result_iter = NULL;
363 mm_resource_manager_res_volume resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX] = { 0 };
365 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
367 for (; acquires->type != MM_RESOURCE_MANAGER_NO_RES; acquires++) {
369 if ((resources[acquires->type] > 0 || resources[acquires->type] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
370 && acquires->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
371 MM_RM_ERROR("The client tries to acquire %s by part and fully at once",
372 _mm_resource_manager_get_res_str(acquires->type));
376 if (acquires->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
377 resources[acquires->type] = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
379 if (conf->max_volume[acquires->type] > 1)
380 resources[acquires->type] += acquires->volume;
382 resources[acquires->type]++;
385 MM_RM_DEBUG("(type, vol) = (%d, %d)", acquires->type, resources[acquires->type]);
388 for (; releases->type != MM_RESOURCE_MANAGER_NO_RES; releases++) {
389 if (resources[releases->type] > 1) {
390 resources[releases->type] += releases->volume;
391 MM_RM_INFO("type %d available volume %d", releases->type, resources[releases->type]);
395 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
396 if (resources[i] > 0 || resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
399 result_iter = result = g_new0(mm_resource_manager_dmn_res_request_s, result_len);
400 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
401 if (resources[i] > 0 || resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
402 result_iter->type = i;
403 result_iter->volume = resources[i];
407 result_iter->type = MM_RESOURCE_MANAGER_NO_RES;
412 static mm_resource_manager_error_e __check_increase_requests(mm_resource_manager_dmn_p manager,
413 mm_resource_manager_dmn_res_request_s *requests)
415 mm_resource_manager_res_volume remaining_volume;
416 mm_resource_manager_dmn_p i_man;
417 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
418 gboolean resource_conflict = FALSE;
420 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
422 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
423 MM_RM_RETVM_IF(requests == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "requests is null");
427 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
428 type = requests->type;
429 const char *type_s = _mm_resource_manager_get_res_str(type);
431 MM_RM_RETVM_IF(type < MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER
432 || type >= MM_RESOURCE_MANAGER_RES_TYPE_MAX,
433 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
434 "wrong type %d", type);
435 MM_RM_RETVM_IF(manager->resources[type] == NULL,
436 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
437 "There is no resource %s for the platform", type_s);
439 remaining_volume = conf->max_volume[type];
441 for (i = 0; i < len; i++) {
442 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
444 if (i_man != manager && conf->priority[i_man->app_class] > conf->priority[manager->app_class]
445 && i_man->resources[type]->is_acquired) {
446 if (i_man->resources[type]->parts) {
447 if (requests->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
448 requests->priority_error = TRUE;
449 resource_conflict = TRUE;
450 MM_RM_DEBUG("Resource conflict. Full volume is requested, but only part is available");
453 for (j = 0; j < i_man->resources[type]->parts->len; j++)
454 remaining_volume -= g_array_index(i_man->resources[type]->parts,
455 mm_resource_manager_res_volume, j);
457 if (remaining_volume < requests->volume) {
458 requests->priority_error = TRUE;
459 resource_conflict = TRUE;
460 MM_RM_DEBUG("Resource conflict. %d of %s are available, but %d required",
461 remaining_volume, type_s, requests->volume);
466 requests->priority_error = TRUE;
467 resource_conflict = TRUE;
468 MM_RM_DEBUG("Resource conflict. %s is already acquired fully", type_s);
475 if (resource_conflict) {
476 MM_RM_DEBUG("There is resource conflict");
477 return MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY;
479 MM_RM_DEBUG("type %d", type);
480 return MM_RESOURCE_MANAGER_ERROR_NONE;
484 static void __sync_increase_acquire_requests(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; increase_iter->type != MM_RESOURCE_MANAGER_NO_RES; increase_iter++) {
491 for (acquire_iter = acquires; acquire_iter->type != MM_RESOURCE_MANAGER_NO_RES; acquire_iter++) {
492 if (acquire_iter->type == increase_iter->type)
493 acquire_iter->priority_error = increase_iter->priority_error;
498 static inline void __add_cb_request(GArray *cb_requests,mm_resource_manager_dmn_p man,
499 mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume)
501 mm_resource_manager_dmn_release_cb_request_s *cb_request;
503 g_array_set_size(cb_requests, cb_requests->len + 1);
504 cb_request = &g_array_index(cb_requests, mm_resource_manager_dmn_release_cb_request_s, cb_requests->len - 1);
506 cb_request->manager = man;
507 cb_request->type = type;
508 cb_request->volume = volume;
511 static GArray *__handle_acquire_requests(mm_resource_manager_dmn_p manager,
512 mm_resource_manager_dmn_res_request_s *requests)
514 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
515 mm_resource_manager_res_volume acquired_volume = 0;
516 mm_resource_manager_dmn_p i_man = NULL, j_man = NULL;
517 const char *res_name = NULL;
518 GArray *cb_requests = NULL;
521 gboolean is_released_called_once = FALSE;
522 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
523 mm_resource_manager_res_volume volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
525 MM_RM_RETVM_IF(conf == NULL, NULL, "conf is NULL");
526 MM_RM_RETVM_IF(requests == NULL, NULL, "requests is NULL");
528 cb_requests = g_array_sized_new(FALSE, FALSE, sizeof(mm_resource_manager_dmn_release_cb_request_s),
529 MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE);
531 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
532 type = requests->type;
533 res_name = _mm_resource_manager_get_res_str(type);
534 volume = requests->volume;
536 if (volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
537 MM_RM_DEBUG("Full volume of %s is requested", res_name);
539 for (i = 0; i < managers->len; i++) {
540 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
542 if (!i_man->resources[type]->is_acquired
543 ||conf->priority[i_man->app_class] >conf->priority[manager->app_class]) {
544 i_man->resources[type]->is_acquired = TRUE;
545 if (conf->max_instance[type] > 0)
550 res = i_man->resources[type]->parts;
553 for (j = 0; j < res->len; j++) {
554 __add_cb_request(cb_requests, i_man, type,
555 g_array_index(res, mm_resource_manager_res_volume, j));
557 mm_resource_manager_backend_release(type);
560 g_array_free(res, TRUE);
561 i_man->resources[type]->parts = NULL;
562 i_man->resources[type]->is_acquired = FALSE;
564 MM_RM_DEBUG("All parts of %s are released in RM %"PRIu64,
565 res_name, _mm_rm_hash64(i_man->id));
567 __add_cb_request(cb_requests, i_man, type, MM_RESOURCE_MANAGER_RES_VOLUME_FULL);
569 mm_resource_manager_backend_release(type);
571 i_man->resources[type]->is_acquired = FALSE;
573 MM_RM_DEBUG("Full resource %s is released in RM %"PRIu64" available volume %d",
574 res_name, _mm_rm_hash64(i_man->id), conf->max_volume[type]);
579 MM_RM_INFO("[managers len #%d] [%d type #%d (max inst #%d)] [%d (max vol %d) units of %s] are requested",
580 managers->len, type, res_count[type] + 1,
581 conf->max_instance[type], volume, conf->max_volume[type], res_name);
583 for (i = 0; i < managers->len; i++) {
584 i_man = (mm_resource_manager_dmn_p)managers->pdata[i];
585 res = i_man->resources[type]->parts;
587 if (!i_man->resources[type]->is_acquired || res
588 || conf->priority[i_man->app_class] > conf->priority[manager->app_class]) {
590 if (conf->volume_would_be_checked[type] && conf->max_volume[type] >= 0 && !res) {
591 conf->max_volume[type] -= volume;
592 MM_RM_INFO("[type %d] - %d = %d", type, volume, conf->max_volume[type]);
595 if (conf->max_instance[type] > 0 && conf->max_instance[type] == res_count[type]
596 && !is_released_called_once) {
597 for (j = 0; j < managers->len; j++) {
598 j_man = (mm_resource_manager_dmn_p)managers->pdata[j];
599 res = j_man->resources[type]->parts;
601 if (res && !j_man->is_released) {
602 MM_RM_INFO("[#%d] [#%d / #%d] would be released %s in RM %"PRIu64,
603 managers->len, j + 1, res->len, res_name, _mm_rm_hash64(j_man->id));
605 j_man->is_released = TRUE;
606 __add_cb_request(cb_requests, j_man, type,
607 g_array_index(res, mm_resource_manager_res_volume, 0));
609 mm_resource_manager_backend_release(type);
610 is_released_called_once = TRUE;
616 if (conf->max_instance[type] > 0 && !res)
619 i_man->resources[type]->is_acquired = TRUE;
621 if (conf->max_instance[type] < res_count[type])
624 if (conf->volume_would_be_checked[type] && conf->max_volume[type] < 0
625 && acquired_volume < volume) {
626 for (j = 0; j < managers->len; j++) {
627 j_man = (mm_resource_manager_dmn_p)managers->pdata[j];
628 res = j_man->resources[type]->parts;
630 if (j_man->is_released)
633 acquired_volume += g_array_index(res, mm_resource_manager_res_volume, 0);
634 MM_RM_INFO("[#%d] [#%d / #%d] There are %d units of %s in RM %"PRIu64,
635 managers->len, j + 1, res->len, acquired_volume, res_name,
636 _mm_rm_hash64(j_man->id));
638 j_man->is_released = TRUE;
639 __add_cb_request(cb_requests, j_man, type,
640 g_array_index(res, mm_resource_manager_res_volume, 0));
642 mm_resource_manager_backend_release(type);
644 if (acquired_volume >= volume)
653 res = manager->resources[requests->type]->parts;
655 res = g_array_sized_new(FALSE, FALSE, sizeof(mm_resource_manager_res_volume),
656 MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE);
657 manager->resources[requests->type]->parts = res;
659 g_array_append_val(res, requests->volume);
662 manager->resources[type]->is_acquired = TRUE;
663 mm_resource_manager_backend_acquire(type);
669 static void __handle_release_callbacks(GArray *requests)
672 mm_resource_manager_id id;
673 mm_resource_manager_dmn_release_cb_request_s *request;
674 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
675 mm_resource_manager_res_volume volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
676 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
678 MM_RM_RETM_IF(requests == NULL, "requests is NULL");
679 MM_RM_RETM_IF(conf == NULL, "conf is NULL");
681 for (i = 0; i < requests->len; i++) {
682 request = &g_array_index(requests, mm_resource_manager_dmn_release_cb_request_s, i);
683 id = request->manager->id;
685 type = request->type;
686 volume = request->volume;
687 MM_RM_DEBUG("Sending release callback to RM #%"PRIu64" for %s of volume %d",
688 id, _mm_resource_manager_get_res_str(type), volume);
689 _mmrm_dmn_dbus_release_callback(id, type, volume);
690 if (__wait_for_release_cb_sync(request->manager->id))
691 MM_RM_DEBUG("Release callback sync success");
693 MM_RM_ERROR("Wait for release callback sync failed");
695 if (conf->volume_would_be_checked[type] && volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
696 conf->max_volume[type] += volume;
697 MM_RM_INFO("type %d available volume + %d = %d", type, volume, conf->max_volume[type]);
700 if (conf->max_instance[type] > 0 && res_count[type] > 0) {
702 MM_RM_INFO("The number of type %d #%d", type, res_count[type]);
707 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
708 mm_resource_manager_dmn_res_request_s *requests)
712 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
713 mm_resource_manager_res_volume volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
714 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
716 MM_RM_RETM_IF(conf == NULL, "conf is NULL");
717 MM_RM_RETM_IF(requests == NULL, "requests is NULL");
719 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
721 type = requests->type;
722 volume = requests->volume;
724 if (volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
725 manager->resources[type]->is_acquired = FALSE;
727 parts = manager->resources[type]->parts;
728 for (i = 0; i < parts->len && ((mm_resource_manager_res_volume*)parts->data)[i] != volume; i++);
730 g_array_remove_index_fast(parts, i);
732 if (parts->len == 0) {
733 g_array_free(parts, TRUE);
734 manager->resources[type]->parts = NULL;
735 manager->resources[type]->is_acquired = FALSE;
739 if (conf->volume_would_be_checked[type]) {
740 conf->max_volume[type] += volume;
741 MM_RM_INFO("[type %d] + %d = %d", type, volume, conf->max_volume[type]);
744 if (conf->max_instance[type] > 0) {
746 MM_RM_INFO("The number of type %d #%d", type, res_count[type]);
749 mm_resource_manager_backend_release(type);
753 static void __release_all_resources(mm_resource_manager_dmn_s *manager)
757 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
758 if (manager->resources[i] && manager->resources[i]->is_acquired) {
759 if (manager->resources[i]->parts) {
760 for (j = 0; j < manager->resources[i]->parts->len; j++)
761 mm_resource_manager_backend_release(i);
763 mm_resource_manager_backend_release(i);
765 manager->resources[i]->is_acquired = FALSE;
770 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id)
773 struct pollfd sync = {0};
774 mm_resource_manager_id recv_id;
777 sync.fd = open(RELEASE_CB_SYNC_PATH, O_RDONLY | O_NONBLOCK);
778 MM_RM_RETVM_IF(sync.fd == -1, FALSE, "Sync FIFO cannot be opened");
780 sync.events = POLLIN;
781 switch (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000)) {
783 MM_RM_ERROR("Polling is failed");
787 MM_RM_DEBUG("Wait timeout is elapsed");
791 read_size = read(sync.fd, &recv_id, sizeof(recv_id));
792 if (read_size == sizeof(recv_id)) {
795 MM_RM_ERROR("Sync is received from wrong client #%"PRIu64, recv_id);
797 * Wait POLLHUP to avoid situation when client sent last sync
798 * through the pipe, but not already closed the pipe handle and
799 * the daemon is already opened the pipe again and waiting for
803 if (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000) == 0 || (sync.revents & (POLLHUP | POLLERR)) == 0)
804 MM_RM_ERROR("The client didn't close the FIFO");
806 MM_RM_ERROR("Read is failed (revents=%hd,read_size=%zd)", sync.revents, read_size);