4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
8 * Cherepanov Vitaliy <v.cherepanov@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
23 * - Samsung RnD Institute Russia
27 // TODO check memory (malloc, free)
30 #include <sys/types.h>
33 #include "da_protocol.h"
34 #include "da_protocol_inst.h"
38 struct lib_list_t *new_lib_inst_list = NULL;
40 uint32_t app_count = 0;
41 char *packed_app_list = NULL;
42 char *packed_lib_list = NULL;
46 //----------------------------------- lists ----------------------------------
48 static int data_list_add_probe_to_hash(struct data_list_t *to, struct probe_list_t *probe)
54 // create hash for lib
55 static int data_list_make_hash(struct data_list_t *what)
57 struct probe_list_t *p;
59 for (p = what->list; p != NULL; p = p->next)
60 data_list_add_probe_to_hash(what, p);
64 //------------ create - destroy
65 static struct data_list_t *new_data(void)
67 struct data_list_t *lib = malloc(sizeof(*lib));
76 struct lib_list_t *new_lib(void)
78 struct lib_list_t *lib = (struct lib_list_t *)new_data();
79 lib->lib = malloc(sizeof(*lib->lib));
80 memset(lib->lib, 0, sizeof(*lib->lib));
84 struct app_list_t *new_app(void)
86 struct app_list_t *app = (struct app_list_t *)new_data();
87 app->app = malloc(sizeof(*app->app));
88 memset(app->app, 0, sizeof(*app->app));
92 struct probe_list_t *new_probe(void)
94 struct probe_list_t *probe = malloc(sizeof(*probe));
102 static void free_probe_element(struct probe_list_t *probe)
108 static void free_data_element(struct data_list_t *lib)
113 static void free_probe_list(struct probe_list_t *probe)
115 struct probe_list_t *next;
116 while (probe != NULL) {
118 free_probe_element(probe);
123 static void free_data(struct data_list_t *lib)
125 free_probe_list(lib->list);
126 free_data_element(lib);
129 void free_data_list(struct data_list_t **data)
131 while (*data != NULL) {
132 struct data_list_t *next = (*data)->next;
138 //------------- add - remove
139 int data_list_append(struct data_list_t **to, struct data_list_t *from)
141 struct data_list_t *p = NULL;
148 from->next = (void *)p;
149 p->prev = (void *)from;
155 static int data_list_append_probes_hash(struct data_list_t *to, struct data_list_t *from)
157 struct probe_list_t *p = from->list;
158 struct probe_list_t *last = p;
161 to->func_num += from->func_num;
162 for (p = from->list; p != NULL; p = p->next) {
163 data_list_add_probe_to_hash(to, p);
167 last->next = to->list;
168 to->list->prev = last;
169 to->list = from->list;
174 int probe_list_append(struct data_list_t *to, struct probe_list_t *from)
176 struct probe_list_t **list = &(to->list);
177 struct probe_list_t *p = NULL;
185 from->next = (void *)p;
186 p->prev = (void *)from;
188 to->size += from->size;
191 for (p = from; p != NULL; p = p->next)
197 static struct probe_list_t *probe_list_rm_element(struct data_list_t *list, struct probe_list_t *element)
199 struct probe_list_t *prev = element->prev;
200 struct probe_list_t *next = element->next;
201 if (element != NULL) {
203 // prev != null, next == null
204 // prev != null, next != null
207 // prev == null, next == null
208 // prev == null, next != null
214 list->size -= element->size;
218 free_probe_element(element);
222 static struct data_list_t *data_list_unlink_data(struct data_list_t **list, struct data_list_t *element)
224 struct data_list_t *prev = element->prev;
225 struct data_list_t *next = element->next;
226 if (element != NULL) {
228 // prev != null, next == null
229 // prev != null, next != null
232 // prev == null, next == null
233 // prev == null, next != null
237 next->prev = (struct lib_list_t *)prev;
240 element->prev = NULL;
241 element->next = NULL;
246 static struct data_list_t *data_list_rm_data(struct data_list_t **list, struct data_list_t *element)
248 struct data_list_t *next = NULL;
250 next = data_list_unlink_data(list, element);
251 free_data_element(element);
257 static struct data_list_t *data_list_find_data(struct data_list_t *whered, struct data_list_t *whatd, cmp_data_f cmp)
259 struct data_list_t *where;
260 struct data_list_t *what = whatd;
261 for (where = whered; where != NULL; where = where->next) {
262 if (where->hash == what->hash) {
263 if (cmp(where, what))
270 static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
272 struct probe_list_t *p ;
273 for (p = where->list; p != NULL; p = p->next)
274 if (p->size == probe->size)
275 if (p->func->func_addr == probe->func->func_addr)
276 if (strcmp(p->func->args, probe->func->args) == 0)
282 // "from" will be destroyed after this call
283 static int data_list_move_with_hash(struct data_list_t **to, struct data_list_t **from, cmp_data_f cmp)
286 struct data_list_t *p = *from;
287 struct data_list_t *next = NULL;
288 struct data_list_t *sch = NULL;
290 sch = data_list_find_data(*to, p, cmp);
291 next = data_list_unlink_data(from, p);
293 data_list_make_hash(p);
294 data_list_append(to, p);
296 data_list_append_probes_hash(sch, p);
303 //---------------------------- collisions resolve ------------------------------
305 static int cmp_libs(struct data_list_t *el_1, struct data_list_t *el_2)
308 ((struct lib_list_t *)el_1)->lib->bin_path,
309 ((struct lib_list_t *)el_2)->lib->bin_path
313 ///////////////////////////////////////////////////////////////////////////
314 // function removes from new list all probes which are already installed
316 // cur - current state (lib list with probes)
317 // new - additional probes which were received with MSG_SWAP_INST_ADD msg
318 // (lib list with probes)
319 // this function removes all probes which are present in cur and new list from
320 // new list so after this function call in new list will be only probes which are
321 // not present in cur list
322 static int resolve_collisions_for_add_msg(struct lib_list_t **cur, struct lib_list_t **new)
324 struct data_list_t *p = (struct data_list_t *)*new;
325 struct data_list_t *sch = NULL;
327 struct probe_list_t *pr = NULL;
328 struct probe_list_t *next_pr = NULL;
330 // remove collisions from list "new"
332 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
334 // lib not found in cur config
336 // lib found in cur config so resolve collisions
340 if (find_probe(sch, pr) != NULL) {
341 // probe already exist
342 // rm from new config
343 next_pr = probe_list_rm_element(p, pr);
350 // rm lib if it is empty
351 if (p->list == NULL) {
352 p = data_list_rm_data((struct data_list_t **)new, p);
361 ///////////////////////////////////////////////////////////////////////////
362 // function removes from cur list all probes which are in list "new"
363 // and removes from "new" all probes which are not instaled
365 // cur - current state (lib list with probes)
366 // new - list for probes remove which were received with MSG_SWAP_INST_REMOVE msg
368 // this function removes all probes which are present in cur and new list from
369 // cur list and removes all probes which are present in new but not present in
370 // cur list so after this function call in new list will be only probes which are
371 // present in cur list
372 static int resolve_collisions_for_rm_msg(struct lib_list_t **cur, struct lib_list_t **new)
374 struct data_list_t *p = (struct data_list_t *)*new;
375 struct data_list_t *next_l = NULL;
376 struct data_list_t *sch = NULL;
378 struct probe_list_t *pr = NULL;
379 struct probe_list_t *next_pr = NULL;
380 struct probe_list_t *tmp = NULL;
382 // remove collisions from list "new"
384 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
386 //lib not found so no probes remove
387 next_l = data_list_rm_data((struct data_list_t **)new, p);
389 //lib found so we need remove collisions
392 // if rm probe list is empty that is mean we need
393 // to remove all probes on this lib
394 data_list_unlink_data((struct data_list_t **)cur, sch);
395 data_list_append((struct data_list_t **)new, sch);
396 next_l = data_list_rm_data((struct data_list_t **)cur, p);
398 // lib is not empty so merge
401 if ((tmp = find_probe(sch, pr)) != NULL) {
402 // probe found so remove probe
404 probe_list_rm_element(sch, tmp);
407 // probe no found so remove it
409 next_pr = probe_list_rm_element(p, pr);
413 // rm lib if it is empty
414 if (sch->list == NULL) {
415 data_list_rm_data((struct data_list_t **)cur, sch);
425 //--------------------------------------pack ----------------------------------
427 static char *pack_lib_head_to_array(char *to, void *data)
429 struct us_lib_inst_t *lib = data;
430 pack_str(to, lib->bin_path);
434 static char *pack_app_head_to_array(char *to, void *data)
436 struct app_info_t *app = data;
437 pack_int32(to, app->app_type);
438 pack_str(to, app->app_id);
439 pack_str(to, app->exe_path);
443 static char *pack_data_to_array(struct data_list_t *data, char *to, pack_head_t pack_head)
445 struct probe_list_t *p;
447 to = pack_head(to, data->data);
448 pack_int32(to, data->func_num);
449 for (p = data->list; p != NULL; p = p->next) {
450 memcpy(to, p->func, p->size);
456 static char *pack_data_list_to_array(struct data_list_t *list, uint32_t *len, uint32_t *count, pack_head_t pack)
462 struct data_list_t *p = list;
464 for (p = list; p != NULL; p = p->next) {
469 size += sizeof(uint32_t);
477 memset(to, '*', size);
479 for (p = list; p != NULL; p = p->next)
480 to = pack_data_to_array(p, to, pack);
482 LOGE("can not malloc buffer for data list packing\n");
488 static char *pack_lib_list_to_array(struct lib_list_t *list, uint32_t *size, uint32_t *count)
490 return pack_data_list_to_array((struct data_list_t *)list, size,
491 count, pack_lib_head_to_array);
494 static char *pack_app_list_to_array(struct app_list_t *list, uint32_t *size, uint32_t *count)
496 return pack_data_list_to_array((struct data_list_t *)list, size,
497 count, pack_app_head_to_array);
500 static int generate_msg(struct msg_t **msg, struct lib_list_t *lib_list, struct app_list_t *app_list)
510 packed_lib_list = pack_lib_list_to_array(lib_list, &libs_size, &libs_count);
511 // print_buf(packed_lib_list, libs_size, "LIBS");
513 packed_app_list = pack_app_list_to_array(app_list, &apps_size, &apps_count);
514 // print_buf(packed_app_list, apps_size, "APPS");
516 size = apps_count * libs_size + apps_size;
518 LOGI("size = %d, apps= %d, libs = %d\n", size, apps_count, libs_count);
521 *msg = malloc(size + sizeof(**msg));
522 memset(*msg, '*', size);
525 pack_int32(p, 0); // msg id
526 pack_int32(p, size); // payload size
527 pack_int32(p, apps_count);
529 struct app_list_t *app = app_list;
530 char *app_p = packed_app_list + sizeof(((struct user_space_inst_t *)0)->app_num);
532 for (i = 0; i < apps_count; i++) {
533 memcpy(p, app_p, app->size);
535 memcpy(p, packed_lib_list, libs_size);
542 // print_buf((char *)*msg, size, "ANSWER");
546 //-----------------------------------------------------------------------------
547 struct app_info_t *app_info_get_first(struct app_list_t **app_list)
549 *app_list = prof_session.user_space_inst.app_inst_list;
550 if (*app_list == NULL) {
554 return (*app_list)->app;
557 struct app_info_t *app_info_get_next(struct app_list_t **app_list)
559 if (*app_list == NULL)
562 if ((*app_list = (*app_list)->next) == NULL)
565 return (*app_list)->app;
568 //-----------------------------------------------------------------------------
569 int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
570 struct msg_t **msg, enum ErrorCode *err)
574 if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
575 *err = ERR_WRONG_MESSAGE_FORMAT;
576 LOGE("parse app inst\n");
580 generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
584 pack_int32(p, NMSG_START);
586 *err = ERR_CANNOT_START_PROFILING;
592 int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
593 struct msg_t **msg, enum ErrorCode *err)
595 uint32_t lib_num = 0;
600 if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
601 *err = ERR_WRONG_MESSAGE_FORMAT;
602 LOGE("parse lib inst list fail\n");
605 // rm probes from new if its presents in cur
606 if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
607 LOGE("resolve collision\n");
611 // generate msg to send
612 if (us_inst->app_inst_list != NULL) {
613 generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list);
615 pack_int32(p, NMSG_SWAP_INST_ADD);
617 // apply changes to cur state
618 if (!data_list_move_with_hash(
619 (struct data_list_t **)&us_inst->lib_inst_list,
620 (struct data_list_t **)&new_lib_inst_list,
628 free_data_list((struct data_list_t **)&new_lib_inst_list);
629 new_lib_inst_list = NULL;
634 int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
635 struct msg_t **msg, enum ErrorCode *err)
637 uint32_t lib_num = 0;
641 if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
642 *err = ERR_WRONG_MESSAGE_FORMAT;
643 LOGE("parse lib inst\n");
647 if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
648 LOGE("resolve collisions\n");
652 if (us_inst->app_inst_list != NULL) {
653 if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
654 LOGE("generate msg\n");
658 pack_int32(p, NMSG_SWAP_INST_ADD);
661 free_data_list((struct data_list_t **)&new_lib_inst_list);
662 new_lib_inst_list = NULL;