OSDN Git Service

2010-03-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libgfortran / intrinsics / system_clock.c
index 1d64558..7806059 100644 (file)
@@ -1,41 +1,33 @@
 /* Implementation of the SYSTEM_CLOCK intrinsic.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
 
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
 
 Libgfortran is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public
 License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
+version 3 of the License, or (at your option) any later version.
 
 Libgfortran is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public
-License along with libgfortran; see the file COPYING.  If not,
-write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
 
-#include "config.h"
-#include <sys/types.h>
 #include "libgfortran.h"
 
 #include <limits.h>
 
 #if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
 #  include <sys/time.h>
-#  define TCK 1000
 #elif defined(HAVE_TIME_H)
 #  include <time.h>
 #  define TCK 1
@@ -44,13 +36,6 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 
-#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
-static struct timeval tp0 = {-1, 0};
-#elif defined(HAVE_TIME_H)
-static time_t t0 = (time_t) -2;
-#endif
-
-
 extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *);
 export_proto(system_clock_4);
 
@@ -68,72 +53,57 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
               GFC_INTEGER_4 *count_max)
 {
   GFC_INTEGER_4 cnt;
-  GFC_INTEGER_4 rate;
   GFC_INTEGER_4 mx;
 
 #if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
+#define TCK 1000
   struct timeval tp1;
-  struct timezone tzp;
-  double t;
 
-  if (gettimeofday(&tp1, &tzp) == 0)
+  if (sizeof (tp1.tv_sec) < sizeof (GFC_INTEGER_4))
+    internal_error (NULL, "tv_sec too small");
+
+  if (gettimeofday(&tp1, NULL) == 0)
     {
-      if (tp0.tv_sec < 0)
-        {
-          tp0 = tp1;
-          cnt = 0;
-        }
+      GFC_UINTEGER_4 ucnt = (GFC_UINTEGER_4) tp1.tv_sec * TCK;
+      ucnt += (tp1.tv_usec + 500000 / TCK) / (1000000 / TCK);
+      if (ucnt > GFC_INTEGER_4_HUGE)
+       cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
       else
-        {
-         /* TODO: Convert this to integer arithmetic.  */
-          t  = (double) (tp1.tv_sec  - tp0.tv_sec);
-          t += (double) (tp1.tv_usec - tp0.tv_usec) * 1.e-6;
-          t *= TCK;
-
-          if (t > (double) GFC_INTEGER_4_HUGE)
-            {
-              /* Time has wrapped. */
-              while (t > (double) GFC_INTEGER_4_HUGE)
-                t -= (double) GFC_INTEGER_4_HUGE;
-              tp0 = tp1;
-            }
-         cnt = (GFC_INTEGER_4) t;
-        }
-      rate = TCK;
+       cnt = ucnt;
       mx = GFC_INTEGER_4_HUGE;
     }
   else
     {
-      if (count != NULL) *count = - GFC_INTEGER_4_HUGE;
-      if (count_rate != NULL) *count_rate = 0;
-      if (count_max != NULL) *count_max = 0;
+      if (count != NULL)
+       *count = - GFC_INTEGER_4_HUGE;
+      if (count_rate != NULL)
+       *count_rate = 0;
+      if (count_max != NULL)
+       *count_max = 0;
+      return;
     }
 #elif defined(HAVE_TIME_H)
-  time_t t, t1;
+  GFC_UINTEGER_4 ucnt;
 
-  t1 = time(NULL);
+  if (sizeof (time_t) < sizeof (GFC_INTEGER_4))
+    internal_error (NULL, "time_t too small");
 
-  if (t1 == (time_t) -1)
-    {
-      cnt = - GFC_INTEGER_4_HUGE;
-      mx = 0;
-    }
-  else if (t0 == (time_t) -2) 
-    t0 = t1;
+  ucnt = time (NULL);
+  if (ucnt > GFC_INTEGER_4_HUGE)
+    cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
   else
-    {
-      /* The timer counts in seconts, so for simplicity assume it never wraps.
-        Even with 32-bit counters this only happens once every 68 years.  */
-      cnt = t1 - t0;
-      mx = GFC_INTEGER_4_HUGE;
-    }
+    cnt = ucnt;
+  mx = GFC_INTEGER_4_HUGE;
 #else
   cnt = - GFC_INTEGER_4_HUGE;
   mx = 0;
 #endif
-  if (count != NULL) *count = cnt;
-  if (count_rate != NULL) *count_rate = TCK;
-  if (count_max != NULL) *count_max = mx;
+  if (count != NULL)
+    *count = cnt;
+  if (count_rate != NULL)
+    *count_rate = TCK;
+  if (count_max != NULL)
+    *count_max = mx;
 }
 
 
