OSDN Git Service

Map compile-time constant references for POSIX clocks.
authorKeith Marshall <keith@users.osdn.me>
Thu, 18 Oct 2018 08:50:58 +0000 (09:50 +0100)
committerKeith Marshall <keith@users.osdn.me>
Thu, 18 Oct 2018 08:50:58 +0000 (09:50 +0100)
mingwrt/ChangeLog
mingwrt/include/time.h
mingwrt/mingwex/clockapi.c
mingwrt/mingwex/clockapi.h
mingwrt/mingwex/clockres.c
mingwrt/mingwex/clockset.c
mingwrt/mingwex/clocktime.c

index 637c78a..899e62b 100644 (file)
@@ -1,3 +1,28 @@
+2018-10-18  Keith Marshall  <keith@users.osdn.me>
+
+       Map compile-time constant references for POSIX clocks.
+
+       * include/time.h (CLOCK_REALTIME, CLOCK_MONOTONIC): Redefine, using...
+       (__MINGW_POSIX_CLOCKAPI): ...this new macro; it converts clock indices
+       to odd-valued compile-time constant pseudo-pointers, (distinguishable
+       from real pointers which are always even-valued), which may be passed
+       as clockid_t references in POSIX clock API function calls.
+
+       * mingwex/clockapi.h (struct __clockid__): Specify 4-byte alignment.
+       (__clock_api_is_valid): Change return type to "clockid_t".
+
+       * mingwex/clockapi.c (__clock_api_is_valid): Return an even-valued,
+       non-NULL, "clockid_t" reference pointer, or "NULL" if invalid; use...
+       (clock_reference): ...this new static inline function, to convert...
+       (CLOCK_REALTIME, CLOCK_MONOTONIC): ...these odd-valued pseudo-pointers
+       to their actual run-time pointer equivalents; delete their physical
+       initializations, which have now become invalid.
+
+       * mingwex/clockres.c (clock_getres)
+       * mingwex/clocktime.c (clock_gettime)
+       * mingwex/clockset.c (clock_settime): Update the "clockid_t" argument
+       to match the real pointer returned by __clock_api_is_valid()
+
 2018-10-08  Keith Marshall  <keith@users.osdn.me>
 
        Suppress autoconf detection of _aligned_malloc functions.
index 89f4b09..69186f6 100644 (file)
@@ -438,16 +438,24 @@ int nanosleep( const struct timespec *period, struct timespec *residual )
  */
 typedef struct __clockid__ *clockid_t;
 
-/* The standard clockid_t entities which we choose to support.
+/* POSIX prefers to have the standard clockid_t entities defined
+ * as macros, each of which represents an entity of type clockid_t.
+ * Since this is not an integer data type, POSIX does not strictly
+ * require such macros to expand to constant expressions; however,
+ * some ill-behaved applications, (GCC's Ada implementation is one
+ * such), depend on such expansions.  Thus, although it will incur
+ * a small additional run-time overhead to interpret them, we map
+ * such entities in terms of pseudo-pointer references, (which we
+ * discriminate from real pointer references, which we assume to
+ * be always to even valued addresses, by forcing odd values for
+ * the pseudo-pointer references).
  */
-extern clockid_t const CLOCK_REALTIME;
-extern clockid_t const CLOCK_MONOTONIC;
+#define __MINGW_POSIX_CLOCKAPI(ID)  ((clockid_t)(1 + ((ID) << 1)))
 
-/* Ensure that these clock implementations are detectable via
- * preprocessor #ifdef names.
+/* The standard clockid_t entities which we choose to support.
  */
-#define CLOCK_REALTIME CLOCK_REALTIME
-#define CLOCK_MONOTONIC CLOCK_MONOTONIC
+#define CLOCK_REALTIME  __MINGW_POSIX_CLOCKAPI (0)
+#define CLOCK_MONOTONIC __MINGW_POSIX_CLOCKAPI (1)
 
 /* Prototypes for the standard POSIX functions which provide the
  * API to these standard clockid_t entities.
index 20b8da0..9d122ae 100644 (file)
@@ -48,11 +48,6 @@ static struct __clockid__ clock_api[] =
   }
 };
 
-/* Publicly visible references to the preceding (opaque) clock definitions.
- */
-clockid_t const CLOCK_REALTIME = &clock_api[CLOCK_TYPE_REALTIME];
-clockid_t const CLOCK_MONOTONIC = &clock_api[CLOCK_TYPE_MONOTONIC];
-
 CLOCK_INLINE
 int64_t clock_api_getres_interval( clockid_t clock_api )
 {
@@ -122,24 +117,34 @@ int64_t clock_api_getres_interval( clockid_t clock_api )
   return clock_api->resolution = ((uint64_t)(clock_api_invalid_error()));
 }
 
