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;
45 // ------------------ prints --------------
46 void print_probe_debug(struct probe_list_t *p)
48 LOGI(" size<%d> <0x%016llX, %s> <p=0x%08lX c=0x%08lX n=0x%08lX>\n",
52 (long unsigned int)p->prev,
54 (long unsigned int)p->next
58 void print_probe_inst_list(struct probe_list_t *list)
60 struct probe_list_t *p;
62 for (p = list; p != NULL; p = p->next)
66 void print_lib_inst_list(struct lib_list_t *list)
68 struct lib_list_t *p = list;
70 for (p = list; p != NULL; p = p->next) {
71 LOGI("lib <%s> size<%d> h0x%08lX\n",
74 (long unsigned int)p->hash);
75 print_probe_inst_list(p->list);
79 void print_app_inst_list(struct app_list_t *list)
82 for (p = list; p != NULL; p = p->next) {
83 LOGI("app <%s> size<%d> h0x%08lX\n",
86 (long unsigned int)p->hash);
87 print_probe_inst_list(p->list);
92 //----------------------------------- lists ----------------------------------
94 static int data_list_add_probe_to_hash(struct data_list_t *to, struct probe_list_t *probe)
100 // create hash for lib
101 static int data_list_make_hash(struct data_list_t *what)
103 struct probe_list_t *p;
105 for (p = what->list; p != NULL; p = p->next)
106 data_list_add_probe_to_hash(what, p);
110 //------------ create - destroy
111 struct data_list_t *new_data(void)
113 struct data_list_t *lib = malloc(sizeof(*lib));
122 struct lib_list_t *new_lib(void)
124 struct lib_list_t *lib = (struct lib_list_t *)new_data();
125 lib->lib = malloc(sizeof(*lib->lib));
126 memset(lib->lib, 0, sizeof(*lib->lib));
130 struct app_list_t *new_app(void)
132 struct app_list_t *app = (struct app_list_t *)new_data();
133 app->app = malloc(sizeof(*app->app));
134 memset(app->app, 0, sizeof(*app->app));
138 struct probe_list_t *new_probe(void)
140 struct probe_list_t *probe = malloc(sizeof(*probe));
148 static void free_probe_element(struct probe_list_t *probe)
154 static void free_data_element(struct data_list_t *lib)
159 static void free_probe_list(struct probe_list_t *probe)
161 struct probe_list_t *next;
162 while (probe != NULL) {
164 free_probe_element(probe);
169 void free_data(struct data_list_t *lib)
171 free_probe_list(lib->list);
172 free_data_element(lib);
175 void free_data_list(struct data_list_t **data)
177 while (*data != NULL) {
178 struct data_list_t *next = (*data)->next;
184 //------------- add - remove
185 int data_list_append(struct data_list_t **to, struct data_list_t *from)
187 struct data_list_t *p = NULL;
194 from->next = (void *)p;
195 p->prev = (void *)from;
201 static int data_list_append_probes_hash(struct data_list_t *to, struct data_list_t *from)
203 struct probe_list_t *p = from->list;
204 struct probe_list_t *last = p;
207 to->func_num += from->func_num;
208 for (p = from->list; p != NULL; p = p->next) {
209 data_list_add_probe_to_hash(to, p);
213 last->next = to->list;
214 to->list->prev = last;
215 to->list = from->list;
220 int probe_list_append(struct data_list_t *to, struct probe_list_t *from)
222 struct probe_list_t **list = &(to->list);
223 struct probe_list_t *p = NULL;
231 from->next = (void *)p;
232 p->prev = (void *)from;
234 to->size += from->size;
237 for (p = from; p != NULL; p = p->next)
243 static struct probe_list_t *probe_list_rm_element(struct data_list_t *list, struct probe_list_t *element)
245 struct probe_list_t *prev = element->prev;
246 struct probe_list_t *next = element->next;
247 if (element != NULL) {
249 // prev != null, next == null
250 // prev != null, next != null
253 // prev == null, next == null
254 // prev == null, next != null
260 list->size -= element->size;
264 free_probe_element(element);
268 static struct data_list_t *data_list_unlink_data(struct data_list_t **list, struct data_list_t *element)
270 struct data_list_t *prev = element->prev;
271 struct data_list_t *next = element->next;
272 if (element != NULL) {
274 // prev != null, next == null
275 // prev != null, next != null
278 // prev == null, next == null
279 // prev == null, next != null
283 next->prev = (struct lib_list_t *)prev;
286 element->prev = NULL;
287 element->next = NULL;
292 static struct data_list_t *data_list_rm_data(struct data_list_t **list, struct data_list_t *element)
294 struct data_list_t *next = NULL;
296 next = data_list_unlink_data(list, element);
297 free_data_element(element);
303 static struct data_list_t *data_list_find_data(struct data_list_t *whered, struct data_list_t *whatd, cmp_data_f cmp)
305 struct data_list_t *where;
306 struct data_list_t *what = whatd;
307 for (where = whered; where != NULL; where = where->next) {
308 if (where->hash == what->hash) {
309 if (cmp(where, what))
316 static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
318 struct probe_list_t *p ;
319 for (p = where->list; p != NULL; p = p->next)
320 if (p->size == probe->size)
321 if (p->func->func_addr == probe->func->func_addr)
322 if (strcmp(p->func->args, probe->func->args) == 0)
328 // "from" will be destroyed after this call
329 static int data_list_move_with_hash(struct data_list_t **to, struct data_list_t **from, cmp_data_f cmp)
332 struct data_list_t *p = *from;
333 struct data_list_t *next = NULL;
334 struct data_list_t *sch = NULL;
336 sch = data_list_find_data(*to, p, cmp);
337 next = data_list_unlink_data(from, p);
339 data_list_make_hash(p);
340 data_list_append(to, p);
342 data_list_append_probes_hash(sch, p);
349 //---------------------------- collisions resolve ------------------------------
351 static int cmp_libs(struct data_list_t *el_1, struct data_list_t *el_2)
354 ((struct lib_list_t *)el_1)->lib->bin_path,
355 ((struct lib_list_t *)el_2)->lib->bin_path
359 // this function for future use
360 static int cmp_apps(struct data_list_t *el_1, struct data_list_t *el_2)
363 ((struct app_list_t *)el_1)->app->exe_path,
364 ((struct app_list_t *)el_2)->app->exe_path
368 ///////////////////////////////////////////////////////////////////////////
369 // function removes from new list all probes which are already installed
371 // cur - current state (lib list with probes)
372 // new - additional probes which were received with MSG_SWAP_INST_ADD msg
373 // (lib list with probes)
374 // this function removes all probes which are present in cur and new list from
375 // new list so after this function call in new list will be only probes which are
376 // not present in cur list
377 static int resolve_collisions_for_add_msg(struct lib_list_t **cur, struct lib_list_t **new)
379 struct data_list_t *p = (struct data_list_t *)*new;
380 struct data_list_t *sch = NULL;
382 struct probe_list_t *pr = NULL;
383 struct probe_list_t *next_pr = NULL;
385 // remove collisions from list "new"
387 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
389 // lib not found in cur config
391 // lib found in cur config so resolve collisions
395 if (find_probe(sch, pr) != NULL) {
396 // probe already exist
397 // rm from new config
398 next_pr = probe_list_rm_element(p, pr);
405 // rm lib if it is empty
406 if (p->list == NULL) {
407 p = data_list_rm_data((struct data_list_t **)new, p);
416 ///////////////////////////////////////////////////////////////////////////
417 // function removes from cur list all probes which are in list "new"
418 // and removes from "new" all probes which are not instaled
420 // cur - current state (lib list with probes)
421 // new - list for probes remove which were received with MSG_SWAP_INST_REMOVE msg
423 // this function removes all probes which are present in cur and new list from
424 // cur list and removes all probes which are present in new but not present in
425 // cur list so after this function call in new list will be only probes which are
426 // present in cur list
427 static int resolve_collisions_for_rm_msg(struct lib_list_t **cur, struct lib_list_t **new)
429 struct data_list_t *p = (struct data_list_t *)*new;
430 struct data_list_t *next_l = NULL;
431 struct data_list_t *sch = NULL;
433 struct probe_list_t *pr = NULL;
434 struct probe_list_t *next_pr = NULL;
435 struct probe_list_t *tmp = NULL;
437 // remove collisions from list "new"
439 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
441 //lib not found so no probes remove
442 next_l = data_list_rm_data((struct data_list_t **)new, p);
444 //lib found so we need remove collisions
447 // if rm probe list is empty that is mean we need
448 // to remove all probes on this lib
449 data_list_unlink_data((struct data_list_t **)cur, sch);
450 data_list_append((struct data_list_t **)new, sch);
451 next_l = data_list_rm_data((struct data_list_t **)cur, p);
453 // lib is not empty so merge
456 if ((tmp = find_probe(sch, pr)) != NULL) {
457 // probe found so remove probe
459 probe_list_rm_element(sch, tmp);
462 // probe no found so remove it
464 next_pr = probe_list_rm_element(p, pr);
468 // rm lib if it is empty
469 if (sch->list == NULL) {
470 data_list_rm_data((struct data_list_t **)cur, sch);
480 //--------------------------------------pack ----------------------------------
482 static char *pack_lib_head_to_array(char *to, void *data)
484 struct us_lib_inst_t *lib = data;
485 pack_str(to, lib->bin_path);
489 static char *pack_app_head_to_array(char *to, void *data)
491 struct app_info_t *app = data;
492 pack_int32(to, app->app_type);
493 pack_str(to, app->app_id);
494 pack_str(to, app->exe_path);
498 static char *pack_data_to_array(struct data_list_t *data, char *to, pack_head_t pack_head)
500 struct probe_list_t *p;
502 to = pack_head(to, data->data);
503 pack_int32(to, data->func_num);
504 for (p = data->list; p != NULL; p = p->next) {
505 memcpy(to, p->func, p->size);
511 static char *pack_data_list_to_array(struct data_list_t *list, uint32_t *len, uint32_t *count, pack_head_t pack)
517 struct data_list_t *p = list;
519 for (p = list; p != NULL; p = p->next) {
524 size += sizeof(uint32_t);
532 memset(to, '*', size);
534 for (p = list; p != NULL; p = p->next)
535 to = pack_data_to_array(p, to, pack);
537 LOGE("can not malloc buffer for data list packing\n");
543 static char *pack_lib_list_to_array(struct lib_list_t *list, uint32_t *size, uint32_t *count)
545 return pack_data_list_to_array((struct data_list_t *)list, size,
546 count, pack_lib_head_to_array);
549 static char *pack_app_list_to_array(struct app_list_t *list, uint32_t *size, uint32_t *count)
551 return pack_data_list_to_array((struct data_list_t *)list, size,
552 count, pack_app_head_to_array);
555 static int generate_msg(struct msg_t **msg, struct lib_list_t *lib_list, struct app_list_t *app_list)
566 // print_lib_inst_list(lib_list);
567 packed_lib_list = pack_lib_list_to_array(lib_list, &libs_size, &libs_count);
568 // print_buf(packed_lib_list, libs_size, "LIBS");
570 packed_app_list = pack_app_list_to_array(app_list, &apps_size, &apps_count);
571 // print_buf(packed_app_list, apps_size, "APPS");
573 size = apps_count * libs_size + apps_size;
575 LOGI("size = %d, apps= %d, libs = %d\n", size, apps_count, libs_count);
578 *msg = malloc(size + sizeof(**msg));
579 memset(*msg, '*', size);
582 pack_int32(p, 0); // msg id
583 pack_int32(p, size); // payload size
584 pack_int32(p, apps_count);
586 struct app_list_t *app = app_list;
587 char *app_p = packed_app_list + sizeof(((struct user_space_inst_t *)0)->app_num);
589 for (i = 0; i < apps_count; i++) {
590 memcpy(p, app_p, app->size);
592 memcpy(p, packed_lib_list, libs_size);
599 // print_buf((char *)*msg, size, "ANSWER");
603 //-----------------------------------------------------------------------------
604 struct app_info_t *app_info_get_first(struct app_list_t **app_list)
606 *app_list = prof_session.user_space_inst.app_inst_list;
607 if (*app_list == NULL) {
611 return (*app_list)->app;
614 struct app_info_t *app_info_get_next(struct app_list_t **app_list)
616 if (*app_list == NULL)
619 if ((*app_list = (*app_list)->next) == NULL)
622 return (*app_list)->app;
625 //-----------------------------------------------------------------------------
626 int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
627 struct msg_t **msg, enum ErrorCode *err)
631 if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
632 *err = ERR_WRONG_MESSAGE_FORMAT;
633 LOGE("parse app inst\n");
636 // print_app_inst_list(app_inst_list);
637 generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
641 pack_int32(p, NMSG_START);
643 *err = ERR_CANNOT_START_PROFILING;
649 int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
650 struct msg_t **msg, enum ErrorCode *err)
652 uint32_t lib_num = 0;
657 if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
658 *err = ERR_WRONG_MESSAGE_FORMAT;
659 LOGE("parse lib inst list fail\n");
662 // rm probes from new if its presents in cur
663 if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
664 LOGE("resolve collision\n");
668 // generate msg to send
669 if (us_inst->app_inst_list != NULL) {
670 generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list);
672 pack_int32(p, NMSG_SWAP_INST_ADD);
674 // apply changes to cur state
675 if (!data_list_move_with_hash(
676 (struct data_list_t **)&us_inst->lib_inst_list,
677 (struct data_list_t **)&new_lib_inst_list,
685 free_data_list((struct data_list_t **)&new_lib_inst_list);
686 new_lib_inst_list = NULL;
691 int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
692 struct msg_t **msg, enum ErrorCode *err)
694 uint32_t lib_num = 0;
698 if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
699 *err = ERR_WRONG_MESSAGE_FORMAT;
700 LOGE("parse lib inst\n");
704 if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
705 LOGE("resolve collisions\n");
709 if (us_inst->app_inst_list != NULL) {
710 if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
711 LOGE("generate msg\n");
715 pack_int32(p, NMSG_SWAP_INST_ADD);
718 free_data_list((struct data_list_t **)&new_lib_inst_list);
719 new_lib_inst_list = NULL;