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.
19 #include <murphy/common/mainloop.h>
20 #include <murphy/plugins/resource-native/libmurphy-resource/resource-api.h>
22 #include "common/mm_resource_manager_utils.h"
23 #include "daemon/backend/murphy/mm_resource_manager_mloop.h"
24 #include "daemon/backend/murphy/mm_resource_manager_rset.h"
28 static const char* state_str[MRP_RES_RESOURCE_ABOUT_TO_LOOSE + 1] = {
38 static void _mm_resource_manager_rset_state_callback(mrp_res_context_t *cx,
39 const mrp_res_resource_set_t *rs, void *user_data);
40 static void _mm_resource_manager_rset_release_cb(mrp_res_context_t *cx,
41 const mrp_res_resource_set_t *rs, void *user_data);
43 #define RM_RESOURCE_TIMEOUT 5
45 int _mm_resource_manager_rset_create(mm_resource_manager_app_class_e app_class,
46 mm_resource_manager_mloop_s *mrp, mm_resource_manager_rset_s **rset)
48 mm_resource_manager_rset_s *handle = NULL;
50 handle = (mm_resource_manager_rset_s *) calloc(1, sizeof(mm_resource_manager_rset_s));
51 MM_RM_RETVM_IF(NULL == handle, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
52 "Error allocating memory for Handle");
54 MM_RM_DEBUG("Creating rset with app_class %s",
55 _mm_resource_manager_get_app_class_str(app_class));
56 handle->mrp_rset = mrp_res_create_resource_set(mrp->mrp_ctx,
57 _mm_resource_manager_get_app_class_str(app_class),
58 _mm_resource_manager_rset_state_callback, handle);
60 if (!handle->mrp_rset) {
61 MM_RM_ERROR("Failed to create rset");
62 _mm_resource_manager_rset_destroy(handle);
63 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
66 if (!mrp_res_set_autorelease(TRUE, handle->mrp_rset))
67 MM_RM_INFO("Failed to set autorelease flag");
69 g_mutex_init(&handle->lock);
70 g_cond_init(&handle->cond);
72 *rset = (mm_resource_manager_rset_s *) handle;
74 MM_RM_INFO("Successfully created resource set %p", handle);
76 return MM_RESOURCE_MANAGER_ERROR_NONE;
79 int _mm_resource_manager_rset_add_resource(mm_resource_manager_rset_s *rset,
80 mm_resource_manager_res_type_e type)
82 mrp_res_resource_t *resource = NULL;
84 g_mutex_lock(&rset->lock);
86 resource = mrp_res_create_resource(rset->mrp_rset,
87 _mm_resource_manager_get_res_str(type), TRUE, FALSE);
90 MM_RM_ERROR("Failed to create resource type %d [%s]", type,
91 _mm_resource_manager_get_res_str(type));
92 g_mutex_unlock(&rset->lock);
93 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
96 if (!mrp_res_set_release_callback(rset->mrp_rset, _mm_resource_manager_rset_release_cb, rset)) {
97 MM_RM_ERROR("Failed to set release callback for rset %p", rset);
98 g_mutex_unlock(&rset->lock);
99 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
102 MM_RM_INFO("Successfully added resource type %d [%s]", type,
103 _mm_resource_manager_get_res_str(type));
107 g_mutex_unlock(&rset->lock);
109 return MM_RESOURCE_MANAGER_ERROR_NONE;
112 int _mm_resource_manager_rset_set_release_cb(mm_resource_manager_rset_s *rset,
113 mm_resource_manager_rset_release_cb release_cb, void *user_data)
115 g_mutex_lock(&rset->lock);
117 rset->release_cb = release_cb;
118 rset->user_data = user_data;
120 g_mutex_unlock(&rset->lock);
122 return MM_RESOURCE_MANAGER_ERROR_NONE;
125 int _mm_resource_manager_rset_acquire(mm_resource_manager_rset_s *rset)
127 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
129 g_mutex_lock(&rset->lock);
131 /* Skip if resource was already acquired */
132 if (MRP_RES_RESOURCE_ACQUIRED == rset->mrp_rset->state) {
133 MM_RM_DEBUG("rset %p already acquired", rset);
134 g_mutex_unlock(&rset->lock);
135 return MM_RESOURCE_MANAGER_ERROR_NONE;
138 if (mrp_res_acquire_resource_set(rset->mrp_rset)) {
139 MM_RM_ERROR("Failed to acquire rset %p", rset);
140 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
143 gint64 end_time = g_get_monotonic_time() + RM_RESOURCE_TIMEOUT * G_TIME_SPAN_SECOND;
144 MM_RM_DEBUG("Waiting for aquire rset %p...", rset);
145 if (!g_cond_wait_until(&rset->cond, &rset->lock, end_time)) {
146 MM_RM_ERROR("Could not acquire rset %p", rset);
147 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
149 if (rset->mrp_rset->state == MRP_RES_RESOURCE_LOST) {
150 MM_RM_INFO("Could not acquire rset %p. Priority is too low.", rset);
151 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
153 MM_RM_INFO("Acquired rset %p", rset);
154 ret = MM_RESOURCE_MANAGER_ERROR_NONE;
158 g_mutex_unlock(&rset->lock);
163 int _mm_resource_manager_rset_release(mm_resource_manager_rset_s *rset)
165 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
167 g_mutex_lock(&rset->lock);
169 if (MRP_RES_RESOURCE_ACQUIRED != rset->mrp_rset->state) {
170 MM_RM_DEBUG("Don't need to release rset %p. Wrong state %d", rset, rset->mrp_rset->state);
171 g_mutex_unlock(&rset->lock);
172 return MM_RESOURCE_MANAGER_ERROR_NONE;
175 if (mrp_res_release_resource_set(rset->mrp_rset)) {
176 MM_RM_ERROR("Could not release rset %p", rset);
177 g_mutex_unlock(&rset->lock);
178 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
181 gint64 end_time = g_get_monotonic_time() + RM_RESOURCE_TIMEOUT * G_TIME_SPAN_SECOND;
182 MM_RM_DEBUG("Waiting for release rset %p...", rset);
183 if (!g_cond_wait_until(&rset->cond, &rset->lock, end_time)) {
184 MM_RM_ERROR("Could not release rset %p", rset);
185 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
187 MM_RM_INFO("Released rset %p", rset);
188 ret = MM_RESOURCE_MANAGER_ERROR_NONE;
191 g_mutex_unlock(&rset->lock);
196 int _mm_resource_manager_rset_destroy(mm_resource_manager_rset_s *rset)
198 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
200 MM_RM_RETVM_IF(NULL == rset, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "rset is NULL");
202 g_mutex_lock(&rset->lock);
204 if (rset->mrp_rset) {
205 /* We will release rset automatically if resource was acquired */
206 if (MRP_RES_RESOURCE_ACQUIRED == rset->state) {
207 if (mrp_res_release_resource_set(rset->mrp_rset))
208 MM_RM_ERROR("Failed to release rset %p", rset->mrp_rset);
210 gint64 end_time = g_get_monotonic_time() + RM_RESOURCE_TIMEOUT * G_TIME_SPAN_SECOND;
211 MM_RM_DEBUG("Waiting for release rset...");
212 if (!g_cond_wait_until(&rset->cond, &rset->lock, end_time)) {
213 MM_RM_ERROR("Timeout elapsed");
214 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
216 MM_RM_INFO("Released rset %p", rset);
217 ret = MM_RESOURCE_MANAGER_ERROR_NONE;
221 mrp_res_delete_resource_set(rset->mrp_rset);
222 rset->mrp_rset = NULL;
225 g_mutex_unlock(&rset->lock);
226 g_mutex_clear(&rset->lock);
227 g_cond_clear(&rset->cond);
229 MM_RM_DEBUG("rset %p destroyed", rset);
236 static void _mm_resource_manager_rset_release_cb(mrp_res_context_t *cx,
237 const mrp_res_resource_set_t *rs, void *user_data)
239 mm_resource_manager_rset_s *rset = NULL;
242 MM_RM_ERROR("user data must be not NULL");
246 rset = (mm_resource_manager_rset_s *) user_data;
247 MM_RM_INFO("Release callback was triggered for rset %p", rset);
249 g_mutex_lock(&rset->lock);
251 if (rset->release_cb)
252 rset->release_cb(rset->type, rset->user_data);
254 g_mutex_unlock(&rset->lock);
257 static void _mm_resource_manager_rset_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
260 mrp_res_resource_t *res = NULL;
261 mm_resource_manager_rset_s *rset = (mm_resource_manager_rset_s *) user_data;
263 g_mutex_lock(&rset->lock);
265 if (!mrp_res_equal_resource_set(rs, rset->mrp_rset)) {
266 MM_RM_INFO("rset (%p) from callback is not same as current rset internal %p", rs, rset->mrp_rset);
267 g_mutex_unlock(&rset->lock);
271 MM_RM_INFO(" - resource set state (%p) is changed to [%s]", rs, state_str[rs->state]);
272 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
273 res = mrp_res_get_resource_by_name(rs, _mm_resource_manager_get_res_str(i));
275 MM_RM_INFO(" -- %s not present in resource set", _mm_resource_manager_get_res_str(i));
277 MM_RM_INFO(" -- resource name [%s] -> [%s]'", res->name, state_str[res->state]);
280 mrp_res_delete_resource_set(rset->mrp_rset);
281 rset->mrp_rset = mrp_res_copy_resource_set(rs);
284 case MRP_RES_RESOURCE_ACQUIRED:
285 MM_RM_INFO("rset (%p) is acquired", rset);
286 g_cond_signal(&rset->cond);
288 case MRP_RES_RESOURCE_AVAILABLE:
289 MM_RM_INFO("rset (%p) is released", rset);
290 g_cond_signal(&rset->cond);
292 case MRP_RES_RESOURCE_LOST:
293 MM_RM_INFO("rset (%p) cannot be acquired", rset);
294 g_cond_signal(&rset->cond);
297 MM_RM_ERROR("rset (%p). Invalid state.", rset);
300 rset->state = rs->state;
301 g_mutex_unlock(&rset->lock);