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 [%s]", rset, _mm_resource_manager_get_res_str(rset->type));
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;
241 MM_RM_RETM_IF(NULL == user_data, "user data must be not NULL");
243 rset = (mm_resource_manager_rset_s *) user_data;
244 MM_RM_INFO("Release callback was triggered for rset %p", rset);
246 g_mutex_lock(&rset->lock);
248 if (rset->release_cb)
249 rset->release_cb(rset->type, rset->user_data);
251 g_mutex_unlock(&rset->lock);
254 static void _mm_resource_manager_rset_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
257 mrp_res_resource_t *res = NULL;
258 mm_resource_manager_rset_s *rset = (mm_resource_manager_rset_s *) user_data;
260 g_mutex_lock(&rset->lock);
262 if (!mrp_res_equal_resource_set(rs, rset->mrp_rset)) {
263 MM_RM_INFO("rset (%p) from callback is not same as current rset internal %p", rs, rset->mrp_rset);
264 g_mutex_unlock(&rset->lock);
268 MM_RM_INFO(" -- resource set state (%p) is changed to [%s]", rs, state_str[rs->state]);
269 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
270 res = mrp_res_get_resource_by_name(rs, _mm_resource_manager_get_res_str(i));
272 MM_RM_INFO(" -- %s not present in resource set", _mm_resource_manager_get_res_str(i));
274 MM_RM_INFO(" -- resource name [%s] -> [%s]'", res->name, state_str[res->state]);
277 mrp_res_delete_resource_set(rset->mrp_rset);
278 rset->mrp_rset = mrp_res_copy_resource_set(rs);
281 case MRP_RES_RESOURCE_ACQUIRED:
282 MM_RM_INFO("rset (%p) is acquired", rset);
283 g_cond_signal(&rset->cond);
285 case MRP_RES_RESOURCE_AVAILABLE:
286 MM_RM_INFO("rset (%p) is released", rset);
287 g_cond_signal(&rset->cond);
289 case MRP_RES_RESOURCE_LOST:
290 MM_RM_INFO("rset (%p) cannot be acquired", rset);
291 g_cond_signal(&rset->cond);
294 MM_RM_ERROR("rset (%p). Invalid state.", rset);
297 rset->state = rs->state;
298 g_mutex_unlock(&rset->lock);