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 "common/mm_resource_manager_utils.h"
25 #include "lib/mm_resource_manager_priv.h"
26 #include "common/mm_resource_manager_dbus.h"
30 #define MM_RESOURCE_MANAGER(x) ((mm_resource_manager_s *) (x))
31 #define MM_RESOURCE_MANAGER_CHECK(x) \
32 MM_RM_UNLOCK_RETVM_IF(!__check_rm_handle(x), handles_lock, \
33 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, \
34 "Invalid resource manager handle %p", x)
35 #define MM_RESOURCE_MANAGER_RESERVED_RES_ARRAY_SIZE 16 /* preallocated size */
36 #define MM_RESOURCE_MANAGER_RESERVED_HANDLE_ARRAY_SIZE 8 /* preallocated size */
37 #define MM_RESOURCE_MANAGER_RES_NOT_FOUND -1
42 MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE, /* uncommitted */
43 MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED, /* committed */
44 MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE /* uncommitted */
45 } mm_resource_manager_res_state_e;
50 } mm_resource_manager_cb_s;
53 mm_resource_manager_res_type_e type;
54 mm_resource_manager_res_volume volume;
55 mm_resource_manager_res_state_e state;
56 gboolean is_acquire_failed;
57 } mm_resource_manager_res_s;
58 typedef mm_resource_manager_res_s *mm_resource_manager_res_p;
61 mm_resource_manager_id id;
65 mm_resource_manager_cb_s release_cb;
66 mm_resource_manager_cb_s status_cb;
68 GMutex resources_lock;
70 mm_resource_manager_res_volume __max_resource_volumes
71 [MM_RESOURCE_MANAGER_RES_TYPE_MAX];
72 mm_resource_manager_res_volume __condition_volumes
73 [MM_RESOURCE_MANAGER_RES_TYPE_MAX]
74 [MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX];
76 MMResourceManager *dbus_proxy;
78 GMainContext *dispatcher_context;
79 GMainLoop *dispatcher_loop;
80 GThread *dispatcher_thread;
81 } mm_resource_manager_s;
85 static GMutex handles_lock;
86 static GPtrArray *handles;
90 static void __init_lib() __attribute__((constructor));
91 static void __deinit_lib() __attribute__((destructor));
92 static int __check_resource(mm_resource_manager_s *rm,
93 mm_resource_manager_res_type_e type,
94 mm_resource_manager_res_volume volume);
95 static int __create_resource(mm_resource_manager_s *rm,
96 mm_resource_manager_res_type_e type,
97 mm_resource_manager_res_volume volume, mm_resource_manager_res_p *res);
98 static void __destroy_resource(void *res);
99 static int __get_resource_index(mm_resource_manager_s *rm,
100 mm_resource_manager_res_p res);
101 static gboolean __mark_resource_for_release(GPtrArray *resources, int index,
102 mm_resource_manager_res_p resource); /* FALSE if resource is destroyed */
103 static void __send_release_cb_sync(mm_resource_manager_id id);
104 static void __mm_resource_manager_release_callback(mm_resource_manager_s *handle,
105 mm_resource_manager_id id,
106 mm_resource_manager_res_type_e type,
107 mm_resource_manager_res_volume volume);
108 static void __mm_resource_manager_status_callback(mm_resource_manager_s *handle,
109 mm_resource_manager_status_e status);
111 static int __dbus_init(mm_resource_manager_s *handle);
112 static int __dbus_deinit(mm_resource_manager_s *handle);
113 static int __dbus_init_conf(mm_resource_manager_s *handle);
114 static gboolean __check_rm_handle(mm_resource_manager_s *handle);
115 static int __dbus_create(mm_resource_manager_s *handle,
116 mm_resource_manager_app_class_e app_class);
117 static int __dbus_destroy(mm_resource_manager_s *handle);
118 static int __dbus_commit(mm_resource_manager_s *handle);
119 static void __dbus_release_callback(MMResourceManager *object, guint64 arg_id,
120 gint arg_resource_type, gint arg_volume);
121 static void __dbus_status_callback(MMResourceManager *object, gint arg_status);
122 static gpointer __dispatcher_thread(gpointer user_data);
123 static void __destroy_dispatcher(mm_resource_manager_s *handle);
127 int _mm_resource_manager_create(mm_resource_manager_app_class_e app_class,
128 mm_resource_manager_release_cb cb, void *cb_data,
129 mm_resource_manager_h *rm)
131 mm_resource_manager_s *handle = *rm = NULL;
133 GError *error = NULL;
135 handle = (mm_resource_manager_s *) calloc(1, sizeof(mm_resource_manager_s));
136 MM_RM_RETVM_IF(NULL == handle, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
137 "Error allocating memory for Handle");
139 handle->dispatcher_context = g_main_context_new();
140 if (!handle->dispatcher_context) {
142 MM_RM_ERROR("g_main_context_new failed");
143 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
145 MM_RM_INFO("new main context %p", handle->dispatcher_context);
147 handle->dispatcher_loop = g_main_loop_new(handle->dispatcher_context, FALSE);
148 if (!handle->dispatcher_loop) {
149 g_main_context_unref(handle->dispatcher_context);
151 MM_RM_ERROR("g_main_loop_new failed");
152 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
154 MM_RM_INFO("new main loop %p", handle->dispatcher_loop);
156 ret = __dbus_init(handle);
157 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
158 __destroy_dispatcher(handle);
160 MM_RM_ERROR("Error initializing dbus client");
164 handle->dispatcher_thread = g_thread_try_new("dispatcher_thread", __dispatcher_thread, handle->dispatcher_loop, &error);
165 if (!handle->dispatcher_thread) {
167 MM_RM_ERROR("dispatcher_thread creation failed : %s", error->message);
170 __destroy_dispatcher(handle);
172 return MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH;
174 MM_RM_INFO("new dispatcher thread %p", handle->dispatcher_thread);
176 ret = __dbus_init_conf(handle);
177 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
178 __destroy_dispatcher(handle);
180 MM_RM_ERROR("Configuration cannot be requested");
184 ret = __dbus_create(handle, app_class);
185 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
186 __destroy_dispatcher(handle);
188 MM_RM_ERROR("Dbus create request failed");
192 handle->release_cb.cb = cb;
193 handle->release_cb.user_data = cb_data;
195 handle->resources = g_ptr_array_new_full(
196 MM_RESOURCE_MANAGER_RESERVED_RES_ARRAY_SIZE, __destroy_resource);
198 g_mutex_init(&handle->resources_lock);
200 *rm = (mm_resource_manager_h *) handle;
201 g_mutex_lock(&handles_lock);
202 g_ptr_array_add(handles, handle);
204 MM_RM_INFO("Resource manager #%"PRIu64" is created", _mm_rm_hash64(handle->id));
205 g_mutex_unlock(&handles_lock);
207 return MM_RESOURCE_MANAGER_ERROR_NONE;
210 int _mm_resource_manager_destroy(mm_resource_manager_h rm)
212 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
213 mm_resource_manager_id id;
214 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
216 g_mutex_lock(&handles_lock);
217 MM_RESOURCE_MANAGER_CHECK(handle);
218 g_ptr_array_remove_fast(handles, handle);
219 g_mutex_unlock(&handles_lock);
223 g_mutex_lock(&handle->resources_lock);
224 ret = __dbus_destroy(handle);
225 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
226 MM_RM_ERROR("Dbus destroy request failed 0x%x", ret);
228 __destroy_dispatcher(handle);
230 g_ptr_array_free(handle->resources, TRUE);
231 g_mutex_unlock(&handle->resources_lock);
233 g_mutex_clear(&handle->resources_lock);
236 if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
237 MM_RM_INFO("Resource manager #%"PRIu64" is destroyed", _mm_rm_hash64(id));
242 int _mm_resource_manager_mark_for_acquire(
243 mm_resource_manager_h rm, mm_resource_manager_res_type_e type,
244 mm_resource_manager_res_volume volume,
245 mm_resource_manager_res_h *resource_h)
247 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
248 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
249 mm_resource_manager_res_p resource;
251 g_mutex_lock(&handles_lock);
252 MM_RESOURCE_MANAGER_CHECK(handle);
253 g_mutex_lock(&handle->resources_lock);
254 g_mutex_unlock(&handles_lock);
256 ret = __create_resource(handle, type, volume, &resource);
257 MM_RM_UNLOCK_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE,
258 handle->resources_lock, ret, "Resource cannot be created");
259 g_ptr_array_add(handle->resources, resource);
261 *resource_h = resource;
263 MM_RM_INFO("Resource %p of type %d with volume %d is marked for acquire in "
264 "resource manager #%"PRIu64, *resource_h, type, volume,
265 _mm_rm_hash64(handle->id));
266 g_mutex_unlock(&handle->resources_lock);
271 int _mm_resource_manager_resize_marked(mm_resource_manager_h rm,
272 mm_resource_manager_res_h resource_h,
273 mm_resource_manager_res_volume new_volume)
275 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
276 mm_resource_manager_res_p resource = (mm_resource_manager_res_p) resource_h;
277 mm_resource_manager_res_p tmp_resource;
278 mm_resource_manager_res_volume add_volume;
280 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
282 g_mutex_lock(&handles_lock);
283 MM_RESOURCE_MANAGER_CHECK(handle);
284 g_mutex_lock(&handle->resources_lock);
285 g_mutex_unlock(&handles_lock);
287 i = __get_resource_index(handle, resource);
288 MM_RM_UNLOCK_RETVM_IF(i == MM_RESOURCE_MANAGER_RES_NOT_FOUND,
289 handle->resources_lock,
290 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
291 "Invalid resource handle");
292 if (new_volume == resource->volume) {
293 g_mutex_unlock(&handle->resources_lock);
294 MM_RM_DEBUG("New volume equals the old. Resize is not needed.");
298 add_volume = resource->volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL &&
299 new_volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL &&
300 resource->volume < new_volume ? (new_volume - resource->volume) : 0;
302 switch (resource->state) {
303 case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
304 if (add_volume > 0) {
305 ret = __check_resource(handle, resource->type, add_volume);
306 MM_RM_UNLOCK_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE,
307 handle->resources_lock, ret, "Resource check failed");
309 resource->volume = new_volume;
312 case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
313 case MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED:
314 ret = __create_resource(handle, resource->type, add_volume, &tmp_resource);
315 MM_RM_UNLOCK_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE,
316 handle->resources_lock, ret, "Resource cannot be created");
318 tmp_resource->volume = resource->volume;
319 tmp_resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
321 g_ptr_array_add(handle->resources, resource);
322 resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE;
323 resource->volume = new_volume;
325 handle->resources->pdata[i] = tmp_resource;
329 MM_RM_INFO("Resource %p is resized for acquire in resource manager #%"PRIu64,
330 resource_h, _mm_rm_hash64(handle->id));
331 g_mutex_unlock(&handle->resources_lock);
336 int _mm_resource_manager_mark_for_release(mm_resource_manager_h rm,
337 mm_resource_manager_res_h resource_h)
339 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
340 mm_resource_manager_res_p resource = (mm_resource_manager_res_p) resource_h;
343 g_mutex_lock(&handles_lock);
344 MM_RESOURCE_MANAGER_CHECK(handle);
345 g_mutex_lock(&handle->resources_lock);
346 g_mutex_unlock(&handles_lock);
348 i = __get_resource_index(handle, resource);
349 MM_RM_UNLOCK_RETVM_IF(i == MM_RESOURCE_MANAGER_RES_NOT_FOUND,
350 handle->resources_lock,
351 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
352 "Invalid resource handle");
354 __mark_resource_for_release(handle->resources, i, resource);
356 MM_RM_INFO("Resource %p is marked for release in resource manager #%"PRIu64,
357 resource_h, _mm_rm_hash64(handle->id));
358 g_mutex_unlock(&handle->resources_lock);
360 return MM_RESOURCE_MANAGER_ERROR_NONE;
363 int _mm_resource_manager_mark_all_for_release(mm_resource_manager_h rm)
365 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
368 g_mutex_lock(&handles_lock);
369 MM_RESOURCE_MANAGER_CHECK(handle);
370 g_mutex_lock(&handle->resources_lock);
371 g_mutex_unlock(&handles_lock);
373 for (i = 0; i < handle->resources->len; i++) {
374 if (!__mark_resource_for_release(handle->resources, i,
375 (mm_resource_manager_res_p) handle->resources->pdata[i]))
379 MM_RM_INFO("All resources are marked for release in resource manager #%"PRIu64,
380 _mm_rm_hash64(handle->id));
381 g_mutex_unlock(&handle->resources_lock);
383 return MM_RESOURCE_MANAGER_ERROR_NONE;
386 int _mm_resource_manager_get_resource_info(mm_resource_manager_h rm,
387 mm_resource_manager_res_h resource_h,
388 mm_resource_manager_res_info_s *info)
390 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
391 mm_resource_manager_res_p resource = (mm_resource_manager_res_p) resource_h;
394 g_mutex_lock(&handles_lock);
395 MM_RESOURCE_MANAGER_CHECK(handle);
396 g_mutex_lock(&handle->resources_lock);
397 g_mutex_unlock(&handles_lock);
399 i = __get_resource_index(handle, resource);
400 MM_RM_UNLOCK_RETVM_IF(i == MM_RESOURCE_MANAGER_RES_NOT_FOUND,
401 handle->resources_lock,
402 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
403 "Invalid resource handle");
405 info->type = resource->type;
406 info->volume = resource->volume;
407 info->is_acquire_failed = resource->is_acquire_failed;
409 MM_RM_INFO("Info structure of resource %p in resource manager #%"PRIu64" is filled",
410 resource_h, _mm_rm_hash64(handle->id));
411 g_mutex_unlock(&handle->resources_lock);
413 return MM_RESOURCE_MANAGER_ERROR_NONE;
416 int _mm_resource_manager_commit(mm_resource_manager_h rm)
418 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
421 g_mutex_lock(&handles_lock);
422 MM_RESOURCE_MANAGER_CHECK(handle);
423 g_mutex_lock(&handle->resources_lock);
424 g_mutex_unlock(&handles_lock);
426 ret = __dbus_commit(handle);
427 if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
428 MM_RM_INFO("Changes in resource manager #%"PRIu64" have been committed successfully",
429 _mm_rm_hash64(handle->id));
431 MM_RM_ERROR("Dbus commit request failed");
432 g_mutex_unlock(&handle->resources_lock);
437 int _mm_resource_manager_set_status_cb(mm_resource_manager_h rm,
438 mm_resource_manager_status_cb cb, void *user_data)
440 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
442 g_mutex_lock(&handles_lock);
443 MM_RESOURCE_MANAGER_CHECK(handle);
444 g_mutex_lock(&handle->resources_lock);
445 g_mutex_unlock(&handles_lock);
447 handle->status_cb.cb = cb;
448 handle->status_cb.user_data = user_data;
449 g_mutex_unlock(&handle->resources_lock);
451 MM_RM_INFO("Status callback %p in resource manager #%"PRIu64" is set", cb,
452 _mm_rm_hash64(handle->id));
454 return MM_RESOURCE_MANAGER_ERROR_NONE;
457 int _mm_resource_manager_get_res_type_max_volume(mm_resource_manager_h rm,
458 mm_resource_manager_res_type_e type,
459 mm_resource_manager_res_volume *max_volume)
461 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
463 if (handle->__max_resource_volumes[type] == MM_RESOURCE_MANAGER_NO_RES) {
464 MM_RM_DEBUG("No resource for the platform");
465 return MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED;
467 *max_volume = handle->__max_resource_volumes[type];
468 return MM_RESOURCE_MANAGER_ERROR_NONE;
472 int _mm_resource_manager_get_res_type_volume(mm_resource_manager_h rm,
473 mm_resource_manager_res_type_e type,
474 mm_resource_manager_res_type_cond_e condition,
475 mm_resource_manager_res_volume *volume)
477 mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
479 if (handle->__condition_volumes[type][condition] == MM_RESOURCE_MANAGER_NO_RES) {
480 MM_RM_DEBUG("No pair (resource,condition) for the platform");
481 return MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED;
483 *volume = handle->__condition_volumes[type][condition];
484 return MM_RESOURCE_MANAGER_ERROR_NONE;
488 void __mm_resource_manager_release_callback(mm_resource_manager_s *handle,
489 mm_resource_manager_id id,
490 mm_resource_manager_res_type_e type,
491 mm_resource_manager_res_volume volume)
493 mm_resource_manager_res_s *resource;
494 mm_resource_manager_id handle_id;
495 gboolean release_all = FALSE;
498 MM_RM_DEBUG("Release callback is emitted for %s of volume %d in RM #%"PRIu64,
499 _mm_resource_manager_get_res_str(type), volume, id);
501 handle_id = handle->id;
502 MM_RM_HASH64(handle_id);
503 if (handle_id == id) {
504 g_mutex_lock(&handle->resources_lock);
505 g_mutex_unlock(&handles_lock);
506 for (j = 0; j < handle->resources->len; j++) {
507 resource = (mm_resource_manager_res_s*)handle->resources->pdata[j];
508 if (resource->type == type && resource->volume == volume) {
510 release_all = ((mm_resource_manager_release_cb)
511 handle->release_cb.cb)(
512 handle, resource, handle->release_cb.user_data);
514 __send_release_cb_sync(handle->id);
516 g_ptr_array_remove_index_fast(handle->resources, j);
520 g_mutex_unlock(&handle->resources_lock);
523 if (_mm_resource_manager_mark_all_for_release(handle) == MM_RESOURCE_MANAGER_ERROR_NONE
524 && _mm_resource_manager_commit(handle) == MM_RESOURCE_MANAGER_ERROR_NONE) {
525 MM_RM_DEBUG("All resources are released after release cb");
527 MM_RM_ERROR("Resources cannot be released after release cb");
531 g_mutex_unlock(&handles_lock);
535 void __mm_resource_manager_status_callback(mm_resource_manager_s *handle,
536 mm_resource_manager_status_e status)
538 g_mutex_lock(&handle->resources_lock);
539 g_mutex_unlock(&handles_lock);
540 if (handle->status_cb.cb) {
541 ((mm_resource_manager_status_cb)handle->status_cb.cb)(handle, status,
542 handle->status_cb.user_data);
544 g_mutex_unlock(&handle->resources_lock);
548 static int __check_resource(mm_resource_manager_s *rm,
549 mm_resource_manager_res_type_e type,
550 mm_resource_manager_res_volume volume)
552 mm_resource_manager_res_volume remaining_local_volume =
553 rm->__max_resource_volumes[type];
554 mm_resource_manager_res_p i_res;
557 MM_RM_RETVM_IF(remaining_local_volume == MM_RESOURCE_MANAGER_NO_RES,
558 MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED,
559 "No resource for the platform");
562 MM_RM_RETVM_IF(remaining_local_volume < volume,
563 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
564 "Requested volume %d exceeds max value %d", volume,
565 remaining_local_volume);
566 for (i = 0; i < rm->resources->len; i++) {
567 i_res = (mm_resource_manager_res_p) rm->resources->pdata[i];
568 if (i_res->type == type &&
569 i_res->state != MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE &&
570 (i_res->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL ||
571 (remaining_local_volume -= i_res->volume) < volume)) {
572 MM_RM_ERROR("Requested volume %d exceeds remaining local volume %d",
574 i_res->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL ?
575 0 : remaining_local_volume);
576 return MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH;
581 return MM_RESOURCE_MANAGER_ERROR_NONE;
584 static int __create_resource(mm_resource_manager_s *rm,
585 mm_resource_manager_res_type_e type,
586 mm_resource_manager_res_volume volume, mm_resource_manager_res_p *res)
590 MM_RM_RETVM_IF(res == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
592 ret = __check_resource(rm, type, volume);
593 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
596 *res = g_new0(mm_resource_manager_res_s, 1);
598 (*res)->volume = volume;
600 return MM_RESOURCE_MANAGER_ERROR_NONE;
603 static void __destroy_resource(void *res)
608 static int __get_resource_index(mm_resource_manager_s *rm,
609 mm_resource_manager_res_p res)
613 for (i = 0; i < rm->resources->len; i++)
614 if (rm->resources->pdata[i] == (gpointer) res)
617 return MM_RESOURCE_MANAGER_RES_NOT_FOUND;
620 static gboolean __mark_resource_for_release(GPtrArray *resources, int index,
621 mm_resource_manager_res_p resource)
623 switch (resource->state) {
624 case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
625 g_ptr_array_remove_index_fast(resources, index);
626 MM_RM_DEBUG("Resource %p is removed implicitly", resource);
628 case MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED:
629 resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
631 case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
632 MM_RM_DEBUG("Resource %p is already marked", resource);
639 static gboolean __check_rm_handle(mm_resource_manager_s *handle)
643 for (i = 0; i < handles->len; i++)
644 if (g_ptr_array_index(handles, i) == handle)
649 static void __send_release_cb_sync(mm_resource_manager_id id)
653 sync_fd = open(RELEASE_CB_SYNC_PATH, O_WRONLY);
654 MM_RM_RETM_IF(sync_fd == -1, "Sync FIFO cannot be opened");
656 if (write(sync_fd, &id, sizeof(id)) == sizeof(id))
657 MM_RM_DEBUG("Sync message is sent successfully");
659 MM_RM_ERROR("Sync message cannot be sent");
664 static void __init_lib()
666 handles = g_ptr_array_sized_new(
667 MM_RESOURCE_MANAGER_RESERVED_HANDLE_ARRAY_SIZE);
668 MM_RM_RETM_IF(handles == NULL, "API lib cannot be initialized");
670 MM_RM_INFO("API lib is loaded");
673 static void __deinit_lib()
675 if (handles->len > 0) {
676 MM_RM_DEBUG("Handles array [%d] is not empty. It will be cleaned now.", handles->len);
677 while (handles->len > 0)
678 _mm_resource_manager_destroy(handles->pdata[0]);
681 g_ptr_array_free(handles, TRUE);
683 MM_RM_INFO("API lib is unloaded");
686 static int __dbus_init(mm_resource_manager_s *handle)
688 GError *error = NULL;
690 MM_RM_RETVM_IF(handle->dbus_proxy != NULL,
691 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
692 "Dbus proxy is not NULL");
694 g_main_context_push_thread_default(handle->dispatcher_context);
695 handle->dbus_proxy = mmresource_manager_proxy_new_for_bus_sync(
696 G_BUS_TYPE_SYSTEM, 0, RMD_GDBUS_NAME, RMD_GDBUS_PATH, NULL, &error);
697 g_main_context_pop_thread_default(handle->dispatcher_context);
698 MM_RM_RET_IF_GERR(error, "Dbus proxy cannot be created");
700 if (g_signal_connect(handle->dbus_proxy, "release_callback",
701 (GCallback)__dbus_release_callback, NULL) < 1 ||
702 g_signal_connect(handle->dbus_proxy, "status_callback",
703 (GCallback)__dbus_status_callback, NULL) < 1) {
705 g_object_unref(handle->dbus_proxy);
706 handle->dbus_proxy = NULL;
707 MM_RM_ERROR("Release or status callback signals cannot be connected");
709 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
712 return MM_RESOURCE_MANAGER_ERROR_NONE;
715 static int __dbus_deinit(mm_resource_manager_s *handle)
717 MM_RM_RETVM_IF(handle->dbus_proxy == NULL,
718 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Dbus proxy is NULL");
719 g_object_unref(handle->dbus_proxy);
720 handle->dbus_proxy = NULL;
721 return MM_RESOURCE_MANAGER_ERROR_NONE;
724 static int __dbus_init_conf(mm_resource_manager_s *handle)
727 GError *error = NULL;
728 int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
729 GVariant *max_volume = NULL;
730 GVariant *cond_volume = NULL;
732 GVariantIter volume_iter;
733 GVariantIter cond_volume_iter;
735 mmresource_manager_call_conf_sync(handle->dbus_proxy, &rm_error,
736 &max_volume, &cond_volume, NULL, &error);
737 MM_RM_RET_IF_GERR(error, "DBus conf msg cannot be sent");
739 MM_RM_RETVM_IF(max_volume == NULL || cond_volume == NULL,
740 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
741 "Variant data are empty");
743 if (g_variant_iter_init(&volume_iter, max_volume) ==
744 MM_RESOURCE_MANAGER_RES_TYPE_MAX) {
745 for (i = 0; g_variant_iter_next(&volume_iter, "i",
746 &handle->__max_resource_volumes[i]); i++);
747 g_variant_unref(max_volume);
749 g_variant_unref(max_volume);
750 g_variant_unref(cond_volume);
751 MM_RM_ERROR("Wrong max volume array size");
752 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
755 if (g_variant_iter_init(&volume_iter, cond_volume) ==
756 MM_RESOURCE_MANAGER_RES_TYPE_MAX) {
757 for (i = 0; (tmp = g_variant_iter_next_value(&volume_iter)) != NULL;
759 if (g_variant_iter_init(&cond_volume_iter, tmp) ==
760 MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX) {
761 for (j = 0; g_variant_iter_next(&cond_volume_iter, "i",
762 &handle->__condition_volumes[i][j]); j++);
763 g_variant_unref(tmp);
765 g_variant_unref(tmp);
766 MM_RM_ERROR("Wrong condition volume array size");
767 rm_error = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
771 g_variant_unref(cond_volume);
773 g_variant_unref(cond_volume);
774 MM_RM_ERROR("Wrong condition volume array size");
775 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
781 static int __dbus_create(mm_resource_manager_s *handle,
782 mm_resource_manager_app_class_e app_class)
784 GError *error = NULL;
785 int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
787 mmresource_manager_call_create_sync(handle->dbus_proxy, app_class, &handle->id,
788 &rm_error, NULL, &error);
789 MM_RM_RET_IF_GERR(error, "DBus create msg cannot be sent");
791 MM_RM_DEBUG("Create returned id - #%"PRIu64", error - %d",
792 _mm_rm_hash64(handle->id), rm_error);
797 static int __dbus_destroy(mm_resource_manager_s *handle)
799 GError *error = NULL;
800 int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
802 mmresource_manager_call_destroy_sync(handle->dbus_proxy, handle->id, &rm_error,
804 MM_RM_RET_IF_GERR(error, "DBus destroy msg cannot be sent");
806 MM_RM_DEBUG("Destroy for id - #%"PRIu64" returned error - %d", _mm_rm_hash64(handle->id), rm_error);
808 return MM_RESOURCE_MANAGER_ERROR_NONE;
811 static int __dbus_commit(mm_resource_manager_s *handle)
815 GVariantBuilder *release_builder;
816 GVariantBuilder *acquire_builder;
817 GVariant *flags_variant;
818 GVariantIter flags_iter;
819 mm_resource_manager_res_p resource;
823 GError *error = NULL;
824 int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
826 release_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
827 acquire_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
828 for (i = 0; i < handle->resources->len; i++) {
829 resource = (mm_resource_manager_res_p) handle->resources->pdata[i];
831 switch (resource->state) {
832 case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
833 g_variant_builder_add_value(acquire_builder, g_variant_new("(ii)",
834 resource->type, resource->volume));
837 case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
838 g_variant_builder_add_value(release_builder, g_variant_new("(ii)",
839 resource->type, resource->volume));
847 if (release_num + acquire_num == 0) {
848 g_variant_builder_unref(release_builder);
849 g_variant_builder_unref(acquire_builder);
850 MM_RM_DEBUG("There is nothing to commit - dbus request is not sent");
855 * Acquire and release arrays are ended with special element, because
856 * g_variant_builder_end crashes without at least one element
858 g_variant_builder_add_value(acquire_builder, g_variant_new("(ii)",
859 MM_RESOURCE_MANAGER_NO_RES, 0));
860 acquire = g_variant_builder_end(acquire_builder);
861 g_variant_builder_unref(acquire_builder);
863 g_variant_builder_add_value(release_builder, g_variant_new("(ii)",
864 MM_RESOURCE_MANAGER_NO_RES, 0));
865 release = g_variant_builder_end(release_builder);
866 g_variant_builder_unref(release_builder);
868 mmresource_manager_call_commit_sync(handle->dbus_proxy, handle->id, release,
869 acquire, &rm_error, &flags_variant, NULL, &error);
871 MM_RM_RET_IF_GERR(error, "DBus commit msg cannot be sent");
873 MM_RM_DEBUG("Commit for id - #%"PRIu64" returned error - %d",
874 _mm_rm_hash64(handle->id), rm_error);
876 if (rm_error == MM_RESOURCE_MANAGER_ERROR_NONE) {
877 for (i = 0; i < handle->resources->len; i++) {
878 resource = (mm_resource_manager_res_p) handle->resources->pdata[i];
880 switch (resource->state) {
881 case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
882 resource->state = MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED;
883 resource->is_acquire_failed = FALSE;
885 case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
886 g_ptr_array_remove_index_fast(handle->resources, i--);
892 } else if (rm_error == MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY) {
893 g_variant_iter_init(&flags_iter, flags_variant);
895 for (i = 0; i < handle->resources->len; i++) {
896 resource = (mm_resource_manager_res_p) handle->resources->pdata[i];
898 if (resource->state == MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE)
899 g_variant_iter_next(&flags_iter, "b", &resource->is_acquire_failed);
903 g_variant_unref(flags_variant);
908 static void __dbus_release_callback(MMResourceManager *object, guint64 arg_id,
909 gint arg_resource_type, gint arg_volume)
911 mm_resource_manager_s *handle;
912 gboolean unlock = TRUE;
915 g_mutex_lock(&handles_lock);
916 for (i = 0; i < handles->len; i++) {
917 handle = (mm_resource_manager_s*)handles->pdata[i];
918 if (handle->dbus_proxy == object) {
919 __mm_resource_manager_release_callback(handle, arg_id,
920 arg_resource_type, arg_volume);
927 g_mutex_unlock(&handles_lock);
930 static void __dbus_status_callback(MMResourceManager *object, gint arg_status)
932 mm_resource_manager_s *handle;
933 gboolean unlock = TRUE;
936 g_mutex_lock(&handles_lock);
937 for (i = 0; i < handles->len; i++) {
938 handle = (mm_resource_manager_s*)handles->pdata[i];
939 if (handle->dbus_proxy == object) {
940 __mm_resource_manager_status_callback(handle, arg_status);
947 g_mutex_unlock(&handles_lock);
950 static gpointer __dispatcher_thread(gpointer user_data)
952 GMainLoop *ml = (GMainLoop *) user_data;
956 MM_RM_INFO("main loop %p quit", ml);
962 static void __destroy_dispatcher(mm_resource_manager_s *handle)
964 if (__dbus_deinit(handle) != MM_RESOURCE_MANAGER_ERROR_NONE)
965 MM_RM_ERROR("Error while dbus deinitializing");
967 if (handle->dispatcher_loop) {
968 if (g_main_loop_is_running(handle->dispatcher_loop)) {
969 MM_RM_INFO("mainloop %p is running", handle->dispatcher_loop);
970 g_main_loop_quit(handle->dispatcher_loop);
972 g_main_loop_unref(handle->dispatcher_loop);
973 handle->dispatcher_loop = NULL;
976 if (handle->dispatcher_thread) {
977 g_thread_join(handle->dispatcher_thread);
978 MM_RM_INFO("dispatcher thread join %p", handle->dispatcher_thread);
979 handle->dispatcher_thread = NULL;
982 if (handle->dispatcher_context) {
983 g_main_context_unref(handle->dispatcher_context);
984 handle->dispatcher_context = NULL;