merge: expanded accounting-event coverage, rewrote cycle timing
[dcpu16] / common.c
index 5887c224815c43c4daadaa1eae0ce2656bb2b88e..bf94ef7c98341ea198a0618d847c9f79fde0c172 100644 (file)
--- a/common.c
+++ b/common.c
@@ -7,6 +7,13 @@
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
+#include <time.h>
+#include <sys/time.h>
+
+#ifdef __MACH__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif /* __MACH__ */
 
 #include "common.h"
 #include "dcpu16.h"
@@ -58,6 +65,17 @@ struct dynamic_array *dynarray_new(size_t entry_size, size_t grow_size) {
     return da;
 }
 
+void dynarray_empty(struct dynamic_array *da, void (*free_element)(void *)) {
+    while ( da->entries-- ) {
+        void *element = (void *)DYNARRAY_ITEM(*da, da->entries);
+
+        free_element(element);
+    }
+    free(da->a);
+    da->a = NULL;
+    da->allocated = 0;
+}
+
 /* copy item onto end of array */
 void *dynarray_add(struct dynamic_array *da, void *item) {
     void *dst;
@@ -205,6 +223,55 @@ char *strqtok_r(char *str, const char *sep, int esc, const char *quote, char **l
     return tok;
 }
 
+/* like gettimeofday, except with nanoseconds */
+inline
+int gettimespecofday(struct timespec *ts) {
+    int retval = 0;
+#ifdef __MACH__
+    clock_serv_t cclock;
+    mach_timespec_t mts;
+
+    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+    clock_get_time(cclock, &mts);
+    mach_port_deallocate(mach_task_self(), cclock);
+    ts->tv_sec = mts.tv_sec;
+    ts->tv_nsec = mts.tv_nsec;
+#else /* __MACH__ */
+    retval = clock_gettime(CLOCK_REALTIME, ts)
+#endif /* __MACH__ */
+
+    return retval;
+}
+
+inline
+int timespec_add(struct timespec *result, const struct timespec *x) {
+    result->tv_sec += x->tv_sec;
+    result->tv_nsec += x->tv_nsec;
+
+    result->tv_sec += result->tv_nsec / 1000000000;
+    result->tv_nsec %= 1000000000;
+
+    return 0;
+}
+
+inline
+int timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) {
+    if (x->tv_nsec < y->tv_nsec) {
+        int z = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
+        y->tv_nsec -= 1000000000 * z;
+        y->tv_sec += z;
+    }
+    if (x->tv_nsec - y->tv_nsec > 1000000000) {
+        int z = (x->tv_nsec - y->tv_nsec) / 1000000000;
+        y->tv_nsec += 1000000000 * z;
+        y->tv_sec -= z;
+    }
+    result->tv_sec = x->tv_sec - y->tv_sec;
+    result->tv_nsec = x->tv_nsec - y->tv_nsec;
+
+    return x->tv_sec < y->tv_sec;
+}
+
 int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
   /* Perform the carry for the later subtraction by updating y. */
   if (x->tv_usec < y->tv_usec) {