"Fossies" - the Fresh Open Source Software Archive

Member "FunctionCheck-3.2.0/src/libfc/fc_com.c" (26 May 2012, 10204 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * FunctionCheck profiler
    3  * (C) Copyright 2000-2012 Yannick Perret
    4  * 
    5  *  This program is free software; you can redistribute it and/or
    6  *  modify it under the terms of the GNU General Public License as
    7  *  published by the Free Software Foundation; either version 2 of the
    8  *  License, or (at your option) any later version.
    9  *
   10  *  This program is distributed in the hope that it will be useful,
   11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13  *  General Public License for more details.
   14  *
   15  *  You should have received a copy of the GNU General Public License
   16  *  along with this program; if not, write to the Free Software
   17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18  */
   19 
   20 /** fc_com.h: manage coms between profiled program and the manager **/
   21 
   22 #include <errno.h>
   23 #include <stdio.h>
   24 #include "fc_com.h"
   25 #include "fc_time.h"
   26 #include "fc_global.h"
   27 #include "fc_tools.h"
   28 #include "fc_fifo.h"
   29 
   30 #ifndef FC_NO_THREAD
   31 #include <pthread.h>
   32 #endif /* FC_NOTHREAD */
   33 
   34 /** flag to indicate if the lib is compiled with threads **/
   35 #ifndef FC_NO_THREAD
   36 int fc_allow_thread_hard=1;
   37 #else
   38 int fc_allow_thread_hard=0;
   39 #endif
   40 
   41 /** sizes for each type **/
   42 unsigned int fc_type_sizes[FC_TYPE_MAX] =
   43 {
   44     sizeof (FC_CEnter),
   45     sizeof (FC_CExit),
   46     sizeof (FC_CMalloc),
   47     sizeof (FC_CFree),
   48     sizeof (FC_CMemalign),
   49     sizeof (FC_CRealloc),
   50     sizeof (FC_CQuit),
   51     sizeof (FC_CDlopen),
   52     sizeof (FC_CDlclose),
   53     sizeof (FC_CDlsym),
   54     sizeof (FC_CParent),
   55     sizeof (FC_CFork),
   56     sizeof (FC_CThread),
   57     sizeof (FC_CTime)
   58 };
   59 
   60 /* maximum element size of fc_type_sizes[] */
   61 static unsigned int fc_max_tsize = 0;
   62 
   63 /* FIFO for the com */
   64 static FC_FIFO fc_com_fifo = FC_FIFO_NDEF;
   65 
   66 /* mode */
   67 int fc_used_mode=0;
   68 
   69 /* current ID for SINGLE mode */
   70 static int fc_single_id = 0;
   71 
   72 /** internal data for messages **/
   73 static unsigned char fc_buffer_total[512];
   74 /* buffer for messages */
   75 static unsigned char *fc_buffer_write = NULL;
   76 /* offset to write the pid */
   77 static unsigned char *fc_buffer_opid  = NULL;
   78 /* offset to write the tid */
   79 static unsigned char *fc_buffer_otid  = NULL;
   80 /* offset to write the data */
   81 static unsigned char *fc_buffer_odata = NULL;
   82 
   83 /* impossible to code as inline due to containing #ifdef.
   84    Easier to code too as a function instead of inline. */
   85 static inline void build_fc_com(void** com, unsigned int *curid, unsigned int type)
   86 {
   87     unsigned char *buffer;
   88     
   89     if (fc_buffer_opid != NULL)
   90     {
   91         *curid = getpid();
   92     }
   93     else
   94     {
   95         /* else if needed the tid */
   96         if (fc_buffer_otid != NULL)
   97         {
   98 #ifdef FC_NO_THREAD
   99             *curid = getpid();
  100 #else
  101             *curid = (unsigned int) pthread_self();
  102 #endif
  103         }
  104     }
  105 
  106     buffer = fc_fifo_write_single(fc_com_fifo, /* sizeof(int) for id + fc_max_tsize + sizeof(char) for type */ fc_max_tsize, *curid);
  107     if (buffer == 0)
  108     {
  109         fc_message("failed to write to fifo buffer, full already.");
  110         *com = 0;
  111         return;
  112     }
  113 
  114     buffer[0] = (char) type;
  115     buffer++;
  116 
  117     if (fc_buffer_opid != NULL)
  118     {
  119         *((unsigned int*) buffer) = *curid;
  120         buffer += sizeof (int);
  121     }
  122     else
  123     {
  124         if (fc_buffer_otid != NULL)
  125         {
  126             *((unsigned int*) buffer) = *curid;
  127             buffer += sizeof (int);
  128         }
  129     }
  130 
  131     *com = (void*)buffer;
  132     
  133     return;
  134 }
  135 
  136 #define     DECLARE_FC_COM(struct_)    \
  137                                                 unsigned int curid = fc_single_id; \
  138                                                 struct_* com;
  139 
  140 #define     BUILD_FC_COM(type)      build_fc_com((void**)&com, &curid, type); \
  141                                     if (com == 0) \
  142                                         return;
  143 
  144 #define     SEND_FC_COM()       fc_fifo_write_single_done(fc_com_fifo, curid);
  145 
  146 /* functions */
  147 void fc_com_enter(void *f, void *s)
  148 {
  149     DECLARE_FC_COM(FC_CEnter);
  150 
  151     BUILD_FC_COM(FC_TYPE_ENTER);
  152 
  153     com->to = f;
  154     com->from = s;
  155     fc_gettimeofday(&(com->time));
  156 
  157     SEND_FC_COM();
  158 }
  159 
  160 void fc_com_exit(void *f, void *s)
  161 {
  162     DECLARE_FC_COM(FC_CExit);
  163 
  164     BUILD_FC_COM(FC_TYPE_EXIT);
  165 
  166     com->to = f;
  167     com->from = s;
  168     fc_gettimeofday(&(com->time));
  169 
  170     SEND_FC_COM();
  171 }
  172 
  173 void fc_com_malloc(void *ptr, unsigned int size, void *where)
  174 {
  175     DECLARE_FC_COM(FC_CMalloc);
  176 
  177     BUILD_FC_COM(FC_TYPE_MALLOC);
  178 
  179     com->ptr = ptr;
  180     com->where = where;
  181     com->size = size;
  182 
  183     SEND_FC_COM();
  184 }
  185 
  186 void fc_com_free(void *ptr, void *where)
  187 {
  188     DECLARE_FC_COM(FC_CFree);
  189 
  190     BUILD_FC_COM(FC_TYPE_FREE);
  191 
  192     com->ptr = ptr;
  193     com->where = where;
  194 
  195     SEND_FC_COM();
  196 }
  197 
  198 void fc_com_realloc(void *ptr, void *inc, unsigned int size, void *where)
  199 {
  200     DECLARE_FC_COM(FC_CRealloc);
  201 
  202     BUILD_FC_COM(FC_TYPE_REALLOC);
  203 
  204     com->ptr = ptr;
  205     com->old = inc;
  206     com->size = size;
  207     com->where = where;
  208 
  209     SEND_FC_COM();
  210 }
  211 
  212 void fc_com_memalign(void *ptr, unsigned int align, unsigned int size, void *where)
  213 {
  214     DECLARE_FC_COM(FC_CMemalign);
  215 
  216     BUILD_FC_COM(FC_TYPE_MEMALIGN);
  217 
  218     com->ptr = ptr;
  219     com->align = align;
  220     com->size = size;
  221     com->where = where;
  222 
  223     SEND_FC_COM();
  224 }
  225 
  226 void fc_com_dlopen(void *ptr, const char *filename, int flag)
  227 {
  228     DECLARE_FC_COM(FC_CDlopen);
  229 
  230     BUILD_FC_COM(FC_TYPE_DLOPEN);
  231 
  232     com->handle = ptr;
  233     com->flag = flag;
  234     sprintf(com->name, "%31s", filename);
  235 
  236     SEND_FC_COM();
  237 }
  238 
  239 void fc_com_dlclose(void *handle)
  240 {
  241     DECLARE_FC_COM(FC_CDlclose);
  242 
  243     BUILD_FC_COM(FC_TYPE_DLCLOSE);
  244 
  245     com->handle = handle;
  246 
  247     SEND_FC_COM();
  248 }
  249 
  250 void fc_com_dlsym(void *ptr, void *handle, char *symbol)
  251 {
  252     DECLARE_FC_COM(FC_CDlsym);
  253 
  254     BUILD_FC_COM(FC_TYPE_DLSYM);
  255 
  256     com->handle = handle;
  257     com->fnc = ptr;
  258     sprintf(com->name, "%31s", symbol);
  259 
  260     SEND_FC_COM();
  261 }
  262 
  263 void fc_com_fork(int pid)
  264 {
  265     DECLARE_FC_COM(FC_CFork);
  266 
  267     BUILD_FC_COM(FC_TYPE_FORK);
  268 
  269     com->child = pid;
  270     fc_gettimeofday(&(com->time));
  271 
  272     SEND_FC_COM();
  273 }
  274 
  275 void fc_com_thread(int tid)
  276 {
  277     DECLARE_FC_COM(FC_CThread);
  278 
  279     BUILD_FC_COM(FC_TYPE_THREAD);
  280 
  281     com->thread = tid;
  282     fc_gettimeofday(&(com->time));
  283 
  284     SEND_FC_COM();
  285 }
  286 
  287 void fc_com_parent(int pid)
  288 {
  289     DECLARE_FC_COM(FC_CParent);
  290 
  291     BUILD_FC_COM(FC_TYPE_PARENT);
  292 
  293     com->parent = pid;
  294 
  295     SEND_FC_COM();
  296 }
  297 
  298 void fc_com_quit(void)
  299 {
  300     DECLARE_FC_COM(FC_CQuit);
  301 
  302     BUILD_FC_COM(FC_TYPE_QUIT);
  303 
  304     fc_gettimeofday(&(com->time));
  305 
  306     SEND_FC_COM();
  307 }
  308 
  309 /* init the communication process and start the manager */
  310 int fc_com_init(int mode, int buffer_size, unsigned int *shmid)
  311 {
  312     int i;
  313 
  314     fc_debug("entering fc_com_init");
  315 
  316     /* set the pointers */
  317     fc_used_mode = mode;
  318     if (mode == FC_MODE_SINGLE)
  319     {
  320         fc_buffer_write = fc_buffer_total;
  321         fc_buffer_opid = NULL;
  322         fc_buffer_otid = NULL;
  323         fc_buffer_odata = &(fc_buffer_total[1]);
  324     }
  325     else
  326         if (mode == FC_MODE_FORK)
  327     {
  328         fc_buffer_write = fc_buffer_total;
  329         fc_buffer_opid = &(fc_buffer_total[1]);
  330         fc_buffer_otid = NULL;
  331         fc_buffer_odata = &(fc_buffer_total[1 + sizeof (int) ]);
  332     }
  333     else
  334         if (mode == FC_MODE_THREAD)
  335     {
  336         fc_buffer_write = fc_buffer_total;
  337         fc_buffer_opid = NULL;
  338         fc_buffer_otid = &(fc_buffer_total[1]);
  339         fc_buffer_odata = &(fc_buffer_total[1 + sizeof (int) ]);
  340     }
  341     else
  342     {
  343         fc_message("invalid mode for communication initialisation (%d).");
  344         return (0);
  345     }
  346 
  347     /* compute the largest element size */
  348     for (i = 0; i <= FC_TYPE_MAX; i++)
  349     {
  350         fc_max_tsize = (fc_type_sizes[i] > fc_max_tsize) ? fc_type_sizes[i] : fc_max_tsize;
  351     }
  352 
  353     fc_max_tsize += (sizeof(char) /*type*/ + sizeof(int) /*pid/tid*/);
  354     
  355     /* create the FIFO */
  356     fc_com_fifo = fc_fifo_create(buffer_size, fc_max_tsize, shmid, mode == FC_MODE_SINGLE ? 1 : 0);
  357     if (fc_com_fifo == FC_FIFO_NDEF)
  358     {/* error */
  359         fc_message("error while opening fifo");
  360         return (0);
  361     }
  362 
  363     fc_debug("FIFO '%d' mapped at %p", shmid, (void*) fc_com_fifo);
  364 
  365     /* single-mode PID */
  366     fc_single_id = (int) getpid();
  367 
  368     /* ok */
  369     return (1);
  370 }
  371 
  372 int fc_com_start_manager(unsigned int shmid)
  373 {
  374     int i, ret;
  375     char *args[64];
  376     char temp[1024];
  377     
  378     /* args for the manager */
  379     for (i = 0; i < 64; i++)
  380     {
  381         args[i] = NULL;
  382     }
  383 
  384     args[0] = strdup("fcmanager"); /* to change */
  385     sprintf(temp, "%d", shmid);
  386     args[1] = strdup(temp);
  387 
  388     fc_debug("args [%s] [%s]", args[0], args[1]);
  389 
  390     /* fork */
  391     fc_debug("starting manager");
  392     if ((ret = fork()) == 0)
  393     {/* the child */
  394         /* start the manager */
  395         fc_debug("CHILD SIDE: -> execvp");
  396         execvp(args[0], args);
  397 
  398         fc_message("error: unable to start profile manager.");
  399         fc_message_fatal(FC_ERR_EXEC, "unable to continute treatments.");
  400     }
  401 
  402     fc_debug("fork -> %d", ret);
  403     if (ret < 0)
  404     {
  405         fc_message("error: unable to fork.");
  406         fc_message_fatal(FC_ERR_FORK, "unable to continute treatments.");
  407     }
  408 
  409     return ret;
  410 }
  411 
  412 /* stop the communication process */
  413 int fc_com_fini(unsigned int shmid)
  414 {
  415   /* close the com */
  416   fc_fifo_close(fc_com_fifo, shmid, 0 /* don't delete shm, fcmanager still processing */);
  417 
  418   /* nothing to do */
  419   return(1);
  420 }
  421 
  422 /* send an init message */
  423 int fc_com_write_init(FC_INIT *init)
  424 {
  425     fc_debug("writing FC_INIT structure");
  426     if (fc_used_mode == FC_MODE_SINGLE)
  427     {
  428         init->first_pid = getpid();
  429     }
  430     else
  431         if (fc_used_mode == FC_MODE_FORK)
  432     {
  433         init->first_pid = getpid();
  434     }
  435     else
  436         if (fc_used_mode == FC_MODE_THREAD)
  437     {
  438 #ifndef FC_NO_THREAD
  439         init->first_pid = pthread_self();
  440 #else
  441         init->first_pid = getpid();
  442 #endif
  443     }
  444     else
  445     {
  446         fc_message("invalid mode for communication initialisation (%d).");
  447         return 0;
  448     }
  449 
  450     fc_fifo_write_init(fc_com_fifo, init, sizeof(FC_INIT), fc_single_id);
  451 
  452     return 1;
  453 }
  454 
  455 /* send an dynamic-lib message */
  456 int fc_com_write_lib(FC_LDYN *ldyn)
  457 {
  458     fc_fifo_write_ldyn(fc_com_fifo, ldyn, sizeof (FC_LDYN), fc_single_id);
  459 
  460     return 1;
  461 }