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.
26 #include "daemon/mm_resource_manager_daemon_priv.h"
27 #include "daemon/mm_resource_manager_daemon_conf.h"
28 #include "daemon/mm_resource_manager_daemon_dbus.h"
29 #include "daemon/backend/mm_resource_manager_backend.h"
30 #include "common/mm_resource_manager_utils.h"
34 #define MM_RESOURCE_MANAGER_RESERVED_RM_ARRAY_SIZE 64 /* preallocated size */
35 #define MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE 4 /* preallocated size */
36 #define MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE 32 /* preallocated size */
37 #define MM_RESOURCE_MANGER_NOT_FOUND -1
38 #define RELEASE_CB_SYNC_TIMEOUT 5 /* seconds */
45 /* NULL means, the resource is acquired fully or is not acquired at all */
48 } mm_resource_manager_dmn_res_s;
49 typedef mm_resource_manager_dmn_res_s *mm_resource_manager_dmn_res_p;
52 mm_resource_manager_id id;
53 mm_resource_manager_app_class_e app_class;
54 mm_resource_manager_res_type_e type;
56 /* if an element is NULL, there is no such a resource for the current platform. */
57 mm_resource_manager_dmn_res_p resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
59 } mm_resource_manager_dmn_s;
60 typedef mm_resource_manager_dmn_s *mm_resource_manager_dmn_p;
63 mm_resource_manager_dmn_p manager;
64 mm_resource_manager_res_type_e type;
65 mm_resource_manager_res_volume volume;
66 } mm_resource_manager_dmn_release_cb_request_s;
70 static GPtrArray *managers;
71 static int res_count[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
73 static void __destroy_resource(mm_resource_manager_dmn_res_p res);
74 static void __destroy_manager(void *m);
75 static int __search_manager_index(mm_resource_manager_id id);
76 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id);
77 static mm_resource_manager_error_e __check_release_requests(
78 mm_resource_manager_dmn_p manager,
79 mm_resource_manager_dmn_res_request_s *releases);
80 static mm_resource_manager_dmn_res_request_s *__create_dmn_res_requests(
81 mm_resource_manager_dmn_res_request_s *releases,
82 mm_resource_manager_dmn_res_request_s *acquires);
83 static mm_resource_manager_error_e __check_requests_conflict(
84 mm_resource_manager_dmn_p manager,
85 mm_resource_manager_dmn_res_request_s *requests);
86 static void __sync_increase_acquire_requests(
87 mm_resource_manager_dmn_res_request_s *increases,
88 mm_resource_manager_dmn_res_request_s *acquires);
89 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
90 mm_resource_manager_dmn_res_request_s *requests);
91 static GArray* __handle_acquire_requests(mm_resource_manager_dmn_p manager,
92 mm_resource_manager_dmn_res_request_s *requests);
93 static void __handle_release_callbacks(GArray *requests);
94 static inline void __add_cb_request(GArray *cb_requests, mm_resource_manager_dmn_p mgr,
95 mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume);
96 static void __release_all_resources(mm_resource_manager_dmn_s *manager);
97 static gboolean __poll(struct pollfd sync);
98 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id);
103 gboolean _mmrm_dmn_init(void)
105 unlink(RELEASE_CB_SYNC_PATH);
106 MM_RM_RETVM_IF(mkfifo(RELEASE_CB_SYNC_PATH,
107 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH) == -1, FALSE,
108 "Release callback sync cannot be created");
110 MM_RM_RETVM_IF(mm_resource_manager_backend_init() !=
111 MM_RESOURCE_MANAGER_ERROR_NONE, FALSE,
112 "Back-end cannot be initialized");
114 if (_mmrm_dmn_dbus_init() != MM_RESOURCE_MANAGER_ERROR_NONE) {
115 mm_resource_manager_backend_deinit();
116 MM_RM_ERROR("D-bus server cannot be created");
120 managers = g_ptr_array_new_full(MM_RESOURCE_MANAGER_RESERVED_RM_ARRAY_SIZE,
122 MM_RM_RETVM_IF(managers == NULL, FALSE, "Daemon cannot be initialized");
127 gboolean _mmrm_dmn_deinit()
131 if (mm_resource_manager_backend_deinit() != MM_RESOURCE_MANAGER_ERROR_NONE)
132 MM_RM_ERROR("Error during back-end deinitialization");
134 if (_mmrm_dmn_dbus_deinit() != MM_RESOURCE_MANAGER_ERROR_NONE)
135 MM_RM_ERROR("Error during d-bus server shutdown");
138 for (i = 0; i < managers->len; i++)
139 __release_all_resources((mm_resource_manager_dmn_p)managers->pdata[i]);
141 mm_resource_manager_backend_commit_all();
142 g_ptr_array_free(managers, TRUE);
144 MM_RM_ERROR("Trying to deinit uninitialized daemon");
147 if (unlink(RELEASE_CB_SYNC_PATH) == -1)
148 MM_RM_ERROR("Release callback sync cannot be removed");
153 mm_resource_manager_error_e _mmrm_dmn_create(
154 mm_resource_manager_app_class_e app_class, mm_resource_manager_id *id)
156 mm_resource_manager_dmn_p mgr;
157 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
160 MM_RM_RETVM_IF(app_class < 0 ||
161 app_class >= MM_RESOURCE_MANAGER_APP_CLASS_MAX,
162 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Wrong app class");
164 MM_RM_RETVM_IF(conf->priority[app_class] ==
165 MM_RESOURCE_MANAGER_NO_APP_CLASS,
166 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
167 "App class is not supported for the platform");
169 mgr = g_new0(mm_resource_manager_dmn_s, 1);
170 MM_RM_RAND64(mgr->id);
171 mgr->app_class = app_class;
172 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
173 mgr->resources[i] = conf->max_volume[i] == MM_RESOURCE_MANAGER_NO_RES ?
174 NULL : g_malloc0(sizeof(mm_resource_manager_dmn_s));
177 g_ptr_array_add(managers, mgr);
179 MM_RM_INFO("managers length %d", managers->len);
183 return MM_RESOURCE_MANAGER_ERROR_NONE;
186 mm_resource_manager_error_e _mmrm_dmn_destroy(mm_resource_manager_id id)
188 int idx = __search_manager_index(id);
189 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
190 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
191 mm_resource_manager_dmn_p i_mgr = __search_manager(id);
193 MM_RM_RETVM_IF(idx == MM_RESOURCE_MANGER_NOT_FOUND, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
194 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
195 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
197 i_mgr = (mm_resource_manager_dmn_p)managers->pdata[idx];
199 __release_all_resources((mm_resource_manager_dmn_s *)managers->pdata[idx]);
200 mm_resource_manager_backend_commit_all();
202 g_ptr_array_remove_index_fast(managers, idx);
206 MM_RM_INFO("managers length #%d type %d available volume %d", managers->len, type, conf->max_volume[type]);
212 return MM_RESOURCE_MANAGER_ERROR_NONE;
215 mm_resource_manager_error_e _mmrm_dmn_commit(mm_resource_manager_id id,
216 mm_resource_manager_dmn_res_request_s *releases,
217 mm_resource_manager_dmn_res_request_s *acquires)
219 mm_resource_manager_dmn_p manager = __search_manager(id);
220 mm_resource_manager_error_e ret = MM_RESOURCE_MANAGER_ERROR_NONE;
221 mm_resource_manager_dmn_res_request_s *increases = NULL;
224 MM_RM_RETVM_IF(manager == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
225 "Resource manager #%"PRIu64" doesn't exist", _mm_rm_hash64(id));
227 (releases == NULL || releases[0].type == MM_RESOURCE_MANAGER_NO_RES) &&
228 (acquires == NULL || acquires[0].type == MM_RESOURCE_MANAGER_NO_RES),
229 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Commit request is empty");
231 ret = __check_release_requests(manager, releases);
232 MM_RM_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE, ret,
233 "check_release_requests is failed [0x%x]", ret);
235 increases = __create_dmn_res_requests(releases, acquires);
236 MM_RM_RETVM_IF(increases == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
237 "create_increase_requests is failed");
239 ret = __check_requests_conflict(manager, increases);
240 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
241 __sync_increase_acquire_requests(increases, acquires);
247 __handle_release_requests(manager, releases);
248 cb_requests = __handle_acquire_requests(manager, acquires);
249 MM_RM_RETVM_IF(cb_requests == NULL, MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH,
250 "not enough free resource volume");
251 __handle_release_callbacks(cb_requests);
252 if (!mm_resource_manager_backend_commit_all()) {
255 * function can fail only if resource management back-end is not solely
256 * used by mm-resource-manager or if the back-end cannot acquire/release
257 * a resource because of some internal error.
259 * Initiate status disconnected and reload the back-end and the RM
262 kill(getpid(), SIGHUP);
263 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
265 g_array_free(cb_requests, TRUE);
270 void _mmrm_dmn_status_callback(mm_resource_manager_status_e status)
272 _mmrm_dmn_dbus_status_callback(status);
275 static void __destroy_resource(mm_resource_manager_dmn_res_p res)
281 g_array_free(res->parts, TRUE);
286 static void __destroy_manager(void *m)
288 mm_resource_manager_dmn_p mgr = (mm_resource_manager_dmn_p) m;
291 MM_RM_RETM_IF(mgr == NULL, "NULL pointer");
293 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
294 __destroy_resource(mgr->resources[i]);
299 static int __search_manager_index(mm_resource_manager_id id)
303 for (i = managers->len - 1; i >= 0; i--) {
304 if (((mm_resource_manager_dmn_p)managers->pdata[i])->id == id)
308 return MM_RESOURCE_MANGER_NOT_FOUND;
311 static inline mm_resource_manager_dmn_p __search_manager(mm_resource_manager_id id)
313 int i = __search_manager_index(id);
314 return i == MM_RESOURCE_MANGER_NOT_FOUND ? NULL : managers->pdata[i];
317 static mm_resource_manager_error_e __check_release_requests(mm_resource_manager_dmn_p manager,
318 mm_resource_manager_dmn_res_request_s *releases)
321 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
322 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
324 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
325 MM_RM_RETVM_IF(releases == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "requests is null");
327 for (; releases->type != MM_RESOURCE_MANAGER_NO_RES; releases++) {
329 type = releases->type;
330 const char *type_s = _mm_resource_manager_get_res_str(type);
332 MM_RM_RETVM_IF(manager->resources[type] == NULL,
333 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED, "There is no resource %s for the platform", type_s);
335 if (manager->resources[type]->is_acquired) {
336 if (manager->resources[type]->parts == NULL) {
337 if (releases->volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
338 MM_RM_ERROR("Resource %s is acquired fully, but a resource part is tried to be released", type_s);
339 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
342 for (i = 0; i < manager->resources[type]->parts->len &&
343 ((mm_resource_manager_res_volume*)manager->resources[type]->parts->data)[i] != releases->volume; i++);
344 if (i == manager->resources[type]->parts->len) {
345 MM_RM_ERROR("Part of %s of volume %d is not acquired", type_s, releases->volume);
346 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
350 MM_RM_ERROR("Resource %s is not acquired", type_s);
351 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
353 MM_RM_DEBUG("Release requests are OK type %d available volume %d", type, conf->max_volume[type]);
356 return MM_RESOURCE_MANAGER_ERROR_NONE;
359 static mm_resource_manager_dmn_res_request_s *__create_dmn_res_requests(
360 mm_resource_manager_dmn_res_request_s *releases, mm_resource_manager_dmn_res_request_s *acquires)
364 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
365 mm_resource_manager_dmn_res_request_s *result = NULL;
366 mm_resource_manager_dmn_res_request_s *result_iter = NULL;
367 mm_resource_manager_res_volume resources[MM_RESOURCE_MANAGER_RES_TYPE_MAX] = { 0 };
369 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
371 for (; acquires->type != MM_RESOURCE_MANAGER_NO_RES; acquires++) {
373 if ((resources[acquires->type] > 0 || resources[acquires->type] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) &&
374 acquires->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
375 MM_RM_ERROR("The client tries to acquire %s by part and fully at once",
376 _mm_resource_manager_get_res_str(acquires->type));
380 if (acquires->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
381 resources[acquires->type] = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
383 if (conf->max_volume[acquires->type] > 1)
384 resources[acquires->type] += acquires->volume;
386 resources[acquires->type]++;
389 MM_RM_DEBUG("(type, vol) = (%d, %d)", acquires->type, resources[acquires->type]);
392 for (; releases->type != MM_RESOURCE_MANAGER_NO_RES; releases++) {
393 if (resources[releases->type] > 1) {
394 resources[releases->type] += releases->volume;
395 MM_RM_INFO("type %d available volume %d", releases->type, resources[releases->type]);
399 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
400 if (resources[i] > 0 || resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
403 result_iter = result = g_new0(mm_resource_manager_dmn_res_request_s, result_len);
404 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
405 if (resources[i] > 0 || resources[i] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
406 result_iter->type = i;
407 result_iter->volume = resources[i];
411 result_iter->type = MM_RESOURCE_MANAGER_NO_RES;
416 static mm_resource_manager_error_e __check_requests_conflict(mm_resource_manager_dmn_p manager,
417 mm_resource_manager_dmn_res_request_s *requests)
419 mm_resource_manager_res_volume remaining_volume;
420 mm_resource_manager_dmn_p i_mgr;
421 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
423 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
425 MM_RM_RETVM_IF(conf == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "conf is null");
426 MM_RM_RETVM_IF(manager == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "manager is null");
427 MM_RM_RETVM_IF(requests == NULL, MM_RESOURCE_MANAGER_ERROR_NONE, "requests is null");
431 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
432 type = requests->type;
433 const char *type_s = _mm_resource_manager_get_res_str(type);
435 MM_RM_RETVM_IF(type < MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER ||
436 type >= MM_RESOURCE_MANAGER_RES_TYPE_MAX,
437 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
438 "wrong type %d", type);
439 MM_RM_RETVM_IF(manager->resources[type] == NULL,
440 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
441 "There is no resource %s for the platform", type_s);
443 remaining_volume = conf->max_volume[type];
445 for (i = 0; i < len; i++) {
446 i_mgr = (mm_resource_manager_dmn_p)managers->pdata[i];
448 if (i_mgr != manager && conf->priority[i_mgr->app_class] > conf->priority[manager->app_class] &&
449 i_mgr->resources[type]->is_acquired) {
450 if (i_mgr->resources[type]->parts) {
451 if (requests->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
452 requests->priority_error = TRUE;
453 MM_RM_DEBUG("Resource conflict. Full volume is requested, but only part is available");
454 return MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY;
456 for (j = 0; j < i_mgr->resources[type]->parts->len; j++)
457 remaining_volume -= g_array_index(i_mgr->resources[type]->parts,
458 mm_resource_manager_res_volume, j);
460 if (remaining_volume < requests->volume) {
461 requests->priority_error = TRUE;
462 MM_RM_DEBUG("Resource conflict. %d of %s are available, but %d required",
463 remaining_volume, type_s, requests->volume);
464 return MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY;
468 requests->priority_error = TRUE;
469 MM_RM_DEBUG("Resource conflict. %s is already acquired fully", type_s);
470 return MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY;
476 return MM_RESOURCE_MANAGER_ERROR_NONE;
479 static void __sync_increase_acquire_requests(mm_resource_manager_dmn_res_request_s *increases,
480 mm_resource_manager_dmn_res_request_s *acquires)
482 mm_resource_manager_dmn_res_request_s *increase_iter;
483 mm_resource_manager_dmn_res_request_s *acquire_iter;
485 for (increase_iter = increases; increase_iter->type != MM_RESOURCE_MANAGER_NO_RES; increase_iter++) {
486 for (acquire_iter = acquires; acquire_iter->type != MM_RESOURCE_MANAGER_NO_RES; acquire_iter++) {
487 if (acquire_iter->type == increase_iter->type)
488 acquire_iter->priority_error = increase_iter->priority_error;
493 static inline void __add_cb_request(GArray *cb_requests,mm_resource_manager_dmn_p mgr,
494 mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume)
496 mm_resource_manager_dmn_release_cb_request_s *cb_request;
498 g_array_set_size(cb_requests, cb_requests->len + 1);
499 cb_request = &g_array_index(cb_requests, mm_resource_manager_dmn_release_cb_request_s, cb_requests->len - 1);
501 cb_request->manager = mgr;
502 cb_request->type = type;
503 cb_request->volume = volume;
506 static GArray *__handle_acquire_requests(mm_resource_manager_dmn_p manager,
507 mm_resource_manager_dmn_res_request_s *requests)
509 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
510 mm_resource_manager_res_volume acquired_volume = 0;
511 mm_resource_manager_dmn_p i_mgr = NULL, j_mgr = NULL;
512 const char *res_name = NULL;
513 GArray *cb_requests = NULL;
516 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
517 mm_resource_manager_res_volume volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
519 MM_RM_RETVM_IF(conf == NULL, NULL, "conf is NULL");
520 MM_RM_RETVM_IF(requests == NULL, NULL, "requests is NULL");
522 cb_requests = g_array_sized_new(FALSE, FALSE, sizeof(mm_resource_manager_dmn_release_cb_request_s),
523 MM_RESOURCE_MANAGER_RESERVED_CALLBACK_ARRAY_SIZE);
525 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
526 type = requests->type;
527 res_name = _mm_resource_manager_get_res_str(type);
528 volume = requests->volume;
530 if (volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
531 MM_RM_DEBUG("Resource of %s is requested (mgr %p)", res_name, manager);
533 for (i = 0; i < managers->len; i++) {
534 i_mgr = (mm_resource_manager_dmn_p)managers->pdata[i];
536 if (manager->id == i_mgr->id || conf->priority[i_mgr->app_class] >conf->priority[manager->app_class]) {
537 i_mgr->resources[type]->is_acquired = TRUE;
539 i_mgr->volume = volume;
540 MM_RM_INFO("Reset the value of release in RM %"PRIu64" (mgr %p)", _mm_rm_hash64(i_mgr->id), i_mgr);
541 if (conf->max_instance[type] > 0)
546 if ((res = i_mgr->resources[type]->parts)) { /* always null, which is no conflict case now */
547 for (j = 0; j < res->len; j++) {
548 __add_cb_request(cb_requests, i_mgr, type, g_array_index(res, mm_resource_manager_res_volume, j));
549 mm_resource_manager_backend_release(type);
551 g_array_free(res, TRUE);
552 i_mgr->resources[type]->parts = NULL;
554 MM_RM_WARNING("Resource of %s is conflicted in RM %"PRIu64, res_name, _mm_rm_hash64(i_mgr->id));
556 __add_cb_request(cb_requests, i_mgr, type, MM_RESOURCE_MANAGER_RES_VOLUME_FULL);
558 mm_resource_manager_backend_release(type);
560 MM_RM_INFO("Resource %s is released (%d) in RM %"PRIu64" available volume %d", res_name,
561 i_mgr->resources[type]->is_acquired, _mm_rm_hash64(i_mgr->id), conf->max_volume[type]);
565 MM_RM_INFO("[managers len #%d] [%s #%d (max inst #%d)] [%d (max vol %d) units of %s] are requested",
566 managers->len, _mm_resource_manager_get_res_str(type), res_count[type] + 1,
567 conf->max_instance[type], volume, conf->max_volume[type], res_name);
569 if (conf->max_instance[type] > 0 && conf->max_instance[type] == res_count[type]) {
570 for (i= 0; i < managers->len; i++) {
571 i_mgr = (mm_resource_manager_dmn_p)managers->pdata[j];
572 res = i_mgr->resources[type]->parts;
574 if (res && i_mgr->resources[type]->is_acquired) {
575 MM_RM_INFO("[#%d] [#%d / #%d] would be released %s in RM %"PRIu64,
576 managers->len, i + 1, res->len, res_name, _mm_rm_hash64(i_mgr->id));
578 __add_cb_request(cb_requests, i_mgr, type, g_array_index(res, mm_resource_manager_res_volume, 0));
580 mm_resource_manager_backend_release(type);
585 for (i = 0; i < managers->len; i++) {
586 i_mgr = (mm_resource_manager_dmn_p)managers->pdata[i];
587 res = i_mgr->resources[type]->parts;
589 if (manager->id == i_mgr->id || conf->priority[i_mgr->app_class] > conf->priority[manager->app_class]) {
591 if (conf->volume_would_be_checked[type]) {
592 if (!i_mgr->resources[type]->is_acquired && conf->max_volume[type] >= 0) {
593 i_mgr->resources[type]->is_acquired = TRUE;
595 i_mgr->volume = volume;
596 conf->max_volume[type] -= volume;
597 MM_RM_INFO("[type %d] - %d = %d", type, volume, conf->max_volume[type]);
600 if (conf->volume_would_be_checked[type] && conf->max_volume[type] < 0
601 && acquired_volume < volume) {
602 for (j = 0; j < managers->len; j++) {
603 j_mgr = (mm_resource_manager_dmn_p)managers->pdata[j];
604 res = j_mgr->resources[type]->parts;
606 if (!j_mgr->resources[type]->is_acquired)
609 acquired_volume += g_array_index(res, mm_resource_manager_res_volume, 0);
610 MM_RM_INFO("[#%d] [#%d / #%d] There are %d units of %s in RM %"PRIu64,
611 managers->len, j + 1, res->len, acquired_volume, res_name, _mm_rm_hash64(j_mgr->id));
613 __add_cb_request(cb_requests, j_mgr, type, g_array_index(res, mm_resource_manager_res_volume, 0));
615 mm_resource_manager_backend_release(type);
617 if (acquired_volume >= volume)
623 if (i_mgr->resources[type]->is_acquired)
626 i_mgr->resources[type]->is_acquired = TRUE;
630 res = manager->resources[requests->type]->parts;
632 res = g_array_sized_new(FALSE, FALSE, sizeof(mm_resource_manager_res_volume),
633 MM_RESOURCE_MANAGER_RESERVED_PART_ARRAY_SIZE);
634 manager->resources[requests->type]->parts = res;
636 g_array_append_val(res, requests->volume);
640 manager->resources[type]->is_acquired = TRUE;
641 mm_resource_manager_backend_acquire(type);
647 static void __handle_release_callbacks(GArray *requests)
650 mm_resource_manager_id id;
651 mm_resource_manager_dmn_release_cb_request_s *request;
652 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
653 mm_resource_manager_res_volume volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
654 mm_resource_manager_dmn_p mgr = NULL;
655 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
657 MM_RM_RETM_IF(requests == NULL, "requests is NULL");
658 MM_RM_RETM_IF(conf == NULL, "conf is NULL");
660 for (i = 0; i < requests->len; i++) {
661 request = &g_array_index(requests, mm_resource_manager_dmn_release_cb_request_s, i);
662 mgr = request->manager;
663 type = request->type;
664 volume = request->volume;
666 if (!mgr->resources[type]->is_acquired)
672 if (mgr->type == type && mgr->volume == volume && !mgr->resources[type]->is_acquired) {
673 MM_RM_WARNING("Resource (mgr %p) release callback is already completed RM #%"PRIu64" for %s of volume %d",
674 mgr, id, _mm_resource_manager_get_res_str(type), volume);
678 MM_RM_INFO("Sending release callback to [mgr %p] RM #%"PRIu64" for %s of volume %d",
679 mgr, id, _mm_resource_manager_get_res_str(type), volume);
681 _mmrm_dmn_dbus_release_callback(id, type, volume);
682 if (__wait_for_release_cb_sync(id))
683 MM_RM_DEBUG("Release callback sync success");
685 MM_RM_ERROR("Wait for release callback sync failed");
687 if (conf->volume_would_be_checked[type] && volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
688 conf->max_volume[type] += volume;
689 MM_RM_INFO("type %d available volume + %d = %d", type, volume, conf->max_volume[type]);
692 if (conf->max_instance[type] > 0 && res_count[type] > 0) {
694 MM_RM_INFO("The number of type %d #%d", type, res_count[type]);
697 mgr->resources[type]->is_acquired = FALSE;
701 static void __handle_release_requests(mm_resource_manager_dmn_p manager,
702 mm_resource_manager_dmn_res_request_s *requests)
706 mm_resource_manager_res_type_e type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
707 mm_resource_manager_res_volume volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
708 mm_resource_manager_conf_s *conf = mm_resource_manager_get_conf();
710 MM_RM_RETM_IF(conf == NULL, "conf is NULL");
711 MM_RM_RETM_IF(requests == NULL, "requests is NULL");
713 for (; requests->type != MM_RESOURCE_MANAGER_NO_RES; requests++) {
715 type = requests->type;
716 volume = requests->volume;
718 if (volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL) {
719 manager->resources[type]->is_acquired = FALSE;
721 parts = manager->resources[type]->parts;
722 for (i = 0; i < parts->len && ((mm_resource_manager_res_volume*)parts->data)[i] != volume; i++);
724 g_array_remove_index_fast(parts, i);
726 if (parts->len == 0) {
727 g_array_free(parts, TRUE);
728 manager->resources[type]->parts = NULL;
729 manager->resources[type]->is_acquired = FALSE;
733 if (conf->volume_would_be_checked[type]) {
734 conf->max_volume[type] += volume;
735 MM_RM_INFO("[type %d] + %d = %d", type, volume, conf->max_volume[type]);
738 if (conf->max_instance[type] > 0) {
740 MM_RM_INFO("The number of type %d #%d", type, res_count[type]);
743 mm_resource_manager_backend_release(type);
747 static void __release_all_resources(mm_resource_manager_dmn_s *manager)
751 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
752 if (manager->resources[i] && manager->resources[i]->is_acquired) {
753 if (manager->resources[i]->parts) {
754 for (j = 0; j < manager->resources[i]->parts->len; j++)
755 mm_resource_manager_backend_release(i);
757 mm_resource_manager_backend_release(i);
759 manager->resources[i]->is_acquired = FALSE;
764 static gboolean __poll(struct pollfd sync)
770 while (try_cnt++ < 3) {
771 sync.events = POLLIN;
774 ret = poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000);
778 MM_RM_ERROR("Polling is failed [fd %d errno %d]", sync.fd, errsv);
782 } else if (ret == 0) {
783 MM_RM_WARNING("Wait timeout is elapsed [fd %d]", sync.fd);
793 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id)
795 gboolean ret = FALSE;
796 struct pollfd sync = {0};
797 mm_resource_manager_id recv_id;
800 sync.fd = open(RELEASE_CB_SYNC_PATH, O_RDONLY | O_NONBLOCK);
801 MM_RM_RETVM_IF(sync.fd == -1, FALSE, "Sync FIFO cannot be opened");
806 read_size = read(sync.fd, &recv_id, sizeof(recv_id));
807 if (read_size != sizeof(recv_id)) {
808 MM_RM_ERROR("Read is failed (revents=%hd, read_size=%zd)", sync.revents, read_size);
812 if (id != _mm_rm_hash64(recv_id)) {
813 MM_RM_ERROR("Sync is received from wrong client #%"PRIu64, id);