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>
31 #include <linux/limits.h>
34 #include "da_protocol.h"
35 #include "da_protocol_inst.h"
39 struct lib_list_t *new_lib_inst_list = NULL;
41 uint32_t app_count = 0;
42 char *packed_app_list = NULL;
43 char *packed_lib_list = NULL;
45 static struct _msg_target_t *lib_maps_message = NULL;
46 static pthread_mutex_t lib_inst_list_mutex = PTHREAD_MUTEX_INITIALIZER;
47 static pthread_mutex_t lib_maps_message_mutex = PTHREAD_MUTEX_INITIALIZER;
51 //----------------------------------- lists ----------------------------------
53 static int data_list_add_probe_to_hash(struct data_list_t *to, struct probe_list_t *probe)
59 // create hash for lib
60 static int data_list_make_hash(struct data_list_t *what)
62 struct probe_list_t *p;
64 for (p = what->list; p != NULL; p = p->next)
65 data_list_add_probe_to_hash(what, p);
69 //------------ create - destroy
70 static struct data_list_t *new_data(void)
72 struct data_list_t *lib = malloc(sizeof(*lib));
81 struct lib_list_t *new_lib(void)
83 struct lib_list_t *lib = (struct lib_list_t *)new_data();
84 lib->lib = malloc(sizeof(*lib->lib));
85 memset(lib->lib, 0, sizeof(*lib->lib));
89 struct app_list_t *new_app(void)
91 struct app_list_t *app = (struct app_list_t *)new_data();
92 app->app = malloc(sizeof(*app->app));
93 memset(app->app, 0, sizeof(*app->app));
97 struct probe_list_t *new_probe(void)
99 struct probe_list_t *probe = malloc(sizeof(*probe));
107 static void free_probe_element(struct probe_list_t *probe)
113 static void free_data_element(struct data_list_t *lib)
119 static void free_probe_list(struct probe_list_t *probe)
121 struct probe_list_t *next;
122 while (probe != NULL) {
124 free_probe_element(probe);
129 static void free_data(struct data_list_t *lib)
131 free_probe_list(lib->list);
132 free_data_element(lib);
135 void free_data_list(struct data_list_t **data)
137 struct data_list_t *next;
138 while (*data != NULL) {
139 next = (*data)->next;
145 //------------- add - remove
146 int data_list_append(struct data_list_t **to, struct data_list_t *from)
148 struct data_list_t *p = NULL;
155 from->next = (void *)p;
156 p->prev = (void *)from;
162 static int data_list_append_probes_hash(struct data_list_t *to, struct data_list_t *from)
164 struct probe_list_t *p = from->list;
165 struct probe_list_t *last = p;
168 to->func_num += from->func_num;
169 for (p = from->list; p != NULL; p = p->next) {
170 data_list_add_probe_to_hash(to, p);
174 last->next = to->list;
175 to->list->prev = last;
176 to->list = from->list;
181 int probe_list_append(struct data_list_t *to, struct probe_list_t *from)
183 struct probe_list_t **list = &(to->list);
184 struct probe_list_t *p = NULL;
192 from->next = (void *)p;
193 p->prev = (void *)from;
195 to->size += from->size;
198 for (p = from; p != NULL; p = p->next)
204 static struct probe_list_t *probe_list_rm_element(struct data_list_t *list, struct probe_list_t *element)
206 struct probe_list_t *prev = element->prev;
207 struct probe_list_t *next = element->next;
217 list->size -= element->size;
220 free_probe_element(element);
224 static struct data_list_t *data_list_unlink_data(struct data_list_t **list, struct data_list_t *element)
226 struct data_list_t *prev = element->prev;
227 struct data_list_t *next = element->next;
230 /* prev != null, next == null */
231 /* prev != null, next != null */
234 /* prev == null, next == null */
235 /* prev == null, next != null */
239 next->prev = (struct lib_list_t *)prev;
241 element->prev = NULL;
242 element->next = NULL;
247 static struct data_list_t *data_list_rm_data(struct data_list_t **list, struct data_list_t *element)
249 struct data_list_t *next = NULL;
251 next = data_list_unlink_data(list, element);
252 free_data_element(element);
258 static struct data_list_t *data_list_find_data(struct data_list_t *whered, struct data_list_t *whatd, cmp_data_f cmp)
260 struct data_list_t *where;
261 struct data_list_t *what = whatd;
262 for (where = whered; where != NULL; where = where->next) {
263 if (where->hash == what->hash) {
264 if (cmp(where, what))
271 // Check whether functions are equal. If so, returns first argument, otherwise - NULL
272 static struct probe_list_t *probes_equal(struct probe_list_t *first, struct probe_list_t *second)
274 if (first->size != second->size)
277 if (first->func->func_addr != second->func->func_addr)
280 if (first->func->probe_type != second->func->probe_type)
286 static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
288 struct probe_list_t *p ;
289 for (p = where->list; p != NULL; p = p->next)
290 if (probes_equal(p, probe))
296 // "from" will be destroyed after this call
297 static int data_list_move_with_hash(struct data_list_t **to, struct data_list_t **from, cmp_data_f cmp)
300 struct data_list_t *p = *from;
301 struct data_list_t *next = NULL;
302 struct data_list_t *sch = NULL;
304 sch = data_list_find_data(*to, p, cmp);
305 next = data_list_unlink_data(from, p);
307 data_list_make_hash(p);
308 data_list_append(to, p);
310 data_list_append_probes_hash(sch, p);
317 //---------------------------- collisions resolve ------------------------------
319 static int cmp_libs(struct data_list_t *el_1, struct data_list_t *el_2)
322 ((struct lib_list_t *)el_1)->lib->bin_path,
323 ((struct lib_list_t *)el_2)->lib->bin_path
327 ///////////////////////////////////////////////////////////////////////////
328 // function removes from new list all probes which are already installed
330 // cur - current state (lib list with probes)
331 // new - additional probes which were received with MSG_SWAP_INST_ADD msg
332 // (lib list with probes)
333 // this function removes all probes which are present in cur and new list from
334 // new list so after this function call in new list will be only probes which are
335 // not present in cur list
336 static int resolve_collisions_for_add_msg(struct lib_list_t **cur, struct lib_list_t **new)
338 struct data_list_t *p = (struct data_list_t *)*new;
339 struct data_list_t *sch = NULL;
341 struct probe_list_t *pr = NULL;
342 struct probe_list_t *next_pr = NULL;
344 // remove collisions from list "new"
346 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
348 // lib not found in cur config
350 // lib found in cur config so resolve collisions
354 if (find_probe(sch, pr) != NULL) {
355 // probe already exist
356 // rm from new config
357 next_pr = probe_list_rm_element(p, pr);
364 // rm lib if it is empty
365 if (p->list == NULL) {
366 p = data_list_rm_data((struct data_list_t **)new, p);
375 ///////////////////////////////////////////////////////////////////////////
376 // function removes from cur list all probes which are in list "new"
377 // and removes from "new" all probes which are not instaled
379 // cur - current state (lib list with probes)
380 // new - list for probes remove which were received with MSG_SWAP_INST_REMOVE msg
382 // this function removes all probes which are present in cur and new list from
383 // cur list and removes all probes which are present in new but not present in
384 // cur list so after this function call in new list will be only probes which are
385 // present in cur list
386 static int resolve_collisions_for_rm_msg(struct lib_list_t **cur, struct lib_list_t **new)
388 struct data_list_t *p = (struct data_list_t *)*new;
389 struct data_list_t *next_l = NULL;
390 struct data_list_t *sch = NULL;
392 struct probe_list_t *pr = NULL;
393 struct probe_list_t *next_pr = NULL;
394 struct probe_list_t *tmp = NULL;
396 // remove collisions from list "new"
398 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
400 //lib not found so no probes remove
401 next_l = data_list_rm_data((struct data_list_t **)new, p);
403 //lib found so we need remove collisions
406 // if rm probe list is empty that is mean we need
407 // to remove all probes on this lib
408 data_list_unlink_data((struct data_list_t **)cur, sch);
409 data_list_append((struct data_list_t **)new, sch);
410 next_l = data_list_rm_data((struct data_list_t **)cur, p);
412 // lib is not empty so merge
415 if ((tmp = find_probe(sch, pr)) != NULL) {
416 // probe found so remove probe
418 probe_list_rm_element(sch, tmp);
421 // probe no found so remove it
423 next_pr = probe_list_rm_element(p, pr);
427 // rm lib if it is empty
428 if (sch->list == NULL) {
429 data_list_rm_data((struct data_list_t **)cur, sch);
439 //--------------------------------------pack ----------------------------------
441 static char *pack_lib_head_to_array(char *to, void *data)
443 struct us_lib_inst_t *lib = data;
444 pack_str(to, lib->bin_path);
448 static char *pack_app_head_to_array(char *to, void *data)
450 struct app_info_t *app = data;
451 pack_int32(to, app->app_type);
452 pack_str(to, app->app_id);
453 pack_str(to, app->exe_path);
457 static char *pack_data_to_array(struct data_list_t *data, char *to, pack_head_t pack_head)
459 struct probe_list_t *p;
461 to = pack_head(to, data->data);
462 pack_int32(to, data->func_num);
463 for (p = data->list; p != NULL; p = p->next) {
464 memcpy(to, p->func, p->size);
470 static char *pack_data_list_to_array(struct data_list_t *list, uint32_t *len, uint32_t *count, pack_head_t pack)
476 struct data_list_t *p = list;
478 for (p = list; p != NULL; p = p->next) {
483 size += sizeof(uint32_t);
492 for (p = list; p != NULL; p = p->next)
493 to = pack_data_to_array(p, to, pack);
495 LOGE("can not malloc buffer for data list packing\n");
501 static char *pack_lib_list_to_array(struct lib_list_t *list, uint32_t *size, uint32_t *count)
503 return pack_data_list_to_array((struct data_list_t *)list, size,
504 count, pack_lib_head_to_array);
507 static char *pack_app_list_to_array(struct app_list_t *list, uint32_t *size, uint32_t *count)
509 return pack_data_list_to_array((struct data_list_t *)list, size,
510 count, pack_app_head_to_array);
513 static int generate_msg(struct msg_t **msg, struct lib_list_t *lib_list, struct app_list_t *app_list)
523 packed_lib_list = pack_lib_list_to_array(lib_list, &libs_size, &libs_count);
524 // print_buf(packed_lib_list, libs_size, "LIBS");
526 packed_app_list = pack_app_list_to_array(app_list, &apps_size, &apps_count);
527 // print_buf(packed_app_list, apps_size, "APPS");
529 size = apps_count * libs_size + apps_size;
531 LOGI("size = %d, apps= %d, libs = %d\n", size, apps_count, libs_count);
534 *msg = malloc(size + sizeof(**msg));
535 memset(*msg, '*', size);
538 pack_int32(p, 0); // msg id
539 pack_int32(p, size); // payload size
540 pack_int32(p, apps_count);
542 struct app_list_t *app = app_list;
543 char *app_p = packed_app_list + sizeof(((struct user_space_inst_t *)0)->app_num);
545 for (i = 0; i < apps_count; i++) {
546 memcpy(p, app_p, app->size);
548 memcpy(p, packed_lib_list, libs_size);
555 free(packed_lib_list);
556 free(packed_app_list);
558 // print_buf((char *)*msg, size, "ANSWER");
562 static void lock_lib_maps_message()
564 pthread_mutex_lock(&lib_inst_list_mutex);
567 static void unlock_lib_maps_message()
569 pthread_mutex_unlock(&lib_inst_list_mutex);
572 static void lock_lib_list()
574 pthread_mutex_lock(&lib_maps_message_mutex);
577 static void unlock_lib_list()
579 pthread_mutex_unlock(&lib_maps_message_mutex);
582 static void generate_maps_inst_msg(struct user_space_inst_t *us_inst)
584 lock_lib_maps_message();
586 struct lib_list_t *lib = us_inst->lib_inst_list;
587 struct app_list_t *app = us_inst->app_inst_list;
589 uint32_t total_maps_count = 0;
590 uint32_t total_len = sizeof(total_maps_count) + sizeof(*lib_maps_message);
591 char real_path_buf[PATH_MAX];
593 /* total message len calculate */
594 while (lib != NULL) {
595 p = lib->lib->bin_path;
596 total_len += strlen(p) + 1;
598 LOGI("lib #%u <%s>\n", total_maps_count, p);
599 lib = (struct lib_list_t *)lib->next;
602 while (app != NULL) {
603 p = app->app->exe_path;
604 resolved = realpath((const char *)p, real_path_buf);
605 if (resolved != NULL) {
606 total_len += strlen(real_path_buf) + 1;
608 LOGI("app #%u <%s>\n", total_maps_count, resolved);
610 LOGE("cannot resolve bin path <%s>\n", p);
613 app = (struct app_list_t *)app->next;
616 if (lib_maps_message != NULL)
617 free(lib_maps_message);
619 lib_maps_message = malloc(total_len);
620 lib_maps_message->type = MSG_MAPS_INST_LIST;
621 lib_maps_message->length = total_len;
624 p = lib_maps_message->data;
625 pack_int32(p, total_maps_count);
627 lib = us_inst->lib_inst_list;
628 while (lib != NULL) {
629 pack_str(p, lib->lib->bin_path);
630 lib = (struct lib_list_t *)lib->next;
633 app = us_inst->app_inst_list;
634 while (app != NULL) {
635 resolved = realpath(app->app->exe_path, real_path_buf);
636 if (resolved != NULL)
637 pack_str(p, real_path_buf);
638 app = (struct app_list_t *)app->next;
641 LOGI("total_len = %u\n", total_len);
642 print_buf((char *)lib_maps_message, total_len, "lib_maps_message");
644 unlock_lib_maps_message();
647 void send_maps_inst_msg_to(struct target *t)
649 lock_lib_maps_message();
650 target_send_msg(t, (struct msg_target_t *)lib_maps_message);
651 unlock_lib_maps_message();
654 static void send_maps_inst_msg_to_all_targets()
656 lock_lib_maps_message();
657 target_send_msg_to_all(lib_maps_message);
658 unlock_lib_maps_message();
661 //-----------------------------------------------------------------------------
662 struct app_info_t *app_info_get_first(struct app_list_t **app_list)
664 *app_list = prof_session.user_space_inst.app_inst_list;
665 if (*app_list == NULL) {
669 return (*app_list)->app;
672 struct app_info_t *app_info_get_next(struct app_list_t **app_list)
674 if (*app_list == NULL)
677 if ((*app_list = (*app_list)->next) == NULL)
680 return (*app_list)->app;
683 //-----------------------------------------------------------------------------
684 int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
685 struct msg_t **msg, enum ErrorCode *err)
691 /* lock list access */
694 if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
695 *err = ERR_WRONG_MESSAGE_FORMAT;
696 LOGE("parse app inst\n");
701 generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
705 pack_int32(p, NMSG_START);
707 *err = ERR_CANNOT_START_PROFILING;
712 generate_maps_inst_msg(us_inst);
715 /* unlock list access */
721 int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
722 struct msg_t **msg, enum ErrorCode *err)
725 uint32_t lib_num = 0;
730 /* lock list access */
733 if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
734 *err = ERR_WRONG_MESSAGE_FORMAT;
735 LOGE("parse lib inst list fail\n");
737 goto msg_swap_inst_add_exit;
739 // rm probes from new if its presents in cur
740 if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
741 LOGE("resolve collision\n");
743 goto msg_swap_inst_add_exit;
746 // generate msg to send
747 if (us_inst->app_inst_list != NULL) {
748 generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list);
750 pack_int32(p, NMSG_SWAP_INST_ADD);
752 // apply changes to cur state
753 if (!data_list_move_with_hash(
754 (struct data_list_t **)&us_inst->lib_inst_list,
755 (struct data_list_t **)&new_lib_inst_list,
760 goto msg_swap_inst_add_exit;
764 free_data_list((struct data_list_t **)&new_lib_inst_list);
765 new_lib_inst_list = NULL;
768 generate_maps_inst_msg(us_inst);
769 send_maps_inst_msg_to_all_targets();
771 msg_swap_inst_add_exit:
772 /* unlock list access */
778 int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
779 struct msg_t **msg, enum ErrorCode *err)
782 uint32_t lib_num = 0;
786 /* lock list access */
789 if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
790 *err = ERR_WRONG_MESSAGE_FORMAT;
791 LOGE("parse lib inst\n");
793 goto msg_swap_inst_remove_exit;
796 if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
797 LOGE("resolve collisions\n");
799 goto msg_swap_inst_remove_exit;
802 if (us_inst->app_inst_list != NULL) {
803 if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
804 LOGE("generate msg\n");
806 goto msg_swap_inst_remove_exit;
809 pack_int32(p, NMSG_SWAP_INST_ADD);
812 free_data_list((struct data_list_t **)&new_lib_inst_list);
813 new_lib_inst_list = NULL;
816 generate_maps_inst_msg(us_inst);
817 send_maps_inst_msg_to_all_targets();
819 msg_swap_inst_remove_exit:
820 /* unlock list access */
826 void msg_swap_free_all_data(struct user_space_inst_t *us_inst)
828 LOGI("new_lib_inst_list %p\n", new_lib_inst_list);
829 if (new_lib_inst_list != NULL) {
830 LOGI("free new_lib_inst_list start\n");
831 free_data_list(&new_lib_inst_list);
832 new_lib_inst_list = NULL;
833 LOGI("free new_lib_inst_list finish\n");
836 LOGI("us_inst->lib_inst_list %p\n", us_inst->lib_inst_list);
837 if (us_inst->lib_inst_list != NULL) {
838 LOGI("free us_inst->lib_inst_list start\n");
839 free_data_list(&us_inst->lib_inst_list);
840 us_inst->lib_inst_list = NULL;
841 LOGI("free us_isnt->lib_inst_list finish\n");
844 LOGI("us_inst->app_inst_list %p\n", us_inst->app_inst_list);
845 if (us_inst->app_inst_list != NULL) {
846 LOGI("free us_inst->app_inst_list start\n");
847 free_data_list(&us_inst->app_inst_list);
848 LOGI("free us_inst->app_isnt_list finish\n");