From: Laurent MAZET Date: Fri, 26 Sep 2025 16:26:23 +0000 (+0200) Subject: modified version of mutex test X-Git-Url: https://secure.softndesign.org/git/?a=commitdiff_plain;h=22a5dd0dd933264453898c7a998331d33e5fc9d9;p=benchmarks.git modified version of mutex test --- diff --git a/mstime.c b/mstime.c new file mode 100644 index 0000000..161b68e --- /dev/null +++ b/mstime.c @@ -0,0 +1,15 @@ +#include + +#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 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 index 0000000..10b85ef --- /dev/null +++ b/mutex.c @@ -0,0 +1,184 @@ +/* depend: */ +/* cflags: */ +/* linker: mstime.o stat.o -lpthread -lm */ + +#include +#include +#include +#include +#include +#include +#include + +#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, ¶m); + 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 index 0000000..72fa6bf --- /dev/null +++ b/stat.c @@ -0,0 +1,97 @@ +/* Statistic module */ + +#include +#include +#include +#include + +#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 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__ */