-int __clock_api_is_valid( clockid_t clock_id )
+CLOCK_INLINE
+clockid_t clock_reference( clockid_t clock_id )
+{ /* Inline helper function to map pseudo-pointer clockid_t entity
+   * references to their actual implementation data references.
+   */
+  return ((uintptr_t)(clock_id) & 1)
+    ? & clock_api[(uintptr_t)(clock_id) >> 1]
+    : clock_id;
+}
+
+clockid_t __clock_api_is_valid( clockid_t clock_id )
 {
   /* Helper function, called by any of clock_getres(), clock_gettime(),
    * or clock_settime(), to check availability of the specified clock,
    * initializing it if necessary, returning...
    */
-  if(  (clock_id != NULL)
+  if( ((clock_id = clock_reference( clock_id )) != NULL)
   &&  ((unsigned)(clock_id->type) < CLOCK_TYPE_UNIMPLEMENTED)
   &&   (clock_api_getres_interval( clock_id ) > 0LL)  )
     /*
-     * ...a nominally TRUE value of 1, in the case of a valid clock...
+     * ...a nominally TRUE value, equivalent to the valid clock_id...
      */
-    return 1;
+    return clock_id;
 
-  /* ...or FALSE (zero), and setting "errno", otherwise.
+  /* ...or NULL, (nominally FALSE), and setting "errno", otherwise.
    */
   errno = EINVAL;
-  return 0;
+  return NULL;
 }
 
 /* $RCSfile$: end of file */
index 64fb9ad..cf68f86 100644 (file)
@@ -6,7 +6,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2017, MinGW.org Project
+ * Copyright (C) 2017, 2018, MinGW.org Project
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -60,7 +60,7 @@ typedef enum
 #define CLOCK_REALTIME_FREQUENCY  (NANOSECONDS_PER_SECOND / 100LL)
 #define UNIX_EPOCH_AS_FILETIME    (11644473600LL * CLOCK_REALTIME_FREQUENCY)
 
-typedef struct __clockid__
+typedef struct __attribute__((__aligned__(4))) __clockid__
 { /* Formal definition of the clockid_t structure; (opaque to
    * user application code).
    */
@@ -74,7 +74,7 @@ typedef struct __clockid__
  * within the scope of the implementation, (so not declared publicly),
  * this also provides initialization support.
  */
-extern int __clock_api_is_valid( clockid_t );
+extern clockid_t __clock_api_is_valid( clockid_t );
 
 #define CLOCK_INLINE  static __inline__ __attribute__((__always_inline__))
 
index b1640ed..9216296 100644 (file)
@@ -6,7 +6,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2017, MinGW.org Project
+ * Copyright (C) 2017, 2018, MinGW.org Project
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -39,7 +39,7 @@ int clock_getres( clockid_t clock_id, struct timespec *counter )
    * recorded within the associated implementation data structure,
    * together with a "validity check" status code.
    */
-  if( __clock_api_is_valid( clock_id ) )
+  if( (clock_id = __clock_api_is_valid( clock_id )) != NULL )
   {
     /* The clock is valid; its resolution must be broken down into
      * separate seconds and nanoseconds components, but only if the
index d3d9a3a..b82d8b8 100644 (file)
@@ -6,7 +6,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2017, MinGW.org Project
+ * Copyright (C) 2017, 2018, MinGW.org Project
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -40,7 +40,7 @@ int clock_settime( clockid_t clock_id, const struct timespec *timeval )
    * FIXME: Decide which clockid_t entities should support any such
    * adjustment; for the time being, deny all such requests.
    */
-  errno = ((timeval != NULL) && __clock_api_is_valid( clock_id ))
+  errno = ((timeval != NULL) && (__clock_api_is_valid( clock_id ) != NULL))
     ? EPERM : EINVAL;
   return -1;
 }
index b078e96..46ea9ab 100644 (file)
@@ -47,7 +47,7 @@ int clock_gettime( clockid_t clock_id, struct timespec *current )
   if( current == NULL )
     return clock_api_invalid_error();
 
-  if( __clock_api_is_valid( clock_id ) )
+  if( (clock_id = __clock_api_is_valid( clock_id )) != NULL )
   {
     /* We must be prepared to retrieve clock frequencies from Windows
      * APIs, which report either LARGE_INTEGER or FILETIME values, but