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 static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
273 struct probe_list_t *p ;
274 for (p = where->list; p != NULL; p = p->next)
275 if (p->size == probe->size)
276 if (p->func->func_addr == probe->func->func_addr)
277 if (strcmp(p->func->args, probe->func->args) == 0)
283 // "from" will be destroyed after this call
284 static int data_list_move_with_hash(struct data_list_t **to, struct data_list_t **from, cmp_data_f cmp)
287 struct data_list_t *p = *from;
288 struct data_list_t *next = NULL;
289 struct data_list_t *sch = NULL;
291 sch = data_list_find_data(*to, p, cmp);
292 next = data_list_unlink_data(from, p);
294 data_list_make_hash(p);
295 data_list_append(to, p);
297 data_list_append_probes_hash(sch, p);
304 //---------------------------- collisions resolve ------------------------------
306 static int cmp_libs(struct data_list_t *el_1, struct data_list_t *el_2)
309 ((struct lib_list_t *)el_1)->lib->bin_path,
310 ((struct lib_list_t *)el_2)->lib->bin_path
314 ///////////////////////////////////////////////////////////////////////////
315 // function removes from new list all probes which are already installed
317 // cur - current state (lib list with probes)
318 // new - additional probes which were received with MSG_SWAP_INST_ADD msg
319 // (lib list with probes)
320 // this function removes all probes which are present in cur and new list from
321 // new list so after this function call in new list will be only probes which are
322 // not present in cur list
323 static int resolve_collisions_for_add_msg(struct lib_list_t **cur, struct lib_list_t **new)
325 struct data_list_t *p = (struct data_list_t *)*new;
326 struct data_list_t *sch = NULL;
328 struct probe_list_t *pr = NULL;
329 struct probe_list_t *next_pr = NULL;
331 // remove collisions from list "new"
333 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
335 // lib not found in cur config
337 // lib found in cur config so resolve collisions
341 if (find_probe(sch, pr) != NULL) {
342 // probe already exist
343 // rm from new config
344 next_pr = probe_list_rm_element(p, pr);
351 // rm lib if it is empty
352 if (p->list == NULL) {
353 p = data_list_rm_data((struct data_list_t **)new, p);
362 ///////////////////////////////////////////////////////////////////////////
363 // function removes from cur list all probes which are in list "new"
364 // and removes from "new" all probes which are not instaled
366 // cur - current state (lib list with probes)
367 // new - list for probes remove which were received with MSG_SWAP_INST_REMOVE msg
369 // this function removes all probes which are present in cur and new list from
370 // cur list and removes all probes which are present in new but not present in
371 // cur list so after this function call in new list will be only probes which are
372 // present in cur list
373 static int resolve_collisions_for_rm_msg(struct lib_list_t **cur, struct lib_list_t **new)
375 struct data_list_t *p = (struct data_list_t *)*new;
376 struct data_list_t *next_l = NULL;
377 struct data_list_t *sch = NULL;
379 struct probe_list_t *pr = NULL;
380 struct probe_list_t *next_pr = NULL;
381 struct probe_list_t *tmp = NULL;
383 // remove collisions from list "new"
385 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
387 //lib not found so no probes remove
388 next_l = data_list_rm_data((struct data_list_t **)new, p);
390 //lib found so we need remove collisions
393 // if rm probe list is empty that is mean we need
394 // to remove all probes on this lib
395 data_list_unlink_data((struct data_list_t **)cur, sch);
396 data_list_append((struct data_list_t **)new, sch);
397 next_l = data_list_rm_data((struct data_list_t **)cur, p);
399 // lib is not empty so merge
402 if ((tmp = find_probe(sch, pr)) != NULL) {
403 // probe found so remove probe
405 probe_list_rm_element(sch, tmp);
408 // probe no found so remove it
410 next_pr = probe_list_rm_element(p, pr);
414 // rm lib if it is empty
415 if (sch->list == NULL) {
416 data_list_rm_data((struct data_list_t **)cur, sch);
426 //--------------------------------------pack ----------------------------------
428 static char *pack_lib_head_to_array(char *to, void *data)
430 struct us_lib_inst_t *lib = data;
431 pack_str(to, lib->bin_path);
435 static char *pack_app_head_to_array(char *to, void *data)
437 struct app_info_t *app = data;
438 pack_int32(to, app->app_type);
439 pack_str(to, app->app_id);
440 pack_str(to, app->exe_path);
444 static char *pack_data_to_array(struct data_list_t *data, char *to, pack_head_t pack_head)
446 struct probe_list_t *p;
448 to = pack_head(to, data->data);
449 pack_int32(to, data->func_num);
450 for (p = data->list; p != NULL; p = p->next) {
451 memcpy(to, p->func, p->size);
457 static char *pack_data_list_to_array(struct data_list_t *list, uint32_t *len, uint32_t *count, pack_head_t pack)
463 struct data_list_t *p = list;
465 for (p = list; p != NULL; p = p->next) {
470 size += sizeof(uint32_t);
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 free(packed_lib_list);
543 free(packed_app_list);
545 // print_buf((char *)*msg, size, "ANSWER");
549 static void lock_lib_maps_message()
551 pthread_mutex_lock(&lib_inst_list_mutex);
554 static void unlock_lib_maps_message()
556 pthread_mutex_unlock(&lib_inst_list_mutex);
559 static void lock_lib_list()
561 pthread_mutex_lock(&lib_maps_message_mutex);
564 static void unlock_lib_list()
566 pthread_mutex_unlock(&lib_maps_message_mutex);
569 static void generate_maps_inst_msg(struct user_space_inst_t *us_inst)
571 lock_lib_maps_message();
573 struct lib_list_t *lib = us_inst->lib_inst_list;
574 struct app_list_t *app = us_inst->app_inst_list;
576 uint32_t total_maps_count = 0;
577 uint32_t total_len = sizeof(total_maps_count) + sizeof(*lib_maps_message);
578 char real_path_buf[PATH_MAX];
580 /* total message len calculate */
581 while (lib != NULL) {
582 p = lib->lib->bin_path;
583 total_len += strlen(p) + 1;
585 LOGI("lib #%u <%s>\n", total_maps_count, p);
586 lib = (struct lib_list_t *)lib->next;
589 while (app != NULL) {
590 p = app->app->exe_path;
591 resolved = realpath((const char *)p, real_path_buf);
592 if (resolved != NULL) {
593 total_len += strlen(real_path_buf) + 1;
595 LOGI("app #%u <%s>\n", total_maps_count, resolved);
597 LOGE("cannot resolve bin path <%s>\n", p);
600 app = (struct app_list_t *)app->next;
603 if (lib_maps_message != NULL)
604 free(lib_maps_message);
606 lib_maps_message = malloc(total_len);
607 lib_maps_message->type = MSG_MAPS_INST_LIST;
608 lib_maps_message->length = total_len;
611 p = lib_maps_message->data;
612 pack_int32(p, total_maps_count);
614 lib = us_inst->lib_inst_list;
615 while (lib != NULL) {
616 pack_str(p, lib->lib->bin_path);
617 lib = (struct lib_list_t *)lib->next;
620 app = us_inst->app_inst_list;
621 while (app != NULL) {
622 resolved = realpath(app->app->exe_path, real_path_buf);
623 if (resolved != NULL)
624 pack_str(p, real_path_buf);
625 app = (struct app_list_t *)app->next;
628 LOGI("total_len = %u\n", total_len);
629 print_buf((char *)lib_maps_message, total_len, "lib_maps_message");
631 unlock_lib_maps_message();
634 void send_maps_inst_msg_to(struct target *t)
636 lock_lib_maps_message();
637 target_send_msg(t, (struct msg_target_t *)lib_maps_message);
638 unlock_lib_maps_message();
641 static void send_maps_inst_msg_to_all_targets()
643 lock_lib_maps_message();
644 target_send_msg_to_all(lib_maps_message);
645 unlock_lib_maps_message();
648 //-----------------------------------------------------------------------------
649 struct app_info_t *app_info_get_first(struct app_list_t **app_list)
651 *app_list = prof_session.user_space_inst.app_inst_list;
652 if (*app_list == NULL) {
656 return (*app_list)->app;
659 struct app_info_t *app_info_get_next(struct app_list_t **app_list)
661 if (*app_list == NULL)
664 if ((*app_list = (*app_list)->next) == NULL)
667 return (*app_list)->app;
670 //-----------------------------------------------------------------------------
671 int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
672 struct msg_t **msg, enum ErrorCode *err)
678 /* lock list access */
681 if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
682 *err = ERR_WRONG_MESSAGE_FORMAT;
683 LOGE("parse app inst\n");
688 generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
692 pack_int32(p, NMSG_START);
694 *err = ERR_CANNOT_START_PROFILING;
699 generate_maps_inst_msg(us_inst);
702 /* unlock list access */
708 int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
709 struct msg_t **msg, enum ErrorCode *err)
712 uint32_t lib_num = 0;
717 /* lock list access */
720 if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
721 *err = ERR_WRONG_MESSAGE_FORMAT;
722 LOGE("parse lib inst list fail\n");
724 goto msg_swap_inst_add_exit;
726 // rm probes from new if its presents in cur
727 if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
728 LOGE("resolve collision\n");
730 goto msg_swap_inst_add_exit;
733 // generate msg to send
734 if (us_inst->app_inst_list != NULL) {
735 generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list);
737 pack_int32(p, NMSG_SWAP_INST_ADD);
739 // apply changes to cur state
740 if (!data_list_move_with_hash(
741 (struct data_list_t **)&us_inst->lib_inst_list,
742 (struct data_list_t **)&new_lib_inst_list,
747 goto msg_swap_inst_add_exit;
751 free_data_list((struct data_list_t **)&new_lib_inst_list);
752 new_lib_inst_list = NULL;
755 generate_maps_inst_msg(us_inst);
756 send_maps_inst_msg_to_all_targets();
758 msg_swap_inst_add_exit:
759 /* unlock list access */
765 int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
766 struct msg_t **msg, enum ErrorCode *err)
769 uint32_t lib_num = 0;
773 /* lock list access */
776 if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
777 *err = ERR_WRONG_MESSAGE_FORMAT;
778 LOGE("parse lib inst\n");
780 goto msg_swap_inst_remove_exit;
783 if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
784 LOGE("resolve collisions\n");
786 goto msg_swap_inst_remove_exit;
789 if (us_inst->app_inst_list != NULL) {
790 if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
791 LOGE("generate msg\n");
793 goto msg_swap_inst_remove_exit;
796 pack_int32(p, NMSG_SWAP_INST_ADD);
799 free_data_list((struct data_list_t **)&new_lib_inst_list);
800 new_lib_inst_list = NULL;
803 generate_maps_inst_msg(us_inst);
804 send_maps_inst_msg_to_all_targets();
806 msg_swap_inst_remove_exit:
807 /* unlock list access */
813 void msg_swap_free_all_data(struct user_space_inst_t *us_inst)
815 LOGI("new_lib_inst_list %p\n", new_lib_inst_list);
816 if (new_lib_inst_list != NULL) {
817 LOGI("free new_lib_inst_list start\n");
818 free_data_list(&new_lib_inst_list);
819 new_lib_inst_list = NULL;
820 LOGI("free new_lib_inst_list finish\n");
823 LOGI("us_inst->lib_inst_list %p\n", us_inst->lib_inst_list);
824 if (us_inst->lib_inst_list != NULL) {
825 LOGI("free us_inst->lib_inst_list start\n");
826 free_data_list(&us_inst->lib_inst_list);
827 us_inst->lib_inst_list = NULL;
828 LOGI("free us_isnt->lib_inst_list finish\n");
831 LOGI("us_inst->app_inst_list %p\n", us_inst->app_inst_list);
832 if (us_inst->app_inst_list != NULL) {
833 LOGI("free us_inst->app_inst_list start\n");
834 free_data_list(&us_inst->app_inst_list);
835 LOGI("free us_inst->app_isnt_list finish\n");