[PROTO] Merge swap_draft <- tizen_2.2 as generic commit
[platform/core/system/swap-probe.git] / helper / libdaprobe.c
1 /*
2  *  DA probe
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  * Nikita Kalyazin <n.kalyazin@samsung.com>
12  * Anastasia Lyupa <a.lyupa@samsung.com>
13  * 
14  * This library is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License as published by the
16  * Free Software Foundation; either version 2.1 of the License, or (at your option)
17  * any later version.
18  * 
19  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
20  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
22  * License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with this library; if not, write to the Free Software Foundation, Inc., 51
26  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  *
28  * Contributors:
29  * - S-Core Co., Ltd
30  * - Samsung RnD Institute Russia
31  * 
32  */
33
34 #include <stdio.h>                      // for sprintf
35 #include <stdlib.h>                     // for getenv
36 #include <string.h>                     // for strstr
37 #include <stdbool.h>            // for bool
38 #include <stdint.h>                     // fot uint32_t,uint64_t
39 #include <stdarg.h>                     // for va_list, va_arg(__appendTypeLog)
40 #include <execinfo.h>           // for backtrace, backtrace_symbols
41 #include <unistd.h>                     // for write, alarm function, syscall
42 #include <pthread.h>            // for pthread_mutex_lock
43 #include <signal.h>
44
45 #include <sys/syscall.h>        // for syscall
46 #include <sys/time.h>           // for gettimeofday
47 #include <sys/socket.h>         // for socket, connect
48 #include <sys/un.h>                     // for sockaddr_un
49 #include <sys/timerfd.h>        // for timerfd
50
51 #include "probeinfo.h"
52 #include "dautil.h"
53 #include "dahelper.h"
54 #include "dacollection.h"
55
56 #include "binproto.h"
57
58 #define APP_INSTALL_PATH                "/opt/apps"
59 #define UDS_NAME                                "/tmp/da.socket"
60 #define TIMERFD_INTERVAL                100000000               // 0.1 sec
61
62 __thread int                    gProbeDepth = 0;
63 __thread unsigned int   gProbeBlockCount = 0;
64 __thread pid_t                  gTid = -1;
65
66 int                     g_timerfd = 0;
67 long            g_total_alloc_size = 0;
68 pthread_t       g_recvthread_id;
69
70 int log_fd = 0;
71
72 int getExecutableMappingAddress();
73
74 /******************************************************************************
75  * internal functions
76    (this means that these functions do not need to set enter/exit flag)
77  ******************************************************************************/
78
79 // runtime configure the probe option
80 static void _configure(char* configstr)
81 {
82         char buf[64];
83         gTraceInfo.optionflag = atoi(configstr);
84
85         sprintf(buf, "configure in probe : %s, %lx\n", configstr, gTraceInfo.optionflag);
86         PRINTMSG(buf);
87 }
88
89 // create socket to daemon and connect
90 static int createSocket(void)
91 {
92         ssize_t recvlen;
93         int clientLen, ret = 0;
94         struct sockaddr_un clientAddr;
95         char buf[16];
96         log_t log;
97
98         if((gTraceInfo.socket.daemonSock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) != -1)
99         {
100                 bzero(&clientAddr, sizeof(clientAddr));
101                 clientAddr.sun_family = AF_UNIX;
102                 sprintf(clientAddr.sun_path, "%s", UDS_NAME);
103
104                 clientLen = sizeof(clientAddr);
105                 if(connect(gTraceInfo.socket.daemonSock, (struct sockaddr *)&clientAddr, clientLen) >= 0)
106                 {
107                         // recv initial configuration value
108                         recvlen = recv(gTraceInfo.socket.daemonSock, &log,
109                                         sizeof(log.type) + sizeof(log.length), MSG_WAITALL);
110
111                         if(recvlen > 0) // recv succeed
112                         {
113                                 if(log.length > 0)
114                                 {
115                                         if(log.length >= DA_LOG_MAX)
116                                                 log.length = DA_LOG_MAX - 1;
117                                         recvlen = recv(gTraceInfo.socket.daemonSock, log.data,
118                                                 log.length, MSG_WAITALL);
119                                 }
120                                 else
121                                 {
122                                         log.length = 0;
123                                 }
124
125                                 log.data[log.length] = '\0';
126
127                                 if(log.type == MSG_CONFIG)
128                                 {
129                                         _configure(log.data);
130                                 }
131                                 else
132                                 {
133                                         // unexpected case
134                                 }
135                         }
136                         else if(recvlen < 0)
137                         {
138                                 char buf[64];
139                                 sprintf(buf, "recv failed in socket creation with error(%d)\n", recvlen);
140                         }
141                         else    // closed by other peer
142                         {
143
144                         }
145                         sprintf(buf, "%d|%u", getpid(), gTraceInfo.app.startTime);
146                         printLogStr(buf, MSG_PID);
147                         PRINTMSG("createSocket connect() success\n");
148                 }
149                 else
150                 {
151                         close(gTraceInfo.socket.daemonSock);
152                         gTraceInfo.socket.daemonSock = -1;
153                         ret = -1;
154                 }
155         }
156         else
157         {
158                 ret = -1;
159         }
160
161         return ret;
162 }
163
164
165 // parse backtrace string and find out the caller of probed api function
166 // return 0 if caller is user binary, otherwise return 1
167 static int determineCaller(char* tracestring)
168 {
169         char *substr;
170
171         // determine whether saveptr (caller binary name) is user binary or not
172         substr = strstr(tracestring, APP_INSTALL_PATH);
173
174         if(substr == NULL)      // not user binary
175                 return 1;
176         else                            // user binary
177                 return 0;
178 }
179
180 // return current thread id
181 static pid_t _gettid()
182 {
183         if(gTid == -1)
184                 gTid = syscall(__NR_gettid);    // syscall is very expensive
185         return gTid;
186 }
187
188 static void* recvThread(void* data)
189 {
190         fd_set readfds, workfds;
191         int maxfd = 0, rc;
192         uint64_t xtime;
193         ssize_t recvlen;
194         log_t log;
195         sigset_t profsigmask;
196
197         if(gTraceInfo.socket.daemonSock == -1)
198                 return NULL;
199
200         TRACE_STATE_SET(TS_RECV_THREAD);
201
202         sigemptyset(&profsigmask);
203         sigaddset(&profsigmask, SIGPROF);
204         pthread_sigmask(SIG_BLOCK, &profsigmask, NULL);
205
206         FD_ZERO(&readfds);
207         if(g_timerfd > 0)
208         {
209                 maxfd = g_timerfd;
210                 FD_SET(g_timerfd, &readfds);
211         }
212         if(maxfd < gTraceInfo.socket.daemonSock)
213                 maxfd = gTraceInfo.socket.daemonSock;
214         FD_SET(gTraceInfo.socket.daemonSock, &readfds);
215
216         while(1)
217         {
218                 workfds = readfds;
219                 rc = select(maxfd + 1, &workfds, NULL, NULL, NULL);
220                 if(rc < 0)
221                 {
222                         continue;
223                 }
224
225                 if(g_timerfd > 0 && FD_ISSET(g_timerfd, &workfds))
226                 {
227                         recvlen = read(g_timerfd, &xtime, sizeof(xtime));
228                         if(recvlen > 0)
229                         {
230                                 log.length = sprintf(log.data, "%ld", g_total_alloc_size);
231                                 // printLog(&log, MSG_ALLOC);
232                         }
233                         else
234                         {
235                                 // read failed
236                         }
237                         continue;
238                 }
239                 else if(FD_ISSET(gTraceInfo.socket.daemonSock, &workfds))
240                 {
241                         recvlen = recv(gTraceInfo.socket.daemonSock, &log,
242                                         sizeof(log.type) + sizeof(log.length), MSG_WAITALL);
243
244                         if(recvlen > 0) // recv succeed
245                         {
246                                 if(log.length > 0)
247                                 {
248                                         if(log.length >= DA_LOG_MAX)
249                                                 log.length = DA_LOG_MAX - 1;
250                                         recvlen = recv(gTraceInfo.socket.daemonSock, log.data,
251                                                 log.length, MSG_WAITALL);
252                                 }
253                                 else
254                                 {
255                                         log.length = 0;
256                                 }
257
258                                 log.data[log.length] = '\0';
259
260                                 if(log.type == MSG_CONFIG)
261                                 {
262                                         _configure(log.data);
263                                 }
264                                 else if(log.type == MSG_STOP)
265                                 {
266                                         exit(0);
267                                 }
268                                 else
269                                 {
270                                         char buf[64];
271                                         sprintf(buf, "recv unknown message(%d)\n", log.type);
272                                         continue;
273                                 }
274                         }
275                         else if(recvlen == 0)   // closed by other peer
276                         {
277                                 close(gTraceInfo.socket.daemonSock);
278                                 gTraceInfo.socket.daemonSock = -1;
279                                 break;
280                         }
281                         else    // recv error
282                         {
283                                 char buf[64];
284                                 sprintf(buf, "recv failed in recv thread with error(%d)\n", recvlen);
285                                 continue;
286                         }
287                 }
288                 else    // unknown case
289                 {
290                         continue;
291                 }
292         }
293
294         TRACE_STATE_UNSET(TS_RECV_THREAD);
295         return NULL;
296 }
297
298 /*****************************************************************************
299  * initialize / finalize function
300  *****************************************************************************/
301
302 void __attribute__((constructor)) _init_probe()
303 {
304         struct timeval ttime;
305         struct itimerspec ctime;
306
307         TRACE_STATE_SET(TS_INIT);
308
309         initialize_hash_table();
310
311         initialize_screencapture();
312
313         initialize_event();
314
315         getExecutableMappingAddress();
316
317         // get app start time
318         gettimeofday(&ttime, NULL);
319         gTraceInfo.app.startTime = ((ttime.tv_sec * 10000 + (ttime.tv_usec/100)));
320
321         // create socket for communication with da_daemon
322         if(createSocket() == 0)
323         {
324                 // create timerfd
325                 g_timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
326                 if(g_timerfd > 0)
327                 {
328                         ctime.it_value.tv_sec = 0;
329                         ctime.it_value.tv_nsec = TIMERFD_INTERVAL;
330                         ctime.it_interval.tv_sec = 0;
331                         ctime.it_interval.tv_nsec = TIMERFD_INTERVAL;
332                         if(0 > timerfd_settime(g_timerfd, 0, &ctime, NULL))
333                         {
334                                 PRINTMSG("failed to set timerfd\n");
335                                 close(g_timerfd);
336                                 g_timerfd = 0;
337                         }
338                 }
339                 else
340                 {
341                         PRINTMSG("failed to create timerdf\n");
342                 }
343
344                 // create recv Thread
345                 if(pthread_create(&g_recvthread_id, NULL, recvThread, NULL) < 0)        // thread creation failed
346                 {
347                         PRINTMSG("failed to crate recv thread\n");
348                 }
349                 update_heap_memory_size(true, 0);
350         }
351         else
352         {
353
354         }
355
356         PRINTMSG("dynamic analyzer probe helper so loading...\n");
357
358         gTraceInfo.init_complete = 1;
359         TRACE_STATE_UNSET(TS_INIT);
360 }
361
362 void __attribute__((destructor)) _fini_probe()
363 {
364         int i;
365         TRACE_STATE_SET(TS_FINIT);
366
367         gTraceInfo.init_complete = -1;
368         PRINTMSG("dynamic analyzer probe helper so unloading...\n");
369
370         remove_all_glist();
371
372         // close timerfd
373         if(g_timerfd > 0)
374                 close(g_timerfd);
375
376         // close socket
377         if(gTraceInfo.socket.daemonSock != -1)
378         {
379                 printLogStr(NULL, MSG_TERMINATE);
380                 close(gTraceInfo.socket.daemonSock);
381                 gTraceInfo.socket.daemonSock = -1;
382         }
383
384         finalize_event();
385
386         finalize_screencapture();
387
388         finalize_hash_table();
389
390         for(i = 0; i < NUM_ORIGINAL_LIBRARY; i++)
391         {
392                 if(lib_handle[i] != NULL)
393                 {
394                         dlclose(lib_handle[i]);
395                 }
396         }
397
398         TRACE_STATE_UNSET(TS_FINIT);
399 }
400
401
402 /**************************************************************************
403  * Helper APIs
404  **************************************************************************/
405
406 /************************************************************************
407  * manipulate and print log functions
408  ************************************************************************/
409
410 /*bool printLog(log_t* log, int msgType)
411 {
412         int res;
413         if(unlikely(gTraceInfo.socket.daemonSock == -1))
414                 return false;
415
416         if(unlikely(log == NULL))
417                 return false;
418
419         TRACE_STATE_SET(TS_PRINT_LOG);
420         log->type = msgType;
421         pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
422         res = send(gTraceInfo.socket.daemonSock, log, sizeof(log->type) + sizeof(log->length) + log->length, 0);
423         pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
424         TRACE_STATE_UNSET(TS_PRINT_LOG);
425
426         return true;
427 }*/
428
429 bool printLogStr(const char* str, int msgType)
430 {
431         int res;
432         log_t log;
433
434         if(unlikely(gTraceInfo.socket.daemonSock == -1))
435                 return false;
436
437         TRACE_STATE_SET(TS_PRINT_LOG);
438
439         log.type = msgType;
440         if(str)
441         {
442                 sprintf(log.data, "%s", str);
443                 log.length = strlen(str);
444         }
445         else
446         {
447                 log.length = 0;
448         }
449
450         pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
451         res = send(gTraceInfo.socket.daemonSock, &log, sizeof(log.type) + sizeof(log.length) + log.length, MSG_DONTWAIT);
452         pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
453
454         TRACE_STATE_UNSET(TS_PRINT_LOG);
455
456         return true;
457 }
458
459 // return 0 for successful case
460 // return non-zero for error
461 // if token is NULL then use DEFAULT TOKEN "`,"
462 // if token is not NULL then insert DEFAULT TOKEN before append input
463 int __appendTypeLog(log_t* log, int nInput, char* token, ...)
464 {
465         static char* default_token = DEFAULT_TOKEN;
466         va_list p_arg;
467         int i, type;
468         char* seperator = default_token;
469
470         if(nInput <= 0 || log == NULL)
471                 return -1;
472
473         TRACE_STATE_SET(TS_APPEND_TYPE_LOG);
474
475         va_start(p_arg, token);
476
477         if(token != NULL)
478                 seperator = token;
479
480         for(i = 0; i < nInput; i++)
481         {
482                 type = va_arg(p_arg, int);
483
484                 if(likely(log->length > 0))     // append token or default token
485                 {
486                         if(unlikely(i == 0))
487                                 log->length += sprintf(log->data + log->length, "%s", default_token);
488                         else
489                                 log->length += sprintf(log->data + log->length, "%s", seperator);
490                 }
491
492                 switch(type)
493                 {
494                 case VT_INT:
495                         log->length += sprintf(log->data + log->length, "%d", va_arg(p_arg, int));
496                         break;
497                 case VT_UINT:
498                         log->length += sprintf(log->data + log->length, "%u", va_arg(p_arg, unsigned int));
499                         break;
500                 case VT_LONG:
501                         log->length += sprintf(log->data + log->length, "%ld", va_arg(p_arg, long));
502                         break;
503                 case VT_ULONG:
504                         log->length += sprintf(log->data + log->length, "%lu", va_arg(p_arg, unsigned long));
505                         break;
506                 case VT_STR:
507                         log->length += sprintf(log->data + log->length, "%s", va_arg(p_arg, char*));
508                         break;
509                 case VT_CHAR:   // 'char' is promoted to 'int' when passed through '...'
510                         log->length += sprintf(log->data + log->length, "%c", va_arg(p_arg, int));
511                         break;
512                 case VT_PTR:
513                         log->length += sprintf(log->data + log->length, "%p", va_arg(p_arg, void*));
514                         break;
515                 case VT_NULL:
516                         va_arg(p_arg, unsigned int);
517                         break;
518                 case VT_OFF_T:
519                         log->length += sprintf(log->data + log->length, "%ld", va_arg(p_arg, off_t));
520                         break;
521                 case VT_SIZE_T:
522                         log->length += sprintf(log->data + log->length, "%u", va_arg(p_arg, size_t));
523                         break;
524                 case VT_SSIZE_T:
525                         log->length += sprintf(log->data + log->length, "%d", va_arg(p_arg, ssize_t));
526                         break;
527                 case VT_SOCKLEN_T:
528                         log->length += sprintf(log->data + log->length, "%u", va_arg(p_arg, socklen_t));
529                         break;
530                 case VT_UINT16_T:       // 'uint16_t' is promoted to 'int' when passed through '...'
531                         log->length += sprintf(log->data + log->length, "%u", va_arg(p_arg, int));
532                         break;
533                 case VT_UINT32_T:
534                         log->length += sprintf(log->data + log->length, "%u", va_arg(p_arg, uint32_t));
535                         break;
536                 case VT_UINT64_T:
537                         log->length += sprintf(log->data + log->length, "%llu", va_arg(p_arg, uint64_t));
538                         break;
539                 case VT_MODE_T:
540                         log->length += sprintf(log->data + log->length, "%u", va_arg(p_arg, mode_t));
541                         break;
542 /*              case VT_DEV_T:
543                         log->length += sprintf(log->data + log->length, "%lu", va_arg(p_arg, dev_t));
544                         break;
545                 case VT_NFDS_T:
546                         log->length += sprintf(log->data + log->length, "%lu", va_arg(p_arg, nfds_t));
547                         break;*/
548                 default:
549                         va_end(p_arg);
550                         TRACE_STATE_UNSET(TS_APPEND_TYPE_LOG);
551                         return -1;
552                 }
553         }
554
555         va_end(p_arg);
556
557         TRACE_STATE_UNSET(TS_APPEND_TYPE_LOG);
558         return 0;
559 }
560
561 // get backtrace string
562 // return stack depth if succeed, otherwise return 0
563 // parameter 'log' cannot be null
564 int getBacktraceString(log_t* log, int bufsize)
565 {
566         void* array[MAX_STACK_DEPTH];
567         char** strings = NULL;
568         size_t i, size;
569         int initsize;
570         int stringlen;
571
572         if(log == NULL)
573                 return 0;
574
575         TRACE_STATE_SET(TS_BACKTRACE);
576
577         initsize = log->length;
578         log->data[log->length] = '\0';  // is this necessary ?
579         size = backtrace(array, MAX_STACK_DEPTH);
580         if(likely(size > TRIM_STACK_DEPTH))
581         {
582                 strings = BACKTRACE_SYMBOLS(array + TRIM_STACK_DEPTH, size - TRIM_STACK_DEPTH);
583
584                 if(likely(strings != NULL))
585                 {
586                         for(i = TRIM_STACK_DEPTH; i < size; i++)
587                         {
588                                 stringlen = strlen(strings[i - TRIM_STACK_DEPTH]) + 14;
589                                 if(log->length + stringlen >= bufsize + initsize)
590                                         break;
591
592                                 log->length += sprintf(log->data + log->length, "%010u`,%s`,", (unsigned int)(array[i]), strings[i - TRIM_STACK_DEPTH]);
593                         }
594                         log->data[log->length-2] = '\0';
595                         log->length -= 2;
596                         free(strings);
597                 }
598                 else    // failed to get backtrace symbols
599                 {
600                         // just print trace address
601                         for(i = TRIM_STACK_DEPTH; i < size; i++)
602                         {
603                                 stringlen = 23;
604                                 if(log->length + stringlen >= bufsize + initsize)
605                                         break;
606
607                                 log->length += sprintf(log->data + log->length, "%010u`,(unknown)`,", (unsigned int)(array[i]));
608                         }
609                         log->data[log->length-2] = '\0';
610                         log->length -= 2;
611                 }
612
613                 TRACE_STATE_UNSET(TS_BACKTRACE);
614                 return (int)(size - TRIM_STACK_DEPTH);
615         }
616         else
617         {
618                 TRACE_STATE_UNSET(TS_BACKTRACE);
619                 return 0;
620         }
621 }
622
623 /*************************************************************************
624  * probe block control functions
625  *************************************************************************/
626 int preBlockBegin(void* caller, bool bFiltering, enum DaOptions option)
627 {
628         bool user = false;
629         void* tarray[1];
630         char** strings;
631
632         if(gSTrace != 0 || gProbeDepth != 0)
633                 return 0;
634
635         if(gTraceInfo.init_complete <= 0)
636                 return 0;
637
638         if((gTraceInfo.optionflag & option) == 0)
639                 return 0;
640
641         TRACE_STATE_SET(TS_ENTER_PROBE_BLOCK);
642
643         if(gTraceInfo.exec_map.map_start != NULL)
644         {
645                 // address comparison
646                 if(caller >= gTraceInfo.exec_map.map_start &&
647                                 caller <= gTraceInfo.exec_map.map_end)
648                 {
649                         user = true;
650                 }
651                 else
652                 {
653                         // nothing to do
654                 }
655         }
656         else
657         {
658                 // backtrace for filtering
659                 tarray[0] = caller;
660                 strings = BACKTRACE_SYMBOLS(tarray, 1);
661                 if(strings != NULL)
662                 {
663                         if((determineCaller(strings[0]) == 0))
664                                 user = true;
665                         free(strings);
666                 }
667                 else
668                 {
669                         // nothing to do
670                 }
671         }
672
673         if(user)
674         {
675                 gProbeDepth++;
676                 return 2;       // user call
677         }
678         else
679         {
680                 if(bFiltering)
681                 {
682                         TRACE_STATE_UNSET(TS_ENTER_PROBE_BLOCK);
683                         return 0;       // not probing
684                 }
685                 else
686                 {
687                         gProbeDepth++;
688                         return 1;       // internal call
689                 }
690         }
691 }
692
693 int postBlockBegin(int preresult)
694 {
695         if(preresult)
696         {
697                 TRACE_STATE_SET(TS_ENTER_PROBE_BLOCK);
698         }
699
700         return preresult;
701 }
702
703 void preBlockEnd()
704 {
705         TRACE_STATE_UNSET(TS_ENTER_PROBE_BLOCK);
706 }
707
708 void postBlockEnd()
709 {
710         gProbeDepth--;
711         TRACE_STATE_UNSET(TS_ENTER_PROBE_BLOCK);
712 }
713
714 // for block that have to be run
715 void probeBlockStart()
716 {
717         gProbeBlockCount++;
718         if(gProbeBlockCount == 1)
719                 TRACE_STATE_SET(TS_PROBE);
720 }
721
722 void probeBlockEnd()
723 {
724         if(gProbeBlockCount == 1)
725                 TRACE_STATE_UNSET(TS_PROBE);
726         gProbeBlockCount--;
727 }
728
729 /*************************************************************************
730  * helper info getter functions
731  *************************************************************************/
732 // return current time in 1/10000 sec unit
733 unsigned long getCurrentTime()
734 {
735         struct timeval cTime;
736
737         gettimeofday(&cTime, NULL);
738
739         return (unsigned long)((cTime.tv_sec * 10000 + (cTime.tv_usec/100)));
740 }
741
742 unsigned int getCurrentEventIndex()
743 {
744         return gTraceInfo.index.eventIndex;
745 }
746
747 unsigned int getCallDepth()
748 {
749         return gProbeDepth;
750 }
751
752 unsigned long getTraceState()
753 {
754         return gSTrace;
755 }
756
757 /************************************************************************
758  * probe functions
759  ************************************************************************/
760 bool setProbePoint(probeInfo_t* iProbe)
761 {
762         if(unlikely(iProbe == NULL))
763         {
764                 return false;
765         }
766
767         TRACE_STATE_SET(TS_SET_PROBE_POINT);
768
769         // atomic operaion(gcc builtin) is more expensive then pthread_mutex
770         pthread_mutex_lock(&(gTraceInfo.index.eventMutex));     
771         iProbe->eventIndex = gTraceInfo.index.eventIndex++;
772         pthread_mutex_unlock(&(gTraceInfo.index.eventMutex));
773
774         iProbe->currentTime = getCurrentTime();
775         iProbe->pID = getpid();
776         iProbe->tID = _gettid();
777         iProbe->callDepth = gProbeDepth;
778
779         TRACE_STATE_UNSET(TS_SET_PROBE_POINT);
780         return true;
781 }
782
783 // update heap memory size through socket
784 // return 0 if size is updated through socket
785 // return 1 if size is updated into global variable
786 int update_heap_memory_size(bool isAdd, size_t size)
787 {
788         long tmp;
789         if(isAdd)
790         {
791                 tmp = __sync_add_and_fetch(&g_total_alloc_size, (long)size);
792         }
793         else
794         {
795                 tmp = __sync_sub_and_fetch(&g_total_alloc_size, (long)size);
796         }
797
798         return 0;
799 }
800
801