modified version of mutex test
authorLaurent MAZET <laurent.mazet@thalesgroup.com>
Fri, 26 Sep 2025 16:26:23 +0000 (18:26 +0200)
committerLaurent MAZET <laurent.mazet@thalesgroup.com>
Fri, 26 Sep 2025 16:26:23 +0000 (18:26 +0200)
mstime.c [new file with mode: 0644]
mstime.h [new file with mode: 0644]
mutex.c [new file with mode: 0644]
stat.c [new file with mode: 0644]
stat.h [new file with mode: 0644]

diff --git a/mstime.c b/mstime.c
new file mode 100644 (file)
index 0000000..161b68e
--- /dev/null
+++ b/mstime.c
@@ -0,0 +1,15 @@
+#include <time.h>
+
+#include "mstime.h"
+
+int64_t timespec_as_nanoseconds (struct timespec ts)
+{
+    return ts.tv_sec * 1000000000 + ts.tv_nsec ;
+}
+
+int64_t sys_timestamp (void)
+{
+    struct timespec ts;
+    clock_gettime (CLOCK_REALTIME, &ts);
+    return timespec_as_nanoseconds (ts);
+}
diff --git a/mstime.h b/mstime.h
new file mode 100644 (file)
index 0000000..959c40a
--- /dev/null
+++ b/mstime.h
@@ -0,0 +1,12 @@
+/* microsecond time */
+
+#ifndef __MSTIME_H__
+#define __MSTIME_H__
+
+#include "inttypes.h"
+
+typedef int64_t mstime_t;
+
+mstime_t sys_timestamp (void);
+
+#endif /* __MSTIME_H__ */
diff --git a/mutex.c b/mutex.c
new file mode 100644 (file)
index 0000000..10b85ef
--- /dev/null
+++ b/mutex.c
@@ -0,0 +1,184 @@
+/* depend: */
+/* cflags: */
+/* linker: mstime.o stat.o -lpthread -lm */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "mstime.h"
+#include "stat.h"
+
+/* static variables */
+
+char *progname = NULL;
+char *version = "1.1";
+
+int nb_measurements = 1000;
+int do_stat = 0;
+int hist_bin = 10;
+char *output = NULL;
+
+/* global variables */
+
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+int shared_flag = 0;
+mstime_t timestamp1, timestamp2;
+int try = 0;
+
+void *mutex_giver_task (__attribute__((unused)) void *arg)
+{
+    while (try < nb_measurements) {
+        pthread_mutex_lock (&mutex);
+        shared_flag = 1;
+        timestamp1 = sys_timestamp (); 
+        pthread_mutex_unlock (&mutex);
+    }
+    pthread_exit(NULL);
+}
+
+void *mutex_taker_task (__attribute__((unused)) void *arg)
+{
+    mstime_t *deltas = (mstime_t *) calloc (nb_measurements, sizeof (mstime_t));
+    assert (deltas);
+
+    while (try < nb_measurements) {
+        pthread_mutex_lock (&mutex);
+        if (shared_flag) {
+            timestamp2 = sys_timestamp ();
+            deltas[try++] = timestamp2 - timestamp1;
+            shared_flag = 0;
+        }
+        pthread_mutex_unlock(&mutex);
+    }
+
+    if (output) {
+        FILE *fd = fopen (output, "w");
+        assert (fd);
+        for (int i = 0; i < nb_measurements; i++) {
+            fprintf (fd, "%ld\n", deltas[i]);
+        }
+        fclose (fd);
+    }
+
+    if (do_stat) {
+        compute_statistics (deltas, nb_measurements, hist_bin);
+    }
+
+    free (deltas);
+
+    pthread_exit(NULL);
+}
+
+/* usage function */
+
+int usage (int ret)
+{
+    FILE *fd = ret ? stderr : stdout;
+    fprintf (fd, "usage: %s [-b int] [-h] [-n int] [-o file] [-s]\n", progname);
+    fprintf (fd, " -b: nb bins for histogram (%d)\n", hist_bin);
+    fprintf (fd, " -h: help message\n");
+    fprintf (fd, " -n: nb measurements (%d)\n", nb_measurements);
+    fprintf (fd, " -o: output raw data (%s)\n", (output) ? output : "none");
+    fprintf (fd, " -s: display statistics (%s)\n", (do_stat) ? "yes" : "no");
+    fprintf (fd, "%s version %s\n", progname, version);
+
+    return ret;
+}
+
+/* main function */
+
+int main (int argc, char *argv[])
+{
+
+    /* get basename */
+
+    char *pt = progname = argv[0];
+    while (*pt) {
+        if ((*pt == '/') || (*pt == '\\')) {
+           progname = pt + 1;
+        }
+        pt++;
+    }
+
+    /* process arguments */
+
+    while (argc-- > 1) {
+        char *arg = *(++argv);
+        if (arg[0] != '-') {
+            fprintf (stderr, "%s: invalid option -- %s\n", progname, arg);
+            return usage (1);
+        }
+        char c = arg[1];
+        switch (c) {
+        case 'b':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                fprintf (stderr, "%s: no number of bins specified\n", progname);
+                return usage (1);
+            }
+            hist_bin = atoi (arg);
+            break;
+        case 'n':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                fprintf (stderr, "%s: no number of measurements specified\n", progname);
+                return usage (1);
+            }
+            nb_measurements = atoi (arg);
+            break;
+        case 'o':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                fprintf (stderr, "%s: no output file specified\n", progname);
+                return usage (1);
+            }
+            output = arg;
+            break;
+        case 's':
+            do_stat = 1;
+            break;
+        case 'v':
+            printf ("version: %s\n", version);
+            break;
+        case 'h':
+        default:
+            return usage (c != 'h');
+        }
+    }
+
+    /* main process */
+
+    pthread_t giver_thread, taker_thread;
+    pthread_attr_t attr;
+    struct sched_param param;
+
+    pthread_attr_init(&attr);
+    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+    param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+    pthread_attr_setschedparam(&attr, &param);
+    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+
+    shared_flag = 1;
+    
+    if (pthread_create (&giver_thread, &attr, mutex_giver_task, NULL) != 0) {
+        fprintf (stderr, "error on pthread_create for giver_task\n");
+        return 1;
+    }
+
+    if (pthread_create (&taker_thread, &attr, mutex_taker_task, NULL) != 0) {
+        fprintf (stderr, "error on pthread_create for taker_task\n");
+        return 1;
+    }
+
+    pthread_join (giver_thread, NULL);
+    pthread_join (taker_thread, NULL);
+
+    pthread_mutex_destroy(&mutex);
+
+    return 0;
+}
diff --git a/stat.c b/stat.c
new file mode 100644 (file)
index 0000000..72fa6bf
--- /dev/null
+++ b/stat.c
@@ -0,0 +1,97 @@
+/* Statistic module */
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mstime.h"
+
+#include "stat.h"
+
+void compute_statistics (mstime_t *points, int nb, int bins)
+{
+
+    /* compute average, minimum and maximum */
+
+    double avg = 0;
+    double min = points[1];
+    double max = points[1];
+
+    for (int i = 1; i < nb; i++) {
+        double pt = points[i];
+        avg += pt;
+        if (pt < min) {
+            min = pt;
+        }
+        if (pt > max) {
+            max = pt;
+        }
+    }
+    avg = avg / (nb - 1);
+
+    printf ("Minimum = %.2lf\n", min);
+    printf ("Average = %.2lf\n", avg);
+    printf ("Maximum = %.2lf\n", max);
+
+    /* standard deviation */
+
+    double std = 0;
+
+    for (int i = 0; i < nb; i++) {
+        std += (points[i] - avg) * (points[i] - avg);
+    }
+    std = sqrt (std / (nb - 1));
+
+    /* compute median, 25 percentile and 75 percentile */
+
+    for (int j = 1; j < nb - 1; j++) {
+        int change_done = 0;
+        for (int i = 1; i < nb - 1; i++) {
+            if (points[i + 1] < points[i]) {
+                mstime_t tmp = points[i];
+                points[i] = points[i + 1];
+                points[i + 1] = tmp;
+                change_done = 1;
+            }
+        }
+        if (!change_done) {
+            break;
+        }
+    }
+    double p25 =  points[nb / 4];
+    if ((nb % 4 == 0) && (nb >= 4)) {
+        p25 = (p25 + points[nb / 4 - 1]) / 2;
+    }
+    double med =  points[nb / 2];
+    if (nb % 2 == 0) {
+        med = (med + points[nb / 2 - 1]) / 2;
+    }
+    double p75 =  points[(3 * nb) / 4];
+    if (((3 * nb) % 4 == 0) && (nb >= 4)) {
+        p75 = (p75 + points[(3 * nb) / 4 - 1]) / 2;
+    }
+
+    printf ("25th %% = %.2lf\n", p25);
+    printf ("Median = %.2lf\n", med);
+    printf ("75th %% = %.2lf\n", p75);
+
+    /* compute histogram */
+
+    int *hist = (int *) calloc (bins, sizeof (int));
+    assert (hist);
+
+    double gap = (max - min) / bins;
+    for (int i = 0; i < nb; i++) {
+        hist[(int)((points[i] - min) / gap)]++;
+    }
+
+    printf ("Histogram\n");
+    for (int i = 0; i < bins - 1; i++) {
+        printf (" [%.2lf - %.2lf] = %d\n", min + i * gap, min + (i + 1) * gap, hist[i]);
+    }
+    printf (" [%.2lf - %.2lf] = %d\n", min + (bins - 1) * gap, max, hist[bins - 1]);
+
+    free (hist);
+
+}
diff --git a/stat.h b/stat.h
new file mode 100644 (file)
index 0000000..4ef040f
--- /dev/null
+++ b/stat.h
@@ -0,0 +1,10 @@
+/* Statistic module */
+
+#ifndef __STAT_H__
+#define __STAT_H__
+
+#include "mstime.h"
+
+void compute_statistics (mstime_t *points, int nb, int bins);
+
+#endif /* __STAT_H__ */