@@ -141,66 +111,71 @@ system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
 
 void
 system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
-               GFC_INTEGER_8 *count_max)
+               GFC_INTEGER_8 *count_max)
 {
   GFC_INTEGER_8 cnt;
-  GFC_INTEGER_8 rate;
   GFC_INTEGER_8 mx;
 
 #if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
+#define TCK 1000000
   struct timeval tp1;
-  struct timezone tzp;
-  double t;
 
-  if (gettimeofday(&tp1, &tzp) == 0)
+  if (sizeof (tp1.tv_sec) < sizeof (GFC_INTEGER_4))
+    internal_error (NULL, "tv_sec too small");
+
+  if (gettimeofday(&tp1, NULL) == 0)
     {
-      if (tp0.tv_sec < 0)
-        {
-          tp0 = tp1;
-          cnt = 0;
-        }
+      if (sizeof (tp1.tv_sec) < sizeof (GFC_INTEGER_8))
+       {
+         GFC_UINTEGER_4 ucnt = (GFC_UINTEGER_4) tp1.tv_sec * TCK;
+         ucnt += (tp1.tv_usec + 500000 / TCK) / (1000000 / TCK);
+         if (ucnt > GFC_INTEGER_4_HUGE)
+           cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
+         else
+           cnt = ucnt;
+         mx = GFC_INTEGER_4_HUGE;
+       }
       else
-        {
-         /* TODO: Convert this to integer arithmetic.  */
-          t  = (double) (tp1.tv_sec  - tp0.tv_sec);
-          t += (double) (tp1.tv_usec - tp0.tv_usec) * 1.e-6;
-          t *= TCK;
-
-          if (t > (double) GFC_INTEGER_8_HUGE)
-            {
-              /* Time has wrapped. */
-              while (t > (double) GFC_INTEGER_8_HUGE)
-                t -= (double) GFC_INTEGER_8_HUGE;
-              tp0 = tp1;
-            }
-         cnt = (GFC_INTEGER_8) t;
-        }
-      rate = TCK;
-      mx = GFC_INTEGER_8_HUGE;
+       {
+         GFC_UINTEGER_8 ucnt = (GFC_UINTEGER_8) tp1.tv_sec * TCK;
+         ucnt += (tp1.tv_usec + 500000 / TCK) / (1000000 / TCK);
+         if (ucnt > GFC_INTEGER_8_HUGE)
+           cnt = ucnt - GFC_INTEGER_8_HUGE - 1;
+         else
+           cnt = ucnt;
+         mx = GFC_INTEGER_8_HUGE;
+       }
     }
   else
     {
-      if (count != NULL) *count = - GFC_INTEGER_8_HUGE;
-      if (count_rate != NULL) *count_rate = 0;
-      if (count_max != NULL) *count_max = 0;
+      if (count != NULL)
+       *count = - GFC_INTEGER_8_HUGE;
+      if (count_rate != NULL)
+       *count_rate = 0;
+      if (count_max != NULL)
+       *count_max = 0;
+
+      return;
     }
 #elif defined(HAVE_TIME_H)
-  time_t t, t1;
-
-  t1 = time(NULL);
-
-  if (t1 == (time_t) -1)
+  if (sizeof (time_t) < sizeof (GFC_INTEGER_4))
+    internal_error (NULL, "time_t too small");
+  else if (sizeof (time_t) == sizeof (GFC_INTEGER_4))
     {
-      cnt = - GFC_INTEGER_8_HUGE;
-      mx = 0;
+      GFC_UINTEGER_4 ucnt = time (NULL);
+      if (ucnt > GFC_INTEGER_4_HUGE)
+       cnt = ucnt - GFC_INTEGER_4_HUGE - 1;
+      else
+       cnt = ucnt;
+      mx = GFC_INTEGER_4_HUGE;
     }
-  else if (t0 == (time_t) -2) 
-    t0 = t1;
   else
     {
-      /* The timer counts in seconts, so for simplicity assume it never wraps.
-        Even with 32-bit counters this only happens once every 68 years.  */
-      cnt = t1 - t0;
+      GFC_UINTEGER_8 ucnt = time (NULL);
+      if (ucnt > GFC_INTEGER_8_HUGE)
+       cnt = ucnt - GFC_INTEGER_8_HUGE - 1;
+      else
+       cnt = ucnt;
       mx = GFC_INTEGER_8_HUGE;
     }
 #else