Add new api of stream and instance for multi-instance
[platform/core/multimedia/mm-resource-manager.git] / src / daemon / backend / murphy / mm_resource_manager_rset.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <glib.h>
18 #include <inttypes.h>
19 #include <murphy/common/mainloop.h>
20 #include <murphy/plugins/resource-native/libmurphy-resource/resource-api.h>
21
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"
25
26
27
28 static const char* state_str[MRP_RES_RESOURCE_ABOUT_TO_LOOSE + 1] = {
29         "lost",
30         "pending",
31         "acquired",
32         "available",
33         "about_to_loose",
34 };
35
36
37
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);
42
43 #define RM_RESOURCE_TIMEOUT 5
44
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)
47 {
48         mm_resource_manager_rset_s *handle = NULL;
49
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");
53
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);
59
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;
64         }
65
66         if (!mrp_res_set_autorelease(TRUE, handle->mrp_rset))
67                 MM_RM_INFO("Failed to set autorelease flag");
68
69         g_mutex_init(&handle->lock);
70         g_cond_init(&handle->cond);
71
72         *rset = (mm_resource_manager_rset_s *) handle;
73
74         MM_RM_INFO("Successfully created resource set %p", handle);
75
76         return MM_RESOURCE_MANAGER_ERROR_NONE;
77 }
78
79 int _mm_resource_manager_rset_add_resource(mm_resource_manager_rset_s *rset,
80         mm_resource_manager_res_type_e type)
81 {
82         mrp_res_resource_t *resource = NULL;
83
84         g_mutex_lock(&rset->lock);
85
86         resource = mrp_res_create_resource(rset->mrp_rset,
87                         _mm_resource_manager_get_res_str(type), TRUE, FALSE);
88
89         if (!resource) {
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;
94         }
95
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;
100         }
101
102         MM_RM_INFO("Successfully added resource type %d [%s]", type,
103                         _mm_resource_manager_get_res_str(type));
104
105         rset->type = type;
106
107         g_mutex_unlock(&rset->lock);
108
109         return MM_RESOURCE_MANAGER_ERROR_NONE;
110 }
111
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)
114 {
115         g_mutex_lock(&rset->lock);
116
117         rset->release_cb = release_cb;
118         rset->user_data = user_data;
119
120         g_mutex_unlock(&rset->lock);
121
122         return MM_RESOURCE_MANAGER_ERROR_NONE;
123 }
124
125 int _mm_resource_manager_rset_acquire(mm_resource_manager_rset_s *rset)
126 {
127         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
128
129         g_mutex_lock(&rset->lock);
130
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;
136         }
137
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;
141         }
142
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;
148         } else {
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;
152                 } else {
153                         MM_RM_INFO("Acquired rset %p", rset);
154                         ret = MM_RESOURCE_MANAGER_ERROR_NONE;
155                 }
156         }
157
158         g_mutex_unlock(&rset->lock);
159
160         return ret;
161 }
162
163 int _mm_resource_manager_rset_release(mm_resource_manager_rset_s *rset)
164 {
165         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
166
167         g_mutex_lock(&rset->lock);
168
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;
173         }
174
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;
179         }
180
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;
186         } else {
187                 MM_RM_INFO("Released rset %p", rset);
188                 ret = MM_RESOURCE_MANAGER_ERROR_NONE;
189         }
190
191         g_mutex_unlock(&rset->lock);
192
193         return ret;
194 }
195
196 int _mm_resource_manager_rset_destroy(mm_resource_manager_rset_s *rset)
197 {
198         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
199
200         MM_RM_RETVM_IF(NULL == rset, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "rset is NULL");
201
202         g_mutex_lock(&rset->lock);
203
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);
209
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;
215                         } else {
216                                 MM_RM_INFO("Released rset %p [%s]", rset, _mm_resource_manager_get_res_str(rset->type));
217                                 ret = MM_RESOURCE_MANAGER_ERROR_NONE;
218                         }
219                 }
220
221                 mrp_res_delete_resource_set(rset->mrp_rset);
222                 rset->mrp_rset = NULL;
223         }
224
225         g_mutex_unlock(&rset->lock);
226         g_mutex_clear(&rset->lock);
227         g_cond_clear(&rset->cond);
228
229         MM_RM_DEBUG("rset %p destroyed", rset);
230
231         free(rset);
232
233         return ret;
234 }
235
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)
238 {
239         mm_resource_manager_rset_s *rset = NULL;
240
241         MM_RM_RETM_IF(NULL == user_data, "user data must be not NULL");
242
243         rset = (mm_resource_manager_rset_s *) user_data;
244         MM_RM_INFO("Release callback was triggered for rset %p", rset);
245
246         g_mutex_lock(&rset->lock);
247
248         if (rset->release_cb)
249                 rset->release_cb(rset->type, rset->user_data);
250
251         g_mutex_unlock(&rset->lock);
252 }
253
254 static void _mm_resource_manager_rset_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
255 {
256         int i = 0;
257         mrp_res_resource_t *res = NULL;
258         mm_resource_manager_rset_s *rset = (mm_resource_manager_rset_s *) user_data;
259
260         g_mutex_lock(&rset->lock);
261
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);
265                 return;
266         }
267
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));
271                 if (res == NULL)
272                         MM_RM_INFO(" -- %s not present in resource set", _mm_resource_manager_get_res_str(i));
273                 else
274                         MM_RM_INFO(" -- resource name [%s] -> [%s]'", res->name, state_str[res->state]);
275         }
276
277         mrp_res_delete_resource_set(rset->mrp_rset);
278         rset->mrp_rset = mrp_res_copy_resource_set(rs);
279
280         switch (rs->state) {
281         case MRP_RES_RESOURCE_ACQUIRED:
282                 MM_RM_INFO("rset (%p) is acquired", rset);
283                 g_cond_signal(&rset->cond);
284                 break;
285         case MRP_RES_RESOURCE_AVAILABLE:
286                 MM_RM_INFO("rset (%p) is released", rset);
287                 g_cond_signal(&rset->cond);
288                 break;
289         case MRP_RES_RESOURCE_LOST:
290                 MM_RM_INFO("rset (%p) cannot be acquired", rset);
291                 g_cond_signal(&rset->cond);
292                 break;
293         default:
294                 MM_RM_ERROR("rset (%p). Invalid state.", rset);
295         }
296
297         rset->state = rs->state;
298         g_mutex_unlock(&rset->lock);
299 }