From 6c0a48828990e241f9673e14649bd92071f61706 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Mon, 1 Sep 2014 17:40:34 +0400 Subject: [PATCH] [REFACTOR] encapsulate target struct (part 1) Change-Id: I783e3dc9c369af7c663261a941f11bc5ac1fc11f Signed-off-by: Vyacheslav Cherkashin --- daemon/Makefile | 3 +- daemon/da_inst.c | 6 +- daemon/da_inst.h | 3 +- daemon/da_protocol.c | 77 +++++++++------ daemon/da_protocol.h | 8 +- daemon/daemon.c | 208 ++++++++++++++-------------------------- daemon/daemon.h | 16 +--- daemon/main.c | 23 +---- daemon/sys_stat.c | 18 +--- daemon/target.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++ daemon/target.h | 90 ++++++++++++++++++ daemon/threads.c | 79 +++++----------- daemon/threads.h | 5 + 13 files changed, 515 insertions(+), 283 deletions(-) create mode 100644 daemon/target.c create mode 100644 daemon/target.h diff --git a/daemon/Makefile b/daemon/Makefile index 5698036..9e84161 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -46,7 +46,8 @@ DAEMON_SRCS = \ device_system_info.c \ device_camera.c \ smack.c \ - malloc_debug.c + malloc_debug.c \ + target.c DAEMON_OBJS = $(patsubst %.c,%.o, $(DAEMON_SRCS)) diff --git a/daemon/da_inst.c b/daemon/da_inst.c index 47a597a..78446cd 100644 --- a/daemon/da_inst.c +++ b/daemon/da_inst.c @@ -631,17 +631,17 @@ static void generate_maps_inst_msg(struct user_space_inst_t *us_inst) unlock_lib_maps_message(); } -void send_maps_inst_msg_to(int sock) +void send_maps_inst_msg_to(struct target *t) { lock_lib_maps_message(); - send_msg_to_target(sock, (struct msg_target_t *)lib_maps_message); + target_send_msg(t, (struct msg_target_t *)lib_maps_message); unlock_lib_maps_message(); } static void send_maps_inst_msg_to_all_targets() { lock_lib_maps_message(); - send_msg_to_all_targets(lib_maps_message); + target_send_msg_to_all(lib_maps_message); unlock_lib_maps_message(); } diff --git a/daemon/da_inst.h b/daemon/da_inst.h index 9368f64..bf26b54 100644 --- a/daemon/da_inst.h +++ b/daemon/da_inst.h @@ -90,6 +90,7 @@ void free_data_list(struct data_list_t **data); struct app_info_t *app_info_get_first(struct app_list_t **app_list); struct app_info_t *app_info_get_next(struct app_list_t **app_list); -void send_maps_inst_msg_to(int sock); +struct target; // move +void send_maps_inst_msg_to(struct target *t); #endif /* __DA_INST_H__*/ diff --git a/daemon/da_protocol.c b/daemon/da_protocol.c index 786ce19..86ffa3f 100644 --- a/daemon/da_protocol.c +++ b/daemon/da_protocol.c @@ -957,31 +957,57 @@ send_ack: return -(err_code != ERR_NO); } -int send_msg_to_target(int sock, struct msg_target_t *msg) +int send_msg_to_sock(int sock, struct msg_target_t *msg) { - if (sock != -1) { - if (send(sock, msg, sizeof(struct _msg_target_t) + msg->length, MSG_NOSIGNAL) == -1) - LOGE("fail to send data to target socket(%d)\n", sock); - else - return 1; + ssize_t ret; + size_t n; + int err = 0; + + n = sizeof(struct _msg_target_t) + msg->length; + ret = send(sock, msg, n, MSG_NOSIGNAL); + if (ret != n) { + LOGE("fail to send data to socket(%d) n=%u, ret=%d\n", + sock, n, ret); + err = 1; } - return 0; + + return err; } -int send_msg_to_all_targets(struct msg_target_t *msg) +int recv_msg_from_sock(int sock, struct msg_target_t *msg) { - int target_index; - int sock; - for (target_index = 0; target_index < MAX_TARGET_COUNT; target_index++) { - sock = manager.target[target_index].socket; - if (sock != -1) { - if (send(sock, msg, sizeof(struct _msg_target_t) + msg->length, MSG_NOSIGNAL) == -1) - LOGE("fail to send data to target index(%d)\n", - target_index); - else - return 1; - } + ssize_t ret; + + ret = recv(sock, msg, MSG_HEADER_LEN, MSG_WAITALL); + if (ret != MSG_HEADER_LEN) + return 1; + + if (IS_PROBE_MSG(msg->type)) { + struct msg_data_t *msg_data = (struct msg_data_t *)msg; + size_t n = MSG_DATA_HDR_LEN - MSG_HEADER_LEN; + + ret = recv(sock, (char *)msg_data + MSG_HEADER_LEN, + n, MSG_WAITALL); + if (ret != n) + return 1; + + /* TODO: check msg_data->len */ + ret = recv(sock, msg_data->payload, + msg_data->len, MSG_WAITALL); + + if (ret != msg_data->len) + return 1; + + return 0; } + + if (msg->length > 0) { + /* TODO: check msg->length */ + ret = recv(sock, msg->data, msg->length, MSG_WAITALL); + if (ret != msg->length) + return 1; + } + return 0; } @@ -996,7 +1022,7 @@ static int process_msg_get_screenshot(struct msg_buf_t *msg_control) sendlog.length = 0; log_len = sizeof(sendlog.type) + sizeof(sendlog.length) + sendlog.length; - if (send_msg_to_all_targets(&sendlog) == 1) + if (target_send_msg_to_all(&sendlog) == 1) err_code = ERR_NO; return -(err_code != ERR_NO); @@ -1168,16 +1194,7 @@ int host_message_handler(struct msg_t *msg) sendlog.type = MSG_OPTION; sendlog.length = sprintf(sendlog.data, "%llu", (unsigned long long) prof_session.conf.use_features0); - for (target_index = 0; target_index < MAX_TARGET_COUNT; target_index++) - { - if(manager.target[target_index].socket != -1) - { - if (0 > send(manager.target[target_index].socket, &sendlog, - sizeof(sendlog.type) + sizeof(sendlog.length) + sendlog.length, - MSG_NOSIGNAL)) - LOGE("fail to send data to target index(%d)\n", target_index); - } - } + target_send_msg_to_all(&sendlog); break; case NMSG_BINARY_INFO: return process_msg_binary_info(&msg_control); diff --git a/daemon/da_protocol.h b/daemon/da_protocol.h index b326e94..d4201f4 100644 --- a/daemon/da_protocol.h +++ b/daemon/da_protocol.h @@ -33,6 +33,7 @@ #include #include #include +#include #include enum HostMessageT { @@ -182,6 +183,9 @@ struct msg_target_t { char data[DA_MSG_MAX]; }; +enum { MSG_HEADER_LEN = offsetof(struct msg_target_t, data) }; + + #define MAX_FILENAME 128 #define MSG_DATA_HDR_LEN 20 @@ -439,8 +443,8 @@ int check_running_status(const struct prof_session_t *prof_session); extern struct prof_session_t prof_session; -extern int send_msg_to_target(int sock, struct msg_target_t *msg); -extern int send_msg_to_all_targets(struct msg_target_t *msg); +int send_msg_to_sock(int sock, struct msg_target_t *msg); +int recv_msg_from_sock(int sock, struct msg_target_t *msg); //debugs void print_replay_event(struct replay_event_t *ev, uint32_t num, char *tab); diff --git a/daemon/daemon.c b/daemon/daemon.c index d232a68..38acb2e 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -70,46 +70,6 @@ #define MAX_CONNECT_TIMEOUT_TIME 5*60 -uint64_t get_total_alloc_size_by_pid(pid_t pid) -{ - int i; - - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].socket != -1 && - manager.target[i].pid == pid && - manager.target[i].allocmem > 0) - return manager.target[i].allocmem; - } - return 0; -} - -static int getEmptyTargetSlot() -{ - int i; - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].socket == -1) - break; - } - - return i; -} - -static void setEmptyTargetSlot(int index) -{ - if (index >= 0 && index < MAX_TARGET_COUNT) { - manager.target[index].pid = -1; - manager.target[index].recv_thread = -1; - manager.target[index].allocmem = 0; - manager.target[index].initial_log = 0; - if (manager.target[index].event_fd != -1) - close(manager.target[index].event_fd); - manager.target[index].event_fd = -1; - if (manager.target[index].socket != -1) - close(manager.target[index].socket); - manager.target[index].socket = -1; - } -} - // ============================================================================= // start and terminate control functions // ============================================================================= @@ -276,41 +236,21 @@ static int exec_app(const struct app_info_t *app_info) // just send stop message to all target process static void terminate_all_target() { - int i; - ssize_t sendlen; - struct msg_target_t sendlog; - - sendlog.type = MSG_STOP; - sendlog.length = 0; - - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].socket != -1) { - sendlen = send(manager.target[i].socket, &sendlog, - sizeof(sendlog.type) + - sizeof(sendlog.length), MSG_NOSIGNAL); - if (sendlen != -1) { - LOGI("TERMINATE send exit msg (socket %d) " - "by terminate_all_target()\n", - manager.target[i].socket); - } - } - } + struct msg_target_t msg = { + .type = MSG_STOP, + .length = 0 + }; + + target_send_msg_to_all(&msg); } // terminate all target and wait for threads void terminate_all() { - int i; terminate_all_target(); // wait for all other thread exit - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].recv_thread != -1) { - LOGI("join recv thread [%d] is started\n", i); - pthread_join(manager.target[i].recv_thread, NULL); - LOGI("join recv thread %d. done\n", i); - } - } + target_wait_all(); } // terminate all profiling by critical error @@ -505,8 +445,6 @@ int reconfigure(struct conf_t conf) return 0; } -static Ecore_Fd_Handler *target_handlers[MAX_TARGET_COUNT]; - static int file2str(const char *filename, char *buf, int len) { @@ -528,13 +466,13 @@ static int file2str(const char *filename, char *buf, int len) return num_read; } -static int get_lpad_pid(int pid) +static pid_t get_lpad_pid(pid_t pid) { - static pid_t lpad_pid = -1; + static pid_t lpad_pid = UNKNOWN_PID; static const char lpad_path[] = DEBUG_LAUNCH_PRELOAD_PATH; enum { lpad_path_len = sizeof(lpad_path) }; - if (lpad_pid == -1) { + if (lpad_pid == UNKNOWN_PID) { char fname[64]; char buf[lpad_path_len]; @@ -553,32 +491,34 @@ static int get_lpad_pid(int pid) static pid_t get_current_pid(void) { - static pid_t pid = -1; + static pid_t pid = UNKNOWN_PID; - if (pid == -1) - pid = getpid(); + if (pid == UNKNOWN_PID) + pid = getpid(); - return pid; + return pid; } -static void taget_set_type(__da_target_info *taget) +static void target_set_type(struct target *t) { - if (get_current_pid() == taget->ppid) { - taget->app_type = APP_TYPE_COMMON; - } else if (get_lpad_pid(taget->ppid) == taget->ppid) { - taget->app_type = APP_TYPE_TIZEN; + pid_t ppid = target_get_ppid(t); + + if (get_current_pid() == ppid) { + t->app_type = APP_TYPE_COMMON; + } else if (get_lpad_pid(ppid) == ppid) { + t->app_type = APP_TYPE_TIZEN; } } -static int target_event_pid_handler(int index, uint64_t msg) +static int target_event_pid_handler(struct target *target) { struct app_list_t *app = NULL; struct app_info_t *app_info = NULL; - taget_set_type(&manager.target[index]); + target_set_type(target); - if (index == 0) { // main application + if (0) { // main application (index == 0) app_info = app_info_get_first(&app); if (app_info == NULL) { LOGE("No app info found\n"); @@ -587,14 +527,14 @@ static int target_event_pid_handler(int index, uint64_t msg) while (app_info != NULL) { if (is_same_app_process(app_info->exe_path, - manager.target[index].pid)) + target_get_pid(target))) break; app_info = app_info_get_next(&app); } if (app_info == NULL) { LOGE("pid %d not found in app list\n", - manager.target[index].pid); + target_get_pid(target)); return -1; } @@ -603,29 +543,30 @@ static int target_event_pid_handler(int index, uint64_t msg) return -1; } } - manager.target[index].initial_log = 1; + + target->initial_log = 1; + return 0; } -static int target_event_stop_handler(int index, uint64_t msg) +static int target_event_stop_handler(struct target *target) { int cnt; + enum app_type_t app_type = target->app_type; - LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n", - manager.target[index].socket, manager.target[index].pid, - manager.target_count - 1); + LOGI("target[%p] close, pid(%d) : (remaining %d target)\n", + target, target_get_pid(target), target_cnt_get() - 1); - - if (index == 0) // main application + if (0) // main application (index == 0) stop_replay(); - ecore_main_fd_handler_del(target_handlers[index]); + ecore_main_fd_handler_del(target->handler); - setEmptyTargetSlot(index); + target_dtor(target); // all target client are closed - cnt = __sync_sub_and_fetch(&manager.target_count, 1); + cnt = target_cnt_sub_and_fetch(); if (0 == cnt) { - switch (manager.target[index].app_type) { + switch (app_type) { case APP_TYPE_TIZEN: case APP_TYPE_COMMON: LOGI("all targets are stopped\n"); @@ -642,16 +583,16 @@ static int target_event_stop_handler(int index, uint64_t msg) // return plus value if non critical error occur // return minus value if critical error occur // return -11 if all target process closed -static int target_event_handler(int index, uint64_t msg) +static int target_event_handler(struct target *t, uint64_t msg) { int err = 0; if (msg & EVENT_PID) - err = target_event_pid_handler(index, msg); + err = target_event_pid_handler(t); if (err) return err; if (msg & EVENT_STOP || msg & EVENT_ERROR) - err = target_event_stop_handler(index, msg); + err = target_event_stop_handler(t); return err; } @@ -660,14 +601,14 @@ static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler) { uint64_t u; ssize_t recvLen; - int index = (int)data; + struct target *target = (struct target *)data; - recvLen = read(manager.target[index].event_fd, &u, sizeof(uint64_t)); + recvLen = read(target->event_fd, &u, sizeof(uint64_t)); if (recvLen != sizeof(uint64_t)) { // maybe closed, but ignoring is more safe then // removing fd from event loop } else { - if (-11 == target_event_handler(index, u)) { + if (-11 == target_event_handler(target, u)) { LOGI("all target process is closed\n"); } } @@ -682,60 +623,53 @@ static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler) */ static int targetServerHandler(void) { + int err; struct msg_target_t log; + struct target *target; - int index = getEmptyTargetSlot(); - if (index == MAX_TARGET_COUNT) { - LOGW("Max target number(8) reached, no more target can connected\n"); + target = target_ctor(); + if (target == NULL) { + LOGW("(target == NULL) no more target can connected\n"); return 1; } - manager.target[index].socket = - accept4(manager.target_server_socket, NULL, NULL, SOCK_CLOEXEC); - - if (manager.target[index].socket >= 0) { - /* accept succeed */ - fd_setup_attributes(manager.target[index].socket); - + err = target_accept(target, manager.target_server_socket); + if (err == 0) { /* send config message to target process */ log.type = MSG_OPTION; log.length = sprintf(log.data, "%llu\0", prof_session.conf.use_features0) + 1; - if (0 > send(manager.target[index].socket, &log, - sizeof(log.type) + sizeof(log.length) + log.length, - MSG_NOSIGNAL)) - LOGE("fail to send data to target index(%d)\n", index); + if (target_send_msg(target, &log) != 0) + LOGE("fail to send data to target %p\n", target); /* send current instrument maps */ - send_maps_inst_msg_to(manager.target[index].socket); + send_maps_inst_msg_to(target); // make event fd - manager.target[index].event_fd = eventfd(EFD_CLOEXEC, EFD_NONBLOCK); - if (manager.target[index].event_fd == -1) { + target->event_fd = eventfd(EFD_CLOEXEC, EFD_NONBLOCK); + if (target->event_fd == -1) { // fail to make event fd - LOGE("fail to make event fd for socket (%d)\n", - manager.target[index].socket); + LOGE("fail to make event fd for target[%p]\n", target); goto TARGET_CONNECT_FAIL; } - target_handlers[index] = - ecore_main_fd_handler_add(manager.target[index].event_fd, + target->handler = + ecore_main_fd_handler_add(target->event_fd, ECORE_FD_READ, target_event_cb, - (void *)index, + (void *)target, NULL, NULL); - if (!target_handlers[index]) { - LOGE("fail to add event fd for socket (%d)\n", - manager.target[index].socket); + if (!target->handler) { + LOGE("fail to add event fd for target[%p]\n", target); goto TARGET_CONNECT_FAIL; } // make recv thread for target - if (makeRecvThread(index) != 0) { + if (makeRecvThread(target) != 0) { // fail to make recv thread - LOGE("fail to make recv thread for socket (%d)\n", - manager.target[index].socket); - ecore_main_fd_handler_del(target_handlers[index]); + LOGE("fail to make recv thread for target[%p]\n", + target); + ecore_main_fd_handler_del(target->handler); goto TARGET_CONNECT_FAIL; } @@ -746,10 +680,10 @@ static int targetServerHandler(void) LOGE("cannot stop app launch timer\n"); } - LOGI("target connected = %d(running %d target)\n", - manager.target[index].socket, manager.target_count + 1); + LOGI("target connected target[%p](running %d target)\n", + target, target_cnt_get() + 1); - manager.target_count++; + target_cnt_set(target_cnt_get() + 1); return 0; } else { // accept error @@ -757,12 +691,12 @@ static int targetServerHandler(void) } TARGET_CONNECT_FAIL: - if (manager.target_count == 0) { + if (target_cnt_get() == 0) { // if this connection is main connection return -1; } else { // if this connection is not main connection then ignore process by error - setEmptyTargetSlot(index); + target_dtor(target); return 1; } } diff --git a/daemon/daemon.h b/daemon/daemon.h index f3749a4..8c10637 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -36,6 +36,7 @@ #include // for uint64_t, int64_t #include // for pthread_mutex_t #include "da_protocol.h" +#include "target.h" #ifdef __cplusplus extern "C" { @@ -142,18 +143,6 @@ typedef struct typedef struct { - int64_t allocmem; // written only by recv thread - pid_t pid; // written only by recv thread - pid_t ppid; // written only by recv thread - int socket; // written only by main thread - pthread_t recv_thread; // written only by main thread - int event_fd; // for thread communication (from recv thread to main thread) - int initial_log; // written only by main thread - enum app_type_t app_type; -} __da_target_info; - -typedef struct -{ int brightness; int voltage; int procmeminfo; @@ -168,7 +157,6 @@ typedef struct { int host_server_socket; int target_server_socket; - int target_count; int apps_to_run; unsigned int config_flag; int app_launch_timerfd; @@ -180,7 +168,6 @@ typedef struct int user_ev_fd; int efd; __da_host_info host; - __da_target_info target[MAX_TARGET_COUNT]; __file_descriptors fd; char appPath[128]; // application executable path } __da_manager; @@ -193,7 +180,6 @@ void initialize_log(void); int daemonLoop(void); void unlink_portfile(void); -int makeRecvThread(int index); int samplingStart(void); int samplingStop(void); diff --git a/daemon/main.c b/daemon/main.c index 42d6aec..cb182f4 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -64,7 +64,6 @@ __da_manager manager = { .host_server_socket = -1, .target_server_socket = -1, - .target_count = 0, .apps_to_run = 0, .config_flag = 0, .app_launch_timerfd = -1, @@ -82,9 +81,6 @@ __da_manager manager = .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER }, - .target = { - {0L, }, - }, .fd = { .brightness = -1, .voltage = -1, @@ -265,22 +261,9 @@ static bool ensure_singleton(const char *lockfile) return locked; } -static void inititialize_manager_targets(__da_manager * mng) +static void inititialize_manager_targets(void) { - int index; - __da_target_info target_init_value = { - .pid = -1, - .socket = -1, - .event_fd = -1, - .recv_thread = -1, - .initial_log = 0, - .allocmem = 0 - }; - - for (index = 0; index < MAX_TARGET_COUNT; index++) - mng->target[index] = target_init_value; - - manager.target_count = 0; + target_cnt_set(0); } static bool initialize_pthread_sigmask() @@ -325,7 +308,7 @@ static int initializeManager(FILE *portfile) LOGI("SUCCESS to write port\n"); - inititialize_manager_targets(&manager); + inititialize_manager_targets(); // initialize sendMutex pthread_mutex_init(&(manager.host.data_socket_mutex), NULL); diff --git a/daemon/sys_stat.c b/daemon/sys_stat.c index 2bfa04f..abd1fb5 100644 --- a/daemon/sys_stat.c +++ b/daemon/sys_stat.c @@ -1803,22 +1803,6 @@ static int get_other_pid_array(pid_t inst_pid[], const int inst_n, pid_t arr[], return count; } -static pid_t get_first_target_process(void) -{ - pid_t pid = -1; - int i; - - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].socket != -1 && - manager.target[i].pid != -1) { - pid = manager.target[i].pid; - break; - } - } - - return pid; -} - // return log length (>0) for normal case // return negative value for error int get_system_info(struct system_info_t *sys_info) @@ -2241,7 +2225,7 @@ struct msg_data_t *pack_system_info(struct system_info_t *sys_info) pack_int64(p, (uint64_t)proc->proc_data.pss); /* TODO total alloc for not ld preloaded processes */ - pack_int64(p, (uint64_t)get_total_alloc_size_by_pid(proc->proc_data.pid)); + pack_int64(p, target_get_total_alloc(proc->proc_data.pid)); //pack threads if (IS_OPT_SET(FL_SYSTEM_THREAD_LOAD)) { diff --git a/daemon/target.c b/daemon/target.c new file mode 100644 index 0000000..471d4e6 --- /dev/null +++ b/daemon/target.c @@ -0,0 +1,262 @@ +/* + * DA manager + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * + * Vyacheslav Cherkashin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Contributors: + * - Samsung RnD Institute Russia + * + */ + + +#define _GNU_SOURCE /* for accept4() */ +#include + +#include "target.h" + +#include "daemon.h" // for manager (it is need delete) +#include "smack.h" +#include "debug.h" + + +static struct target *target_malloc(void); +static void target_free(struct target *t); + +struct target *target_ctor(void) +{ + struct target *t; + + t = target_malloc(); + if (t) { + t->pid = UNKNOWN_PID; + t->socket = UNKNOWN_FD; + t->event_fd = UNKNOWN_FD; + t->recv_thread = 0; + t->initial_log = 0; + t->allocmem = 0; + } + + return t; +} + +void target_dtor(struct target *t) +{ + t->recv_thread = -1; + t->allocmem = 0; + t->initial_log = 0; + + if (t->event_fd != -1) + close(t->event_fd); + t->event_fd = -1; + + if (t->socket != UNKNOWN_FD) + close(t->socket); + t->socket = -1; + + target_free(t); +} + + +int target_accept(struct target *t, int sockfd) +{ + int sock; + + sock = accept4(sockfd, NULL, NULL, SOCK_CLOEXEC); + if (sock == UNKNOWN_FD) + return 1; + + /* accept succeed */ + fd_setup_attributes(sock); + + t->socket = sock; + + return 0; +} + +int target_send_msg(struct target *t, struct msg_target_t *msg) +{ + return send_msg_to_sock(t->socket, msg); +} + +int target_recv_msg(struct target *t, struct msg_target_t *msg) +{ + return recv_msg_from_sock(t->socket, msg); +} + + +int target_start(struct target *t, void *(*start_routine) (void *)) +{ + return pthread_create(&t->recv_thread, NULL, start_routine, (void *)t); +} + +int target_wait(struct target *t) +{ + return pthread_join(t->recv_thread, NULL); +} + + +pid_t target_get_pid(struct target *t) +{ + return t->pid; +} + +void target_set_pid(struct target *t, pid_t pid) +{ + t->pid = pid; +} + +pid_t target_get_ppid(struct target *t) +{ + return t->ppid; +} + +void target_set_ppid(struct target *t, pid_t ppid) +{ + t->ppid = ppid; +} + +static int target_cnt = 0; +static pthread_mutex_t ts_mutex = PTHREAD_MUTEX_INITIALIZER; +static int target_use[MAX_TARGET_COUNT] = {0}; +static struct target target_array[MAX_TARGET_COUNT]; + +static void target_array_lock(void) +{ + pthread_mutex_lock(&ts_mutex); +} + +static void target_array_unlock(void) +{ + pthread_mutex_unlock(&ts_mutex); +} + +static struct target *target_malloc(void) +{ + int i; + struct target *t = NULL; + + target_array_lock(); + for (i = 0; i < MAX_TARGET_COUNT; i++) { + if (target_use[i] == 0) { + target_use[i] = 1; + t = &target_array[i]; + break; + } + } + target_array_unlock(); + + return t; +} + +static void target_free(struct target *t) +{ + target_array_lock(); + target_use[t - target_array] = 0; + target_array_unlock(); +} + + +void target_cnt_set(int cnt) +{ + target_cnt = cnt; +} + +int target_cnt_get(void) +{ + return target_cnt; +} + +int target_cnt_sub_and_fetch(void) +{ + return __sync_sub_and_fetch(&target_cnt, 1); +} + + +struct target *target_get(int i) +{ + return &target_array[i]; +} + + + + + +/* + * for all targets + */ +int target_send_msg_to_all(struct msg_target_t *msg) +{ + int i, ret = 0; + struct target *t; + + target_array_lock(); + for (i = 0; i < MAX_TARGET_COUNT; ++i) { + if (target_use[i] == 0) + continue; + + t = target_get(i); + if (target_send_msg(t, msg)) + ret = 1; + } + target_array_unlock(); + + return ret; +} + +void target_wait_all(void) +{ + int i; + struct target *t; + + target_array_lock(); + for (i = 0; i < MAX_TARGET_COUNT; ++i) { + if (target_use[i] == 0) + continue; + + t = target_get(i); + + LOGI("join recv thread [%d] is started\n", i); + target_wait(t); + LOGI("join recv thread %d. done\n", i); + } + target_array_unlock(); +} + +uint64_t target_get_total_alloc(pid_t pid) +{ + int i; + uint64_t ret = 0; + struct target *t; + + target_array_lock(); + for (i = 0; i < MAX_TARGET_COUNT; i++) { + if (target_use[i] == 0) + continue; + + t = target_get(i); + if (target_get_pid(t) == pid) { + ret = t->allocmem; + goto unlock; + } + } +unlock: + target_array_lock(); + + return ret; +} diff --git a/daemon/target.h b/daemon/target.h new file mode 100644 index 0000000..e30ea25 --- /dev/null +++ b/daemon/target.h @@ -0,0 +1,90 @@ +/* + * DA manager + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * + * Vyacheslav Cherkashin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Contributors: + * - Samsung RnD Institute Russia + * + */ + + +#ifndef _TARGER_H_ +#define _TARGER_H_ + + +#include +#include + +#include + +#include "da_protocol.h" + + +#define UNKNOWN_PID ((pid_t)(-1)) +#define UNKNOWN_FD (-1) + + +struct target { + enum app_type_t app_type; /* calculated when connecting */ + int64_t allocmem; /* written only by recv thread */ + pid_t pid; /* written only by recv thread */ + pid_t ppid; /* written only by recv thread */ + int socket; /* written only by main thread */ + pthread_t recv_thread; /* written only by main thread */ + int event_fd; /* for thread communication + * (from recv thread to main thread) */ + int initial_log; /* written only by main thread */ + Ecore_Fd_Handler *handler; /* calculated when connecting */ +}; + + +struct target *target_ctor(void); +void target_dtor(struct target *t); + +int target_accept(struct target *t, int sockfd); + +int target_send_msg(struct target *t, struct msg_target_t *msg); +int target_recv_msg(struct target *t, struct msg_target_t *msg); + + +int target_start(struct target *t, void *(*start_routine) (void *)); +int target_wait(struct target *t); + + +pid_t target_get_pid(struct target *t); +void target_set_pid(struct target *t, pid_t pid); + +pid_t target_get_ppid(struct target *t); +void target_set_ppid(struct target *t, pid_t ppid); + + +void target_cnt_set(int cnt); +int target_cnt_get(void); +int target_cnt_sub_and_fetch(void); + +struct target *target_get(int i); + +/* for all targets */ +int target_send_msg_to_all(struct msg_target_t *msg); +void target_wait_all(void); +uint64_t target_get_total_alloc(pid_t pid); + + +#endif /* _TARGER_H_ */ diff --git a/daemon/threads.c b/daemon/threads.c index 7797ba3..3cbd85a 100644 --- a/daemon/threads.c +++ b/daemon/threads.c @@ -46,67 +46,38 @@ #include "da_protocol.h" #include "da_data.h" +#include "da_inst.h" #include "debug.h" #include "buffer.h" #include "input_events.h" static void* recvThread(void* data) { - __da_target_info *target = data; + struct target *target = data; int pass = 0; uint64_t event; - ssize_t recvLen; struct msg_target_t log; + int err; // initialize target variable - target->pid = -1; target->allocmem = 0; - while(1) - { - // read from target process - recvLen = recv(target->socket, &log, - sizeof(log.type) + sizeof(log.length), - MSG_WAITALL); - - if(unlikely(recvLen < sizeof(log.type) + sizeof(log.length))) - { // disconnect + for (;;) { + err = target_recv_msg(target, &log); + if (err != 0) { + /* disconnect */ event = EVENT_STOP; - write(target->event_fd, &event, sizeof(uint64_t)); + write(target->event_fd, &event, sizeof(event)); break; } + if (IS_PROBE_MSG(log.type)) { - struct msg_data_t tmp_msg; - int offs = sizeof(log.type) + sizeof(log.length); - - recvLen = recv(target->socket, - (char *)&log + offs, - MSG_DATA_HDR_LEN - offs, - MSG_WAITALL); - memcpy(&tmp_msg, &log, MSG_DATA_HDR_LEN); - struct msg_data_t *msg = malloc(MSG_DATA_HDR_LEN + - tmp_msg.len); - memcpy(msg, &tmp_msg, MSG_DATA_HDR_LEN); - recvLen = recv(target->socket, - (char *)msg + MSG_DATA_HDR_LEN, - msg->len, MSG_WAITALL); - if (write_to_buf(msg) != 0) + struct msg_data_t *msg_data = (struct msg_data_t *)&log; + + if (write_to_buf(msg_data) != 0) LOGE("write to buf fail\n"); - free(msg); - continue; - } - // send to host - if (likely(log.length > 0)) - { - recvLen = recv(target->socket, log.data, log.length, - MSG_WAITALL); - if(unlikely((recvLen == -1) || (recvLen != log.length))) // consume as disconnect - { - event = EVENT_STOP; - write(target->event_fd, &event, sizeof(uint64_t)); - break; - } + continue; } log.data[log.length] = '\0'; @@ -120,8 +91,7 @@ static void* recvThread(void* data) LOGI("MSG_PID arrived (pid ppid): %s\n", log.data); // only when first MSG_PID is arrived - if(target->pid == -1) - { + if (target_get_pid(target) == UNKNOWN_PID) { int n; pid_t pid, ppid; @@ -140,19 +110,20 @@ static void* recvThread(void* data) } /* set pid and ppid */ - target->pid = pid; - target->ppid = ppid; + target_set_pid(target, pid); + target_set_ppid(target, ppid); /* send event */ event = EVENT_PID; write(target->event_fd, &event, sizeof(uint64_t)); } - send_maps_inst_msg_to(target->socket); + send_maps_inst_msg_to(target); continue; // don't send to host } else if(log.type == MSG_TERMINATE) { - LOGI("MSG_TERMINATE arrived: pid[%d]\n", target->pid); + LOGI("MSG_TERMINATE arrived: pid[%d]\n", + target_get_pid(target)); // send stop message to main thread event = EVENT_STOP; @@ -214,16 +185,10 @@ static void* recvThread(void* data) return NULL; } -int makeRecvThread(int index) +int makeRecvThread(struct target *target) { - if (manager.target[index].socket == -1) - return -1; - - if (pthread_create(&(manager.target[index].recv_thread), - NULL, recvThread, &manager.target[index]) < 0) - { - LOGE("Failed to create recv thread for socket (%d)\n", - manager.target[index].socket); + if (target_start(target, recvThread) < 0) { + LOGE("Failed to create recv thread\n"); return -1; } diff --git a/daemon/threads.h b/daemon/threads.h index 6569e3a..ea4a670 100644 --- a/daemon/threads.h +++ b/daemon/threads.h @@ -38,6 +38,11 @@ extern "C" { #endif +struct target; + + +int makeRecvThread(struct target *target); + #ifdef __cplusplus } -- 2.7.4