1  /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
       2     Contributed by Oracle.
       3  
       4     This file is part of GNU Binutils.
       5  
       6     This program is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3, or (at your option)
       9     any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; if not, write to the Free Software
      18     Foundation, 51 Franklin Street - Fifth Floor, Boston,
      19     MA 02110-1301, USA.  */
      20  
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <dlfcn.h>
      24  #include <errno.h>
      25  #include <string.h>
      26  #include "stopwatch.h"
      27  
      28  
      29  #define DYNSOROUTINE "sx_cputime"
      30  #define DYNSONAME "./so_syx.so"
      31  
      32  /* callsx -- dynamically link a shared object, and call a routine in it */
      33  
      34  #ifndef NONSHARED
      35  
      36  static void *sx_object = NULL;
      37  static void closesx (void);
      38  
      39  int
      40  callsx (int k)
      41  {
      42    int i;
      43    char buf[1024];
      44    char *p;
      45    char *q = DYNSONAME;
      46    int errnum;
      47  
      48    hrtime_t start = gethrtime ();
      49    hrtime_t vstart = gethrvtime ();
      50  
      51    /* Log the event */
      52    wlog ("start of callsx", NULL);
      53  
      54    /* see if already linked */
      55    if (sx_object != NULL)
      56      {
      57        fprintf (stderr, "Execution error -- callsx: sx_object already linked\n");
      58        return 0;
      59      }
      60  
      61    /* open the dynamic shared object */
      62    /* open the dynamic shared object */
      63    sx_object = NULL;
      64    while (sx_object == NULL)
      65      {
      66        sx_object = dlopen (DYNSONAME, RTLD_NOW);
      67        if (sx_object != NULL)
      68          break;
      69        p = dlerror ();
      70        if (q == NULL) q = "DYNSONAME";
      71        if (p == NULL) p = "dlerror() returns NULL";
      72        errnum = errno;
      73        if (errnum == EINTR)
      74          continue;  /* retry */
      75        else
      76          {
      77            fprintf (stderr, "Execution error -- callso: dlopen of %s failed--%s, errno=%d (%s)\n",
      78                     q, p, errnum, strerror (errnum));
      79            return (0);
      80          }
      81      }
      82  
      83    /* look up the routine name in it */
      84    int (*sx_routine)() = (int (*)())dlsym (sx_object, DYNSOROUTINE);
      85    if (sx_routine == NULL)
      86      {
      87        fprintf (stderr, "Execution error -- callsx: dlsym %s not found\n",
      88                 DYNSOROUTINE);
      89        return (0);
      90      }
      91  
      92    /* invoke the routine */
      93    long long count = 0;
      94    do
      95      {
      96        i = (*sx_routine)();
      97        count++;
      98      }
      99    while (start + testtime * 1e9 > gethrtime ());
     100  
     101    closesx ();
     102    sprintf (buf, "end of callsx, %s returned %d", DYNSOROUTINE, i);
     103    wlog (buf, NULL);
     104    fprintf (stderr, "   Performed %lld while-loop iterations\n", count);
     105    whrvlog ((gethrtime () - start), (gethrvtime () - vstart), "callsx", NULL);
     106    return 0;
     107  }
     108  
     109  /* closesx -- close a DSO */
     110  void
     111  closesx (void)
     112  {
     113    /* Log the event */
     114    wlog ("start of closesx", NULL);
     115  
     116    /* ensure already linked */
     117    if (sx_object == NULL)
     118      {
     119        fprintf (stderr, "Execution error -- closesx: sx_object not linked\n");
     120        return;
     121      }
     122  
     123  #if 0
     124    /* close the dynamic shared object */
     125    rc = dlclose (sx_object);
     126    if (rc != 0)
     127      {
     128        fprintf (stderr, "Execution error -- closesx: dlclose() failed--%s\n",
     129                 dlerror ());
     130        return;
     131      }
     132    /* clear the pointer */
     133    sx_object = NULL;
     134  #endif
     135    wlog ("end of closesx", NULL);
     136    return;
     137  }
     138  
     139  #else /* NONSHARED */
     140  
     141  int
     142  callsx (int i)
     143  {
     144    return 0;
     145  }
     146  
     147  void
     148  closesx (void)
     149  {
     150    return;
     151  }
     152  #endif /* NONSHARED */