+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.
*/
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.
}
};
-/* 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 )
{
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 */
* $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
#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).
*/
* 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__))
* $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
* 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
* $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
* 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;
}
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