[FIX] wrong pack size of system memory total/used
[platform/core/system/swap-manager.git] / daemon / threads.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32
33 #include <stdio.h>
34 #include <stdlib.h>                     // for atoi, atol
35 #include <string.h>                     // for strchr
36 #include <stdint.h>                     // for uint64_t
37 #include <sys/types.h>          // for recv
38 #include <sys/socket.h>         // for recv
39 #include <sys/time.h>           // for setitimer
40 #include <signal.h>                     // for sigemptyset, sigset_t, sigaddset, ...
41 #include <unistd.h>                     // for write
42
43 #include "daemon.h"
44 #include "utils.h"
45 #include "sys_stat.h"
46
47 #include "da_protocol.h"
48 #include "da_data.h"
49 #include "debug.h"
50 #include "buffer.h"
51
52 static void* recvThread(void* data)
53 {
54         int index = (int)data;
55         int pass = 0;
56         uint64_t event;
57         ssize_t recvLen;
58         msg_target_t log;
59
60         // initialize target variable
61         manager.target[index].pid = -1;
62         manager.target[index].allocmem = 0;
63
64         while(1)
65         {
66                 // read from target process
67                 recvLen = recv(manager.target[index].socket, &log,
68                                 sizeof(log.type) + sizeof(log.length), MSG_WAITALL);
69
70                 if(unlikely(recvLen < sizeof(log.type) + sizeof(log.length)))
71                 {       // disconnect
72                         event = EVENT_STOP;
73                         write(manager.target[index].event_fd, &event, sizeof(uint64_t));
74                         break;
75                 }
76                 if (IS_PROBE_MSG(log.type)) {
77                         struct msg_data_t tmp_msg;
78                         int offs = sizeof(log.type) + sizeof(log.length);
79                         recvLen = recv(manager.target[index].socket,
80                                        (char *)&log + offs,
81                                        MSG_DATA_HDR_LEN - offs,
82                                        MSG_WAITALL);
83                         memcpy(&tmp_msg, &log, MSG_DATA_HDR_LEN);
84                         struct msg_data_t *msg = malloc(MSG_DATA_HDR_LEN +
85                                                         tmp_msg.len);
86                         memcpy(msg, &tmp_msg, MSG_DATA_HDR_LEN);
87                         recvLen = recv(manager.target[index].socket,
88                                        (char *)msg + MSG_DATA_HDR_LEN,
89                                        msg->len, MSG_WAITALL);
90                         write_to_buf(msg);
91                         free(msg);
92                         continue;
93                 }
94
95                 // send to host
96                 if (likely(log.length > 0))
97                 {
98                         recvLen = recv(manager.target[index].socket,
99                                                         log.data, log.length, MSG_WAITALL);
100                         if(unlikely((recvLen == -1) || (recvLen != log.length)))        // consume as disconnect
101                         {
102                                 event = EVENT_STOP;
103                                 write(manager.target[index].event_fd, &event, sizeof(uint64_t));
104                                 break;
105                         }
106                 }
107
108                 log.data[log.length] = '\0';
109                 if(log.type == MSG_ALLOC)
110                 {
111                         manager.target[index].allocmem = str_to_int64(log.data);
112                         continue;               // don't send to host
113                 }
114                 else if(log.type == MSG_PID)
115                 {
116                         LOGI("MSG_PID arrived : %s\n", log.data);
117
118                         // only when first MSG_PID is arrived
119                         if(manager.target[index].pid == -1)
120                         {
121                                 char* barloc;
122                                 barloc = strchr(log.data, '|');
123                                 if(barloc == NULL)
124                                 {
125                                         // TODO: complain to host about wrong pid message
126                                         // send stop message to main thread
127                                         event = EVENT_STOP;
128                                         write(manager.target[index].event_fd, &event, sizeof(uint64_t));
129                                         break;
130                                 }
131                                 barloc[0] = '\0';
132                                 barloc++;
133
134                                 manager.target[index].pid = atoi(log.data);
135                                 event = EVENT_PID;
136                                 write(manager.target[index].event_fd, &event, sizeof(uint64_t));
137                         }
138                         continue;               // don't send to host
139                 }
140                 else if(log.type == MSG_TERMINATE)
141                 {
142                         // send stop message to main thread
143                         event = EVENT_STOP;
144                         write(manager.target[index].event_fd, &event,
145                               sizeof(uint64_t));
146
147                         struct msg_data_t *msg = malloc(sizeof(*msg) + /* pid */
148                                                         sizeof(uint32_t));
149                         fill_data_msg_head(msg, NMSG_TERMINATE, 0,
150                                            sizeof(uint32_t));
151                         *(uint32_t *) msg->payload = (uint32_t) manager.target[index].pid;
152                         write_to_buf(msg);
153                         free(msg);
154                         break;
155                 }
156                 else if(log.type == MSG_MSG)
157                 {
158                         // don't send to host
159                         LOGI("EXTRA MSG type=%d;len=%d;data='%s'\n", log.type, log.length, log.data);
160                         continue;
161                 }
162 #ifdef PRINT_TARGET_LOG
163                 else if(log.type == MSG_LOG)
164                 {
165                         switch(log.data[0])
166                         {
167                                 case '2':       // UI control creation log
168                                 case '3':       // UI event log
169                                 case '6':       // UI lifecycle log
170                                 case '7':       // screenshot log
171                                 case '8':       // scene transition log
172                                         LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
173                                         break;
174                                 default:
175                                         break;
176                         }
177                 }
178                 else if(log.type == MSG_IMAGE)
179                 {
180                         LOGI("MSG_IMAGE received\n");
181                 }
182                 else    // not MSG_LOG and not MSG_IMAGE
183                 {
184                         LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
185                 }
186 #endif
187
188                 // do not send any message to host until MSG_PID message arrives
189                 if(unlikely(pass == 0))
190                 {
191                         while(manager.target[index].initial_log == 0)
192                         {
193                                 sleep(0);
194                         }
195                 }
196                 pass = 1;
197         }
198
199         manager.target[index].recv_thread = -1;
200         return NULL;
201 }
202
203 int makeRecvThread(int index)
204 {
205         if (manager.target[index].socket == -1)
206                 return -1;
207
208         if (pthread_create(&(manager.target[index].recv_thread),
209                 NULL, recvThread, (void*)index) < 0)
210         {
211                 LOGE("Failed to create recv thread for socket (%d)\n",
212                                 manager.target[index].socket);
213                 return -1;
214         }
215
216         return 0;
217 }
218
219 //static
220 void* samplingThread(void* data)
221 {
222         int err, signo, i;
223         sigset_t waitsigmask;
224
225         LOGI("sampling thread started\n");
226
227         sigemptyset(&waitsigmask);
228         sigaddset(&waitsigmask, SIGALRM);
229         sigaddset(&waitsigmask, SIGUSR1);
230
231         while (1) {
232                 err = sigwait(&waitsigmask, &signo);
233                 if (err != 0) {
234                         LOGE("Failed to sigwait() in sampling thread\n");
235                         continue;
236                 }
237
238                 if (signo == SIGALRM) {
239                         int pidarr[MAX_TARGET_COUNT];
240                         int pidcount = 0;
241                         struct system_info_t sys_info;
242                         struct msg_data_t *msg;
243
244                         if (IS_SYSTEM_INFO_NEEDED()) {
245                                 for (i = 0; i < MAX_TARGET_COUNT; i++) {
246                                         if (manager.target[i].socket != -1 &&
247                                             manager.target[i].pid != -1)
248                                                 pidarr[pidcount++] = manager.target[i].pid;
249                                 }
250
251                                 if (get_system_info(&sys_info, pidarr, pidcount) == -1) {
252                                         LOGE("Cannot get system info\n");
253                                         //do not send sys_info because
254                                         //it is corrupted
255                                         continue;
256                                 }
257
258                                 msg = pack_system_info(&sys_info);
259                                 if (!msg) {
260                                         LOGE("Cannot pack system info\n");
261                                         reset_system_info(&sys_info);
262                                         continue;
263                                 }
264
265                                 write_to_buf(msg);
266
267                                 printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
268
269                                 free_msg_data(msg);
270                                 reset_system_info(&sys_info);
271                         }
272                         flush_buf();
273                 }
274                 else if(signo == SIGUSR1)
275                 {
276                         LOGI("SIGUSR1 catched\n");
277                         // end this thread
278                         break;
279                 }
280                 else
281                 {
282                         // never happen
283                         LOGE("This should never happen in sampling thread\n");
284                 }
285         }
286
287         LOGI("sampling thread ended\n");
288         return NULL;
289 }
290
291 // return 0 if normal case
292 // return minus value if critical error
293 // return plus value if non-critical error
294 int samplingStart()
295 {
296         struct itimerval timerval;
297         time_t sec = prof_session.conf.system_trace_period / 1000;
298         suseconds_t usec = prof_session.conf.system_trace_period * 1000 %
299                 1000000;
300
301         if(manager.sampling_thread != -1)       // already started
302                 return 1;
303
304         if (check_running_status(&prof_session) == 0) {
305                 LOGI("try to start sampling when running_status is 0\n");
306                 return 1;
307         }
308
309         if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
310         {
311                 LOGE("Failed to create sampling thread\n");
312                 return -1;
313         }
314
315         timerval.it_interval.tv_sec = sec;
316         timerval.it_interval.tv_usec = usec;
317         timerval.it_value.tv_sec = sec;
318         timerval.it_value.tv_usec = usec;
319         setitimer(ITIMER_REAL, &timerval, NULL);
320
321         return 0;
322 }
323
324 int samplingStop()
325 {
326         if(manager.sampling_thread != -1)
327         {
328                 struct itimerval stopval;
329
330                 // stop timer
331                 stopval.it_interval.tv_sec = 0;
332                 stopval.it_interval.tv_usec = 0;
333                 stopval.it_value.tv_sec = 0;
334                 stopval.it_value.tv_usec = 0;
335                 setitimer(ITIMER_REAL, &stopval, NULL);
336
337                 pthread_kill(manager.sampling_thread, SIGUSR1);
338                 LOGI("join sampling thread started\n");
339                 pthread_join(manager.sampling_thread, NULL);
340                 LOGI("join sampling thread done\n");
341
342                 manager.sampling_thread = -1;
343         }
344
345         return 0;
346 }
347
348 static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
349 {
350         return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
351                 ((int)tv1->tv_usec - (int)tv2->tv_usec);
352 }
353
354 static void *replay_thread(void *arg)
355 {
356         struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
357         int i = 0;
358         useconds_t ms;
359         useconds_t prev_event_offset = 0;
360
361         struct replay_event_t * pevent = NULL;
362
363         LOGI_th_rep("replay events thread started\n");
364         if (event_seq->event_num != 0)
365         {
366                 pevent = event_seq->events;
367         }
368
369         for (i = 0; i < event_seq->event_num; i++) {
370                 useconds_t event_offset = time_diff_us(&pevent->ev.time, &event_seq->tv);
371                 if (event_offset >= prev_event_offset)
372                         ms = event_offset - prev_event_offset;
373                 else
374                         ms = 0;
375
376 #ifdef THREAD_REPLAY_DEBUG
377                 print_replay_event(pevent, i + 1, "\t");
378 #endif
379                 LOGI_th_rep("%d) sleep %d\n", i, ms);
380                 usleep(ms);
381
382                 /* filter touch and key events here
383                    and process them separately */
384                 switch (pevent->id)
385                 {
386                 case INPUT_ID_TOUCH:
387                         LOGI_th_rep("event -> %s\n", INPUT_ID_STR_TOUCH);
388                         _device_write(g_touch_dev, &pevent->ev);
389                         break;
390
391                 case INPUT_ID_KEY:
392                         LOGI_th_rep("event -> %s\n", INPUT_ID_STR_KEY);
393                         _device_write(g_key_dev, &pevent->ev);
394                         break;
395                 default:
396                         LOGE("event -> UNKNOWN INPUT ID");
397                 }
398
399                 prev_event_offset = event_offset;
400
401                 pevent++;
402         }
403
404         LOGI("replay events thread finished\n");
405
406         return arg;
407 }
408
409 int start_replay()
410 {
411         if (manager.replay_thread != -1) // already started
412                 return 1;
413
414         if (pthread_create(&(manager.replay_thread),
415                            NULL,
416                            replay_thread,
417                            &prof_session.replay_event_seq) < 0)
418         {
419                 LOGE("Failed to create replay thread\n");
420                 return 1;
421         }
422
423         return 0;
424 }
425
426 void stop_replay()
427 {
428         if (manager.replay_thread == -1) {
429                 LOGI("replay thread not running\n");
430                 return;
431         }
432         LOGI("stopping replay thread\n");
433         pthread_cancel(manager.replay_thread);
434         pthread_join(manager.replay_thread, NULL);
435         manager.replay_thread = -1;
436         reset_replay_event_seq(&prof_session.replay_event_seq);
437         LOGI("replay thread joined\n");
438 }