TSP: The Transport Sample Protocol



Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

gdisp_sampling.c

Go to the documentation of this file.
00001 
00043 /*
00044  * System includes.
00045  */
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <assert.h>
00049 #include <string.h>
00050 #include <time.h>
00051 #include <errno.h>
00052 #include <ctype.h>
00053 
00054 
00055 /*
00056  * GDISP+ includes.
00057  */
00058 #include "gdisp_sampling.h"
00059 
00060 #undef THREAD_DEBUG
00061 #undef SAMPLING_DEBUG
00062 
00063 /*
00064  --------------------------------------------------------------------
00065                              STATIC ROUTINES
00066  --------------------------------------------------------------------
00067 */
00068 
00069 
00070 /*
00071  * Encapsulation of thread creation.
00072  */
00073 static gint
00074 gdisp_createThread ( Kernel_T               *kernel,
00075                      gchar                  *threadName,
00076                      pthread_t              *threadIdentity,
00077                      const pthread_attr_t   *threadAttributes,
00078                      void                 *(*threadProcedure)(void*),
00079                      void                   *threadArgument,
00080                      gboolean                threadIsDetached,
00081                      gboolean                threadCreationIsVerbose )
00082 {
00083 
00084   ThreadStatus_T  threadStatus  = GD_THREAD_STOPPED;
00085   GString        *messageString =    (GString*)NULL;
00086   gint            status        =                 0;
00087 
00088 
00089   /*
00090    * Really create the thread.
00091    */
00092   *threadIdentity = (pthread_t)NULL;
00093 
00094   status = pthread_create(threadIdentity,
00095                           threadAttributes,
00096                           threadProcedure,
00097                           threadArgument);
00098 
00099   if (status != 0) {
00100 
00101     *threadIdentity = (pthread_t)NULL;
00102     threadStatus    = GD_THREAD_ERROR;
00103 
00104     if (threadCreationIsVerbose == TRUE) {
00105 
00106       messageString = g_string_new((gchar*)NULL);
00107       g_string_sprintf(messageString,
00108                        "%s thread creation failed.",
00109                        threadName);
00110       kernel->outputFunc(kernel,messageString,GD_ERROR);
00111 
00112       messageString = g_string_new((gchar*)NULL);
00113       g_string_sprintf(messageString,
00114                        "%s.",
00115                        strerror(errno));
00116       kernel->outputFunc(kernel,messageString,GD_ERROR);
00117 
00118     } /* verbose */
00119 
00120   }
00121   else if (threadIsDetached == TRUE) {
00122 
00123     status = pthread_detach(*threadIdentity);
00124 
00125     if (status != 0 && threadCreationIsVerbose == TRUE) {
00126 
00127       threadStatus = GD_THREAD_WARNING;
00128 
00129       messageString = g_string_new((gchar*)NULL);
00130       g_string_sprintf(messageString,
00131                        "Cannot detach %s thread.",
00132                        threadName);
00133       kernel->outputFunc(kernel,messageString,GD_ERROR);
00134 
00135       messageString = g_string_new((gchar*)NULL);
00136       g_string_sprintf(messageString,
00137                        "%s.",
00138                        strerror(errno));
00139       kernel->outputFunc(kernel,messageString,GD_ERROR);
00140 
00141     }
00142 
00143   }
00144 
00145   return threadStatus;
00146 
00147 }
00148 
00149 
00150 /*
00151  * Main callback routine to perform timer period computation.
00152  */
00153 static void
00154 gdisp_computeTimerPeriod ( Kernel_T         *kernel,
00155                            Page_T           *page,
00156                            PlotSystemData_T *plotSystemData,
00157                            void             *userData )
00158 {
00159 
00160   guint *timerPeriod = (guint*)userData;
00161   guint  plotPeriod  = 0;
00162 
00163   /*
00164    * Get back the current period of the plot.
00165    */
00166   plotPeriod = (*plotSystemData->plotSystem->psGetPeriod)
00167                                       (kernel,plotSystemData->plotData);
00168 
00169   *timerPeriod = gdisp_computePgcd(*timerPeriod,plotPeriod);
00170 
00171 }
00172 
00173 
00174 /*
00175  * Main callback routine to perform plot cycle computation.
00176  */
00177 static void
00178 gdisp_computePlotCycles ( Kernel_T         *kernel,
00179                           Page_T           *page,
00180                           PlotSystemData_T *plotSystemData,
00181                           void             *userData )
00182 {
00183 
00184   guint *timerPeriod = (guint*)userData;
00185   guint  plotPeriod  = 0;
00186 
00187   /*
00188    * Compute the plot cycle.
00189    * If GTK step timer has a period equal to 100 milli-seconds, and
00190    * our plot has a period of 1000 milli-seconds, so out plot cycle is 10.
00191    * It will be "stepped" 1 time out of 10.
00192    */
00193   plotPeriod = (*plotSystemData->plotSystem->psGetPeriod)
00194                                       (kernel,plotSystemData->plotData);
00195 
00196   plotSystemData->plotCycle = plotPeriod / *timerPeriod;
00197 
00198   if (plotSystemData->plotCycle == 0) {
00199 
00200     plotSystemData->plotCycle = 1;
00201 
00202   }
00203 
00204 }
00205 
00206 
00207 /*
00208  * Main callback routine to perform symbol treatment on the graphic plot.
00209  */
00210 static void
00211 gdisp_treatSymbolOnOneGraphicPlot ( Kernel_T         *kernel,
00212                                     Page_T           *page,
00213                                     PlotSystemData_T *plotSystemData,
00214                                     void             *userData )
00215 {
00216 
00217   (*plotSystemData->plotSystem->psTreatSymbolValues)(kernel,
00218                                                      plotSystemData->plotData);
00219 
00220 }
00221 
00222 
00223 /*
00224  * Main callback routine to perform start-step on the graphic plot.
00225  */
00226 static void
00227 gdisp_startStepOnOneGraphicPlot ( Kernel_T         *kernel,
00228                                   Page_T           *page,
00229                                   PlotSystemData_T *plotSystemData,
00230                                   void             *userData )
00231 {
00232 
00233   gboolean ready = FALSE;
00234 
00235   ready = (*plotSystemData->plotSystem->psStartStep)(kernel,
00236                                                      plotSystemData->plotData);
00237 
00238   if (ready == FALSE) {
00239 
00240     *((gboolean*)userData) = FALSE;
00241 
00242   }
00243 
00244 }
00245 
00246 
00247 /*
00248  * Main callback routine to perform stop-step on the graphic plot.
00249  */
00250 static void
00251 gdisp_stopStepOnOneGraphicPlot ( Kernel_T         *kernel,
00252                                  Page_T           *page,
00253                                  PlotSystemData_T *plotSystemData,
00254                                  void             *userData )
00255 {
00256 
00257   (*plotSystemData->plotSystem->psStopStep)(kernel,
00258                                             plotSystemData->plotData);
00259 
00260 }
00261 
00262 
00263 /*
00264  * Main callback routine to perform steps on the graphic plot.
00265  */
00266 static void
00267 gdisp_stepOnOneGraphicPlot ( Kernel_T         *kernel,
00268                              Page_T           *page,
00269                              PlotSystemData_T *plotSystemData,
00270                              void             *userData )
00271 {
00272 
00273   /*
00274    * Take into account the period of the step management, and the
00275    * period of the graphic plot.
00276    */
00277   if (kernel->stepGlobalCycle % plotSystemData->plotCycle == 0) {
00278 
00279     (*plotSystemData->plotSystem->psStep)(kernel,
00280                                           plotSystemData->plotData);
00281 
00282   }
00283 
00284 }
00285 
00286 
00287 /*
00288  * Main routine to perform steps on the graphic pages.
00289  * The prototype of this routine ensures that it may be used
00290  * as a callback given to the 'gtk_timeout_add' action.
00291  */
00292 #undef BENCHMARK
00293 
00294 static gint
00295 gdisp_stepsOnGraphicPlots ( void *data )
00296 {
00297 
00298   Kernel_T        *kernel    = (Kernel_T*)data;
00299 
00300 #if defined(BENCHMARK)
00301 
00302   HRTime_T         startMark = (HRTime_T)0;
00303   HRTime_T         stopMark  = (HRTime_T)0;
00304   HRTime_T         deltaMark = (HRTime_T)0;
00305   static HRTime_T  lastMark  = (HRTime_T)0;
00306 
00307 #endif
00308 
00309   /*
00310    * Check GTK timer.
00311    */
00312 #if defined(BENCHMARK)
00313 
00314   if (lastMark > 0) {
00315 
00316     deltaMark = gdisp_getHRTime() - lastMark;
00317 
00318     fprintf(stdout,
00319             "GTK Timer : %d nanoseconds\n",
00320             (int)(deltaMark & 0xFFFFFFFF));
00321 
00322   }
00323 
00324 #endif
00325 
00326   /*
00327    * Do the plot step.
00328    */
00329 #if defined(BENCHMARK)
00330 
00331   startMark = gdisp_getHRTime();
00332 
00333 #endif
00334 
00335   /* ************************************************************
00336    *
00337    * BEGIN : Loop over all graphic plots of all pages, do steps...
00338    *
00339    * ************************************************************/
00340 
00341   kernel->stepGlobalCycle++;
00342 
00343   gdisp_loopOnGraphicPlots (kernel,
00344                             gdisp_stepOnOneGraphicPlot,
00345                             (void*)NULL);
00346 
00347   /* ************************************************************
00348    *
00349    * END.
00350    *
00351    * ************************************************************/
00352 
00353 #if defined(BENCHMARK)
00354 
00355   stopMark = gdisp_getHRTime();
00356 
00357   deltaMark = stopMark - startMark;
00358 
00359   fprintf(stdout,
00360           "Step on all plots : %d nanoseconds\n",
00361           (int)(deltaMark & 0xFFFFFFFF));
00362 
00363   lastMark = gdisp_getHRTime();
00364 
00365 #endif
00366 
00367   return TRUE; /* keep on running */
00368 
00369 }
00370 
00371 
00372 /*
00373  * Memory allocation for sampling symbols.
00374  */
00375 static void
00376 gdisp_freeSymbolsForSampling (Kernel_T *kernel)
00377 {
00378 
00379   GList    *symbolList =    (GList*)NULL;
00380   Symbol_T *symbol     = (Symbol_T*)NULL;
00381 
00382   /*
00383    * Loop on every symbol that must be sampled.
00384    * Free memory that has been used for storing the evolution of the symbol.
00385    */
00386   symbolList = gdisp_getSymbolsInPages(kernel);
00387   symbolList = g_list_first(symbolList);
00388 
00389   while (symbolList != (GList*)NULL) {
00390 
00391     symbol = (Symbol_T*)symbolList->data;
00392 
00393     /*
00394      * Release everything necessary here.
00395      */
00396 
00397     /* nothing to be done by now */
00398 
00399     symbolList = g_list_next(symbolList);
00400 
00401   }
00402 
00403   g_list_free(symbolList);
00404 
00405 }
00406 
00407 
00408 /*
00409  * Memory allocation for sampling symbols.
00410  */
00411 static gboolean
00412 gdisp_allocateSymbolsForSampling (Kernel_T *kernel)
00413 {
00414 
00415   GList    *symbolList =    (GList*)NULL;
00416   Symbol_T *symbol     = (Symbol_T*)NULL;
00417 
00418   /*
00419    * Loop on every symbol that must be sampled.
00420    * Allocate memory for storing the evolution of the symbol.
00421    */
00422   symbolList = gdisp_getSymbolsInPages(kernel);
00423   symbolList = g_list_first(symbolList);
00424 
00425   while (symbolList != (GList*)NULL) {
00426 
00427     symbol = (Symbol_T*)symbolList->data;
00428 
00429     /*
00430      * Do allocation here if necessary.
00431      */
00432 
00433     /* nothing to be done by now */
00434 
00435     symbolList = g_list_next(symbolList);
00436 
00437   }
00438 
00439   g_list_free(symbolList);
00440 
00441   return TRUE; /* no error */
00442 
00443 }
00444 
00445 
00446 /*
00447  * Garbage collector on symbols.
00448  * Loop over all symbols and release memory if necessary.
00449  */
00450 static void*
00451 gdisp_garbageCollectorThread ( void *data )
00452 {
00453 
00454   Kernel_T   *kernel       =   (Kernel_T*)data;
00455   GList      *providerItem =      (GList*)NULL;
00456   Symbol_T   *symbolPtr    =   (Symbol_T*)NULL;
00457   Provider_T *provider     = (Provider_T*)NULL;
00458   gint        symbolCpt    =                 0;
00459 
00460 #if defined(THREAD_DEBUG)
00461   fprintf(stdout,"Beginning of garbage collector thread.\n");
00462   fflush (stdout);
00463 #endif
00464 
00465   /*
00466    * Wait for the thread creation to finalise...
00467    */
00468   while (kernel->garbageCollectorThread != pthread_self()) {
00469 
00470     gdisp_uSleep(_100_MILLISECONDS_IN_MICROSECONDS_);
00471 
00472   }
00473 
00474   /*
00475    * Garbage collector on symbols.
00476    * Loop over all symbols and release memory if necessary.
00477    */
00478   providerItem = g_list_first(kernel->providerList);
00479   while (providerItem != (GList*)NULL) {
00480 
00481     provider  = (Provider_T*)providerItem->data;
00482     symbolPtr = provider->pSymbolList;
00483 
00484     for (symbolCpt=0; symbolCpt<provider->pSymbolNumber; symbolCpt++) {
00485 
00486       /*
00487        * Release memory if no more graphic plots make use of this symbol.
00488        */
00489       if (symbolPtr->sReference == 0) {
00490 
00491         /*
00492          * Nothing by now.
00493          */
00494 
00495       }
00496 
00497       /*
00498        * Every 100 symbols, wait for a while by leaving CPU.
00499        * This enables other threads to keep on running...
00500        * FIXME : confirm it is useful...
00501        */
00502       if (symbolCpt % 100 == 0) {
00503 
00504         gdisp_uSleep(0);
00505 
00506       }
00507 
00508       symbolPtr++;
00509 
00510     } /* symbolCpt */
00511 
00512     providerItem = g_list_next(providerItem);
00513 
00514   }
00515 
00516   /*
00517    * Tell the kernel the garbage thread is about to finish.
00518    */
00519   kernel->garbageCollectorThread = (pthread_t)NULL;
00520 
00521 #if defined(THREAD_DEBUG)
00522   fprintf(stdout,"End of garbage collector thread.\n");
00523   fflush (stdout);
00524 #endif
00525 
00526   pthread_exit((void*)TRUE /* OK */);
00527 
00528 }
00529 
00530 
00531 /*
00532  * Main Sampling Thread.
00533  */
00534 static void*
00535 gdisp_samplingThread (void *data )
00536 {
00537 
00538   Kernel_T     *kernel           =   (Kernel_T*)data;
00539   Provider_T   *provider         = (Provider_T*)NULL;
00540   Symbol_T     *symbol           =   (Symbol_T*)NULL;
00541   GList        *providerItem     =      (GList*)NULL;
00542   gboolean      providerIsFound  =             FALSE;
00543   guchar        watchDog         =                10;
00544   gint          requestStatus    =                 0;
00545   gboolean      sampleHasArrived =             FALSE;
00546   guint         sampleRefTimeTag =                 0;
00547   TSP_sample_t  sampleValue;
00548 
00549 #if defined(THREAD_DEBUG)
00550   fprintf(stdout,"Beginning of provider sampling thread.\n");
00551   fflush (stdout);
00552 #endif
00553 
00554   /*
00555    * Wait for the thread creation to finalise...
00556    * Let's search for the provider we are talking about...
00557    * because only the kernel has been given to the thread.
00558    */
00559   do {
00560 
00561     providerItem = g_list_first(kernel->providerList);
00562     while (providerItem != (GList*)NULL && providerIsFound == FALSE) {
00563 
00564       provider = (Provider_T*)providerItem->data;
00565 
00566       if (provider->pSamplingThread == pthread_self()) {
00567 
00568         providerIsFound = TRUE;
00569 
00570       }
00571 
00572       providerItem = g_list_next(providerItem);
00573 
00574     } /* loop on providers */
00575 
00576     if (providerIsFound == FALSE) {
00577 
00578       watchDog--;
00579       gdisp_uSleep(_100_MILLISECONDS_IN_MICROSECONDS_);
00580 
00581     }
00582 
00583   } while (providerIsFound == FALSE && watchDog > 0);
00584 
00585 
00586   /*
00587    * Do I know who I am ?
00588    */
00589   if (providerIsFound == FALSE) {
00590 
00591     pthread_exit((void*)FALSE);
00592 
00593   }
00594 
00595 
00596   /*
00597    * Give requested symbols to TSP core.
00598    */
00599   requestStatus = TSP_consumer_request_sample(provider->pHandle,
00600                                               &provider->pSampleList);
00601 
00602   if (requestStatus == 0) {
00603 
00604     provider->pSamplingThreadStatus = GD_THREAD_REQUEST_SAMPLE_ERROR;
00605     pthread_exit((void*)FALSE);
00606 
00607   }
00608 
00609 
00610   /*
00611    * Tell TSP core to start sampling process.
00612    * Wait for a while so that TSP core has time to fill in FIFOs.
00613    */
00614   requestStatus =
00615     TSP_consumer_request_sample_init(provider->pHandle,
00616                                      (TSP_sample_callback_t)NULL,
00617                                      (void*)NULL);
00618 
00619   if (requestStatus == 0) {
00620 
00621     provider->pSamplingThreadStatus = GD_THREAD_SAMPLE_INIT_ERROR;
00622     pthread_exit((void*)FALSE);
00623 
00624   }
00625   else {
00626 
00627     gdisp_uSleep(_ONE_SECOND_IN_MICROSECONDS_ / 2);
00628 
00629   }
00630 
00631 
00632   /*
00633    * Sample... Do it...
00634    * As load is concerned, only "double" values are supported by TSP.
00635    */
00636   provider->pLoad    = 0;
00637   provider->pMaxLoad = provider->pBaseFrequency  *
00638                        provider->pSampleList.len * sizeof(gdouble);
00639 
00640   provider->pSamplingThreadStatus = GD_THREAD_RUNNING;
00641 
00642   while (kernel->samplingThreadMustExit == FALSE) {
00643 
00644     requestStatus = TSP_consumer_read_sample(provider->pHandle,
00645                                              &sampleValue,
00646                                              &sampleHasArrived);
00647 
00648     if (requestStatus == FALSE) {
00649 
00650       /*
00651        * Out of "while" loop.
00652        */
00653       break;
00654 
00655     }
00656 
00657     if (sampleHasArrived == TRUE) {
00658 
00659       /*
00660        * Count the number of incoming values in order to deduce
00661        * the provider load (bytes per seconds).
00662        */
00663       provider->pLoad += sizeof(gdouble);
00664 
00665       /*
00666        * Check out new incoming frame.
00667        */
00668       if (sampleRefTimeTag != (guint)sampleValue.time) {
00669 
00670 #if defined(SAMPLING_DEBUG)
00671 
00672         printf("------------------------ FRAME ------------------------\n");
00673 
00674 #endif
00675         gdisp_loopOnGraphicPlots (kernel,
00676                                   gdisp_treatSymbolOnOneGraphicPlot,
00677                                   (void*)NULL);
00678 
00679         sampleRefTimeTag = (guint)sampleValue.time;
00680 
00681       }
00682 
00683       /*
00684        * Treat symbol.
00685        */
00686 #if defined(SAMPLING_DEBUG)
00687 
00688       printf("Time [%d] - Index [%d] - Name [%s] - Value [%f]\n",
00689          sampleValue.time,
00690          sampleValue.provider_global_index,
00691          provider->pSymbolList[sampleValue.provider_global_index].sInfo.name,
00692          (float)sampleValue.user_value);
00693 
00694 #endif
00695 
00696       symbol = &provider->pSymbolList[sampleValue.provider_global_index];
00697 
00698       symbol->sTimeTag    = (guint)sampleValue.time;
00699 
00700       symbol->sHasChanged =
00701         sampleValue.user_value == symbol->sLastValue ? FALSE : TRUE;
00702 
00703       symbol->sLastValue  = sampleValue.user_value;
00704 
00705     } /* sampleHasArrived == TRUE */
00706 
00707     else {
00708 
00709       /*
00710        * Used to give time to other TSP threads for filling internal
00711        * FIFOs with received samples.
00712        */
00713       gdisp_uSleep(_ONE_SECOND_IN_MICROSECONDS_ / provider->pBaseFrequency);
00714 
00715     }
00716 
00717   }
00718 
00719   provider->pSamplingThreadStatus = GD_THREAD_STOPPED;
00720   
00721 
00722   /*
00723    * Tell TSP core to stop sampling process.
00724    */
00725   if (requestStatus == FALSE) {
00726     requestStatus = 0;
00727   }
00728   else {
00729     requestStatus = TSP_consumer_request_sample_destroy(provider->pHandle);
00730   }
00731 
00732   if (requestStatus == 0) {
00733 
00734     provider->pSamplingThreadStatus = GD_THREAD_SAMPLE_DESTROY_ERROR;
00735 
00736   }
00737 
00738 
00739   /*
00740    * Bye bye.
00741    */
00742   provider->pSamplingThread = (pthread_t)NULL;
00743 
00744 #if defined(THREAD_DEBUG)
00745   fprintf(stdout,"End of provider sampling thread.\n");
00746   fflush (stdout);
00747 #endif
00748 
00749   pthread_exit((void*)TRUE);
00750 
00751 }
00752 
00753 
00754 /*
00755  * Pre-Sampling Thread.
00756  */
00757 static void*
00758 gdisp_preSamplingThread (void *data )
00759 {
00760 
00761   Kernel_T       *kernel            =   (Kernel_T*)data;
00762   Provider_T     *provider          = (Provider_T*)NULL;
00763   GList          *providerItem      =      (GList*)NULL;
00764   gboolean        memoryIsAllocated =             FALSE;
00765   ThreadStatus_T  threadStatus      =   GD_THREAD_ERROR;
00766 
00767 
00768 #if defined(THREAD_DEBUG)
00769   fprintf(stdout,"Beginning of pre-sampling thread.\n");
00770   fflush (stdout);
00771 #endif
00772 
00773   /*
00774    * Memory allocation for sampling symbols.
00775    */
00776   memoryIsAllocated = gdisp_allocateSymbolsForSampling(kernel);
00777   if (memoryIsAllocated == FALSE) {
00778 
00779     /*
00780      * No matter the returned value, because 'preSamplingThread' is detached.
00781      */
00782     pthread_exit((void*)FALSE);
00783 
00784   }
00785 
00786 
00787   /*
00788    * Compute provider sampling configurations.
00789    */
00790   gdisp_affectRequestedSymbolsToProvider(kernel);
00791 
00792 
00793   /*
00794    * All provider threads must keep on running...
00795    */
00796   kernel->samplingThreadMustExit = FALSE;
00797 
00798 
00799   /*
00800    * Loop on each provider, and launch the sampling thread.
00801    */
00802   providerItem = g_list_first(kernel->providerList);
00803   while (providerItem != (GList*)NULL) {
00804 
00805     provider = (Provider_T*)providerItem->data;
00806 
00807     /*
00808      * Create the thread is only there something to be sampled...
00809      */
00810     if (provider->pSampleList.len != 0) {
00811 
00812       threadStatus = gdisp_createThread(kernel,
00813                                         provider->pUrl->str,
00814                                         &provider->pSamplingThread,
00815                                         (const pthread_attr_t*)NULL,
00816                                         gdisp_samplingThread,
00817                                         (void*)kernel,
00818                                         TRUE  /* thread is detached */,
00819                                         FALSE /* no verbose         */);
00820 
00821       provider->pSamplingThreadStatus =
00822         threadStatus == GD_THREAD_ERROR ? threadStatus : GD_THREAD_STARTING;
00823 
00824     } /* something to be sampled... */
00825 
00826     providerItem = g_list_next(providerItem);
00827 
00828   } /* loop on providers */
00829 
00830 
00831   /*
00832    * Launch a timer.
00833    * The period must be defined in milli-seconds.
00834    */
00835   kernel->stepTimerIdentity  = gtk_timeout_add(kernel->stepTimerPeriod,
00836                                                gdisp_stepsOnGraphicPlots,
00837                                                (gpointer)kernel);
00838 
00839 
00840   /*
00841    * No matter the returned value, because 'preSamplingThread' is detached.
00842    */
00843 #if defined(THREAD_DEBUG)
00844   fprintf(stdout,"End of pre-sampling thread.\n");
00845   fflush (stdout);
00846 #endif
00847 
00848   pthread_exit((void*)TRUE);
00849 
00850 }
00851 
00852 
00853 /*
00854  --------------------------------------------------------------------
00855                              PUBLIC ROUTINES
00856  --------------------------------------------------------------------
00857 */
00858 
00859 
00860 /*
00861  * Start everything that deals with sampling process.
00862  */
00863 gboolean
00864 gdisp_startSamplingProcess (Kernel_T *kernel)
00865 {
00866 
00867   pthread_t       preSamplingThread = (pthread_t)NULL;
00868   ThreadStatus_T  threadStatus      = GD_THREAD_ERROR;
00869   gboolean        allPlotsReady     = TRUE;
00870   GString        *messageString     = (GString*)NULL;
00871 
00872 
00873   /*
00874    * Compute now the period (expressed in milli-seconds that
00875    * must be given to the GTK timer that performs steps on plots.
00876    * Each graphic plot is asked its own period, then the minimum
00877    * period is given to the GTK timer.
00878    */
00879   kernel->stepTimerPeriod = G_MAXINT; /* will be overwritten */
00880   kernel->stepGlobalCycle = 0;
00881 
00882   gdisp_loopOnGraphicPlots(kernel,
00883                            gdisp_computeTimerPeriod,
00884                            (void*)&kernel->stepTimerPeriod);
00885 
00886   if (kernel->stepTimerPeriod == G_MAXINT /* no plot created */) {
00887 
00888     /*
00889      * Error message.
00890      */
00891     messageString =
00892       g_string_new("You should create a graphic plot before sampling...");
00893     kernel->outputFunc(kernel,messageString,GD_ERROR);
00894 
00895     return FALSE;
00896 
00897   }
00898   
00899   if (kernel->stepTimerPeriod < GD_TIMER_MIN_PERIOD) {
00900 
00901     /*
00902      * GTK is not precise enough... it is not real time...
00903      * 100 milli-seconds is a minimum minimorum.
00904      */
00905     kernel->stepTimerPeriod = GD_TIMER_MIN_PERIOD;
00906 
00907   }
00908   
00909   gdisp_loopOnGraphicPlots(kernel,
00910                            gdisp_computePlotCycles,
00911                            (void*)&kernel->stepTimerPeriod);
00912 
00913   messageString = g_string_new((gchar*)NULL);
00914   g_string_sprintf(messageString,
00915                    "Step process period is %d milli-seconds.",
00916                    kernel->stepTimerPeriod);
00917   kernel->outputFunc(kernel,messageString,GD_MESSAGE);
00918 
00919 
00920   /*
00921    * Before starting anything, ask all graphic plots if they
00922    * are ready to perform real-time steps.
00923    * If one answer is NO (ie FALSE), abort operation.
00924    */
00925   gdisp_loopOnGraphicPlots(kernel,
00926                            gdisp_startStepOnOneGraphicPlot,
00927                            (void*)&allPlotsReady);
00928 
00929   if (allPlotsReady == FALSE) {
00930 
00931     /*
00932      * Cancel any start-step side effects.
00933      */
00934     gdisp_loopOnGraphicPlots(kernel,
00935                              gdisp_stopStepOnOneGraphicPlot,
00936                              (void*)NULL);
00937 
00938 
00939     /*
00940      * Error message.
00941      */
00942     messageString =
00943       g_string_new("Cannot start dynamic plot process");
00944     kernel->outputFunc(kernel,messageString,GD_ERROR);
00945 
00946     messageString =
00947       g_string_new("because one or more plots are unabled to proceed.");
00948     kernel->outputFunc(kernel,messageString,GD_ERROR);
00949 
00950     return FALSE;
00951 
00952   }
00953 
00954 
00955   /*
00956    * Create the thread that will handle TSP symbol pre-sampling,
00957    * according to symbols that have been dropped on plots.
00958    * The pre-sampling phase consists in allocating memory for symbols
00959    * that must be sampled, assigning symbols to providers, creating
00960    * a sampling thread for each provider, and launching a GTK timer
00961    * for managing steps on graphic plots.
00962    */
00963   threadStatus = gdisp_createThread(kernel,
00964                                     "Pre-sampling",
00965                                     &preSamplingThread,
00966                                     (const pthread_attr_t*)NULL,
00967                                     gdisp_preSamplingThread,
00968                                     (void*)kernel,
00969                                     TRUE /* thread is detached */,
00970                                     TRUE /* verbose            */);
00971 
00972   if (threadStatus == GD_THREAD_ERROR) {
00973 
00974     return FALSE;
00975 
00976   }
00977 
00978 
00979   /*
00980    * Create the garbage collector thread that will release
00981    * memory of symbols that are no longer in use.
00982    * CAUTION : this thread must be detached in order to release
00983    * ressouces, because no other thread will wait for it (pthread_join).
00984    */
00985   if (kernel->garbageCollectorThread == (pthread_t)NULL) {
00986 
00987     threadStatus = gdisp_createThread(kernel,
00988                                       "Garbage collector",
00989                                       &kernel->garbageCollectorThread,
00990                                       (const pthread_attr_t*)NULL,
00991                                       gdisp_garbageCollectorThread,
00992                                       (void*)kernel,
00993                                       TRUE /* thread is detached */,
00994                                       TRUE /* verbose            */);
00995 
00996   } /* test whether garbage collector thread already exists */
00997 
00998   return TRUE;
00999 
01000 }
01001 
01002 
01003 /*
01004  * Stop everything that deals with sampling process.
01005  */
01006 void
01007 gdisp_stopSamplingProcess (Kernel_T *kernel)
01008 {
01009 
01010   /*
01011    * Stop the timer that performs steps on graphic plots.
01012    */
01013   if (kernel->stepTimerIdentity > 0) {
01014 
01015     gtk_timeout_remove(kernel->stepTimerIdentity);
01016     kernel->stepTimerIdentity = 0;
01017 
01018   }
01019 
01020 
01021   /*
01022    * Stop sampling threads.
01023    * Do not wait (pthread_join) for those provider threads,
01024    * because they are detached.
01025    */
01026   kernel->samplingThreadMustExit = TRUE;
01027   gdisp_uSleep(_ONE_SECOND_IN_MICROSECONDS_ / 2);
01028 
01029 
01030   /*
01031    * Tell all plots that step-process has stopped.
01032    */
01033   gdisp_loopOnGraphicPlots(kernel,
01034                            gdisp_stopStepOnOneGraphicPlot,
01035                            (void*)NULL);
01036 
01037 }
01038 
01039 
01040 /*
01041  * All symbols that must be plotted do not belong to the same
01042  * provider. So give back requested symbols to the provider each
01043  * of them belongs to.
01044  */
01045 void
01046 gdisp_affectRequestedSymbolsToProvider ( Kernel_T *kernel )
01047 {
01048 
01049   GArray     *requestedSymbolArray =     (GArray*)NULL;
01050   GList      *providerItem         =      (GList*)NULL;
01051   Provider_T *provider             = (Provider_T*)NULL;
01052   GList      *symbolList           =      (GList*)NULL;
01053   GList      *symbolItem           =      (GList*)NULL;
01054   Symbol_T   *symbol               =   (Symbol_T*)NULL;
01055   guint       elementSize          =                 0;
01056 
01057   /*
01058    * Get back requested symbols from graphic pages.
01059    */
01060   symbolList = gdisp_getSymbolsInPages(kernel);
01061 
01062 
01063   /*
01064    * Loop over all providers, cancel any previous sampling
01065    * configuration, attach new symbols if any.
01066    */
01067   providerItem = g_list_first(kernel->providerList);
01068   while (providerItem != (GList*)NULL) {
01069 
01070     provider = (Provider_T*)providerItem->data;
01071 
01072     if (provider->pStatus == GD_SESSION_OPENED) {
01073 
01074       /*
01075        * Cancel any previous sampling configuration.
01076        */
01077       provider->pSampleList.len = 0;
01078       if (provider->pSampleList.val != (TSP_consumer_symbol_requested_t*)NULL)
01079         free(provider->pSampleList.val);
01080       provider->pSampleList.val = (TSP_consumer_symbol_requested_t*)NULL;
01081 
01082 
01083       /*
01084        * Temporary ressource.
01085        */
01086       elementSize = sizeof(TSP_consumer_symbol_requested_t);
01087       requestedSymbolArray = g_array_new(FALSE, /* zero_terminated */
01088                                          TRUE,  /* clear           */
01089                                          (guint)elementSize);
01090 
01091 
01092       /*
01093        * Loop on every symbol that must be sampled.
01094        */
01095       symbolItem = g_list_first(symbolList);
01096       while (symbolItem != (GList*)NULL) {
01097 
01098         symbol = (Symbol_T*)symbolItem->data;
01099 
01100         /*
01101          * The symbol belongs to the current provider because its
01102          * address is in the good address interval.
01103          */
01104         if (provider->pSymbolList <= symbol &&
01105             symbol < provider->pSymbolList + provider->pSymbolNumber) {
01106 
01107           g_array_append_val(requestedSymbolArray,symbol->sInfo);
01108 
01109         }
01110 
01111         symbolItem = g_list_next(symbolItem);
01112 
01113       }
01114 
01115 
01116       /*
01117        * Transfer information to provider.
01118        */
01119       provider->pSampleList.val =
01120         (TSP_consumer_symbol_requested_t*)requestedSymbolArray->data;
01121       provider->pSampleList.len = requestedSymbolArray->len;
01122 
01123 
01124       /*
01125        * Free temporary ressource.
01126        * Free the table, not the content.
01127        */
01128       g_array_free(requestedSymbolArray,FALSE);
01129 
01130     } /* provider->pStatus == GD_SESSION_OPENED */
01131 
01132     providerItem = g_list_next(providerItem);
01133 
01134   }
01135 
01136 
01137   /*
01138    * Release ressource.
01139    */
01140   g_list_free(symbolList);
01141 
01142 }
Framework Home Page.

Beware !! TSP wave is coming...