+CFLAGS= -D_GNU_SOURCE
+CFLAGS+= -I/usr/include/dlog -I/usr/lib/glib-2.0/include -I/usr/include/glib-2.0
+CFLAGS+= -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -L/usr/lib
+CFLAGS+=-Wall -O2 -g
+LDFLAGS= -lglib-2.0 -lgobject-2.0 -lgio-2.0 -lgmodule-2.0 -ldbus-1 -lgthread-2.0 -lpthread -lrt -lpcre
+LDFLAGS+=-lm
+DFTSRC=benchmark/common.c
+
+all:
+ gcc $(CFLAGS) -pg -o benchmark/pipe $(DFTSRC) benchmark/pipe.c $(LDFLAGS)
+ gcc $(CFLAGS) -o benchmark/socket $(DFTSRC) benchmark/socket.c $(LDFLAGS)
+ gcc $(CFLAGS) -o benchmark/sharedmem $(DFTSRC) benchmark/sharedmem.c $(LDFLAGS)
+ gcc $(CFLAGS) -o benchmark/gdbus $(DFTSRC) benchmark/gdbus.c $(LDFLAGS)
+ gcc $(CFLAGS) -o benchmark/libdbus $(DFTSRC) benchmark/libdbus.c $(LDFLAGS)
+
+
install:
make -C policychecker install
+ mkdir -p $(DESTDIR)/usr/bin
+ cp benchmark/pipe $(DESTDIR)/usr/bin/pipe
+ cp benchmark/socket $(DESTDIR)/usr/bin/socket
+ cp benchmark/sharedmem $(DESTDIR)/usr/bin/sharedmem
+ cp benchmark/gdbus $(DESTDIR)/usr/bin/gdbus
+ cp benchmark/libdbus $(DESTDIR)/usr/bin/libdbus
--- /dev/null
+#include "common.h"
+
+int cpu_pin(int cpuid, int pid) {
+ int ncpu = get_nprocs();
+ cpu_set_t set;
+
+ cpuid %= ncpu;
+
+ CPU_ZERO(&set);
+ CPU_SET(cpuid, &set);
+
+ if(sched_setaffinity(pid, sizeof(set), &set) == -1)
+ return 0;
+ else
+ return 1;
+}
+
+void print_help(char **argv)
+{
+ printf("%s [-m <message size>] [-p <#process>] [-b] [-l] [-h]\n", argv[0]);
+ printf("-m: message size\n");
+ printf("-p: the number of process (default: the number of CPU)\n");
+ printf("-b: measure bandwidth\n");
+ printf("-l: measure latency\n");
+ printf("-h: print help page\n");
+}
--- /dev/null
+#ifndef BENCHMARK_COMMON
+#define BENCHMARK_COMMON
+
+#include <fcntl.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sched.h>
+#include <sys/sysinfo.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+
+#define WARMUP_TRY 100
+#define REAL_TRY 1000
+
+#define US 1000000
+#define NS 1000000000
+
+#define ONE_PAGE_SIZE 4096
+
+typedef enum {false, true} bool;
+void print_help(char **argv);
+int cpu_pin(int cpuid, int pid);
+
+#endif
--- /dev/null
+/*
+ * lat_gdbus.c - gdbus IPC latency
+ *
+ */
+
+#include <gio/gio.h>
+#include "common.h"
+
+typedef struct _state {
+ int iters;
+ char *buf;
+ bool is_lt;
+ GMainLoop *main_loop;
+} State;
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+static void server_name_acquired_handler (GDBusConnection *conn, const gchar *name, gpointer user_data)
+{ }
+
+static void server_name_lost_handler (GDBusConnection *conn, const gchar *name, gpointer user_data)
+{ }
+
+static GVariant *handle_get_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{ }
+
+static gboolean handle_set_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *value,
+ GError **error,
+ gpointer user_data)
+{ }
+
+static void handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ static int bw_cnt = 0;
+ static int cnt = 0;
+ static unsigned long long start;
+ unsigned long long end;
+ unsigned long long temp;
+ struct timespec clock;
+ State *state = (State *)user_data;
+
+ if (g_strcmp0 (method_name, "Perf") == 0)
+ {
+ if(state->is_lt)
+ g_variant_get (parameters, "(ts)", &start, &state->buf);
+ else
+ g_variant_get (parameters, "(ts)", &temp, &state->buf);
+
+ g_object_unref (invocation);
+
+ if(++cnt == state->iters) {cnt = 0; g_main_loop_quit (state->main_loop); }
+
+ if(state->buf[0] != 'r')
+ return;
+
+ if(state->is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+ printf("latency: %0.4f\n", lt);
+#endif
+
+ if(lt > 0) {
+ lt_cnt++;
+ total += lt;
+ if(lt > max)
+ max = lt;
+
+ if(lt < min)
+ min = lt;
+ }
+ }
+ else {
+ bw_cnt++;
+ if(bw_cnt == 1) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ + (unsigned long long)clock.tv_nsec;
+ }
+
+ if(bw_cnt == REAL_TRY) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+ printf("bandwidth: %llu (/s)\n", bw);
+ }
+ }
+ }
+}
+
+static const GDBusInterfaceVTable _vtable =
+{
+ handle_method_call,
+ handle_get_property,
+ handle_set_property
+};
+
+void Receive(register int size, const char *name, const char *path, bool is_lt)
+{
+ State state;
+ register char *buf = (char *)malloc(size);
+
+ GMainLoop *g_main_loop = g_main_loop_new (g_main_context_default(), FALSE);
+ GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_assert(conn != NULL);
+ guint id = g_bus_own_name_on_connection (conn, name, G_BUS_NAME_OWNER_FLAGS_NONE
+ , server_name_acquired_handler
+ , server_name_lost_handler
+ , NULL, NULL);
+ g_assert(id != 0);
+
+ static gchar _interface_introspection_xml[5000];
+ sprintf(_interface_introspection_xml,
+ "<node>"
+ " <interface name='%s'>"
+ " <method name='Perf'>"
+ " <arg type='t' name='Start' direction='in'/>"
+ " <arg type='s' name='Msg' direction='in'/>"
+ " <arg type='t' name='Response' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>", name);
+
+ GDBusNodeInfo *introspection_data = NULL;
+ introspection_data = g_dbus_node_info_new_for_xml (_interface_introspection_xml, NULL);
+
+ state.iters = WARMUP_TRY + REAL_TRY;
+ state.is_lt = is_lt;
+ state.buf = buf;
+ state.main_loop = g_main_loop;
+
+ guint rid = g_dbus_connection_register_object (conn, path
+ , introspection_data->interfaces[0]
+ , &_vtable
+ , (gpointer)&state, NULL, NULL);
+ g_assert(rid > 0);
+
+
+
+ g_main_loop_run (g_main_loop);
+
+ g_dbus_connection_unregister_object(conn, rid);
+ g_bus_unown_name (id);
+ g_dbus_connection_close(conn, NULL, NULL, NULL);
+ g_object_unref(conn);
+ free(buf);
+}
+
+void Send(register int size, const char *name, const char *path, bool is_lt)
+{
+ unsigned long long start;
+ register char *cptr = (char *)malloc(size);
+ GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_assert(conn != NULL);
+
+ sleep(2);
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ struct timespec clock;
+
+ memset(cptr, 0, size);
+ if(i >= WARMUP_TRY)
+ cptr[0] = 'r';
+ else
+ cptr[0] = 'w';
+
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ }
+ else
+ start = 0;
+
+ //GError *error = NULL;
+ g_dbus_connection_call(conn,
+ name,
+ path,
+ name,
+ "Perf",
+ g_variant_new ("(ts)", start, cptr),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+ /*if(error != NULL) {
+ g_printerr("Error=%s\n", error->message);
+ g_error_free (error);
+ }*/
+ if(is_lt) {
+ if(size <= ONE_PAGE_SIZE)
+ usleep(5000);
+ else if(size <= 10 * ONE_PAGE_SIZE)
+ usleep(10000);
+ else if(size <= 100 * ONE_PAGE_SIZE)
+ usleep(20000);
+ else
+ usleep(40000);
+ }
+ }
+
+ g_dbus_connection_close(conn, NULL, NULL, NULL);
+ g_object_unref(conn);
+ free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+ int ret;
+ int returnp[nprocs/2][2];
+ int pids[nprocs];
+ int ready_fd;
+ char *ready_ptr;
+
+ ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(ready_fd == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(ready_fd, sizeof(char))) {
+ perror("Ftruncate");
+ return;
+ }
+ ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+ MAP_SHARED, ready_fd, 0);
+ if(ready_ptr == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ close(ready_fd);
+ ready_ptr[0] = 'n';
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(returnp[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ for(int child = 1; child < nprocs; child++) {
+ char name[30];
+ char path[30];
+
+ sprintf(name, "org.gdbus.server%d", child/2);
+ sprintf(path, "/org/gdbus/server%d", child/2);
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(child, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ // Wait for parent
+ while(ready_ptr[0] == 'n') {
+ }
+
+ if(child % 2 == 0) {
+ Receive(msize, (const char *)name, (const char *)path, false);
+
+ //send result(bandwidth) to parent
+ {
+ int wres;
+ close(returnp[child/2][0]);
+ wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+ if (wres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe sender");
+ exit(1);
+ }
+ close(returnp[child/2][1]);
+ }
+ }
+ else {
+ Send(msize, (const char *)name, (const char *)path, false);
+ }
+
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ pids[child] = pid;
+ break;
+ }
+ }
+
+ sleep(1);
+ ready_ptr[0] = 'y';
+
+ Receive(msize, "org.gdbus.server0", "/org/gdbus/server0", false);
+ for(int child = 1; child < nprocs; child++) {
+ //receive result(bandwidth) from child(s)
+ if(child % 2 == 0) {
+ int rres;
+ unsigned long long child_bw;
+
+ close(returnp[child/2][1]);
+ rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+ if (rres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe receiver");
+ exit(1);
+ }
+ close(returnp[child/2][0]);
+ bw += child_bw;
+ }
+
+ waitpid(pids[child], NULL, 0);
+ }
+ ret = munmap(ready_ptr, sizeof(bool));
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink("isready");
+ if (ret != 0) {
+ perror("shm unlink");
+ //exit(1);
+ }
+ printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+
+void Measure_latency(void)
+{
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(1, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ Send(msize, "org.gdbus.server", "/org/gdbus/server", true);
+
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ Receive(msize, "org.gdbus.server", "/org/gdbus/server", true);
+ printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+
+ waitpid(pid, NULL, 0);
+ return;
+ }
+}
+
+ int
+main(int argc, char **argv)
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ nprocs = get_nprocs();
+ if(nprocs == 1)
+ nprocs = 2;
+
+ msize = 3;
+ lt_on = bw_on = false;
+ while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+ switch(opt) {
+ case 'm':
+ msize = atoi(optarg);
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ if(nprocs <= 0) {
+ printf("The number of process should be larger than 0\n");
+ exit(0);
+ }
+ if(nprocs % 2 != 0) {
+ printf("The number of process should be even\n");
+ exit(0);
+ }
+ break;
+ case 'b':
+ bw_on = true;
+ break;
+ case 'l':
+ lt_on = true;
+ break;
+ case 'h':
+ print_help(argv);
+ exit(0);
+ }
+ }
+
+ if(!lt_on && !bw_on) {
+ print_help(argv);
+ exit(0);
+ }
+
+ bw = 0;
+ lt_cnt = 0;
+ max = total = 0.0;
+ min = 1000000.0;
+
+ if(lt_on)
+ Measure_latency();
+
+ if(bw_on)
+ Measure_bandwidth();
+}
--- /dev/null
+/*
+ * lat_libdbus.c - libdbus IPC latency
+ *
+ */
+
+#include <dbus/dbus.h>
+#include "common.h"
+
+typedef struct _state {
+ int iters;
+ char *buf;
+ bool is_lt;
+} State;
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+bool stop;
+
+static void unregistered_func (DBusConnection *connection, void *user_data)
+{ }
+
+static DBusHandlerResult message_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ static int bw_cnt = 0;
+ static int cnt = 0;
+ static unsigned long long start;
+ unsigned long long end;
+ unsigned long long temp;
+ struct timespec clock;
+ State *state = (State *)user_data;
+
+ //if (dbus_message_is_method_call (message, "org.libdbus.server", "Perf"))
+ {
+ if(state->is_lt)
+ dbus_message_get_args (message, NULL, DBUS_TYPE_UINT64, &start,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &state->buf, &msize, DBUS_TYPE_INVALID);
+ else
+ dbus_message_get_args (message, NULL, DBUS_TYPE_UINT64, &temp,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &state->buf, &msize, DBUS_TYPE_INVALID);
+
+ if(++cnt == state->iters) {cnt = 0; stop = true; }
+
+ if(state->buf[0] != 'r')
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+ if(state->is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ double lt = (double)(end - start) / 1000;
+
+ if(lt) {
+ lt_cnt++;
+ total += lt;
+ if(lt > max)
+ max = lt;
+
+ if(lt < min)
+ min = lt;
+ }
+ }
+ else {
+ bw_cnt++;
+ if(bw_cnt == 1) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ + (unsigned long long)clock.tv_nsec;
+ }
+
+ if(bw_cnt == REAL_TRY) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+ printf("bandwidth: %llu (/s)\n", bw);
+ }
+ }
+ }
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusObjectPathVTable vtable = {
+ unregistered_func,
+ message_func,
+ NULL,
+};
+
+
+void Receive(register int size, const char *name, const char *path, bool is_lt)
+{
+ State state;
+ DBusError error;
+ DBusConnection* conn;
+ char *buf = (char *)malloc(size);
+
+ dbus_error_init(&error);
+ conn = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ exit(1);
+ }
+
+ int ret = dbus_bus_request_name (conn, name,
+ DBUS_NAME_FLAG_REPLACE_EXISTING|DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL);
+ if( ret == -1 ) {
+ perror("dbus_bus_request_name()\n");
+ exit(1);
+ }
+
+ state.iters = WARMUP_TRY + REAL_TRY;
+ state.is_lt = is_lt;
+ state.buf = buf;
+ dbus_connection_register_object_path (conn, path, &vtable, &state);
+
+ //for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ while(1) {
+ if(!dbus_connection_read_write_dispatch(conn, -1)) {
+ printf("read on parent error\n");
+ exit(1);
+ }
+
+ if(stop)
+ break;
+ }
+ stop = false;
+ //}
+
+ dbus_connection_unregister_object_path (conn, path);
+ free(buf);
+}
+
+void Send(register int size, const char *name, const char *path, const char *client, bool is_lt)
+{
+ DBusMessage *msg;
+ unsigned long long start;
+
+ char *cptr = (char *)malloc(size);
+ DBusConnection* conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ int ret = dbus_bus_request_name (conn, client, DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
+ if( ret == -1 ) {
+ perror("dbus_bus_request_name()\n");
+ exit(1);
+ }
+
+ sleep(2);
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ struct timespec clock;
+
+ memset(cptr, 0, size);
+ if(i >= WARMUP_TRY)
+ cptr[0] = 'r';
+ else
+ cptr[0] = 'w';
+
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ }
+ else
+ start = 0;
+
+ msg = dbus_message_new_method_call (name, path, name, "Perf");
+ DBusMessageIter iter;
+ dbus_message_iter_init_append (msg, &iter);
+ dbus_message_append_args (msg,
+ DBUS_TYPE_UINT64, &start,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cptr, size,
+ DBUS_TYPE_INVALID);
+ dbus_message_set_no_reply(msg, 1);
+ dbus_connection_send (conn, msg, NULL);
+
+ if(is_lt) {
+ if(size <= ONE_PAGE_SIZE)
+ usleep(5000);
+ else if(size <= 10 * ONE_PAGE_SIZE)
+ usleep(10000);
+ else if(size <= 100 * ONE_PAGE_SIZE)
+ usleep(20000);
+ else
+ usleep(40000);
+ }
+ }
+
+ dbus_connection_flush(conn);
+ dbus_message_unref (msg);
+ free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+ int ret;
+ int returnp[nprocs/2][2];
+ int pids[nprocs];
+ int ready_fd;
+ char *ready_ptr;
+
+ ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(ready_fd == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(ready_fd, sizeof(char))) {
+ perror("Ftruncate");
+ return;
+ }
+ ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+ MAP_SHARED, ready_fd, 0);
+ if(ready_ptr == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ close(ready_fd);
+ ready_ptr[0] = 'n';
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(returnp[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ for(int child = 1; child < nprocs; child++) {
+ char name[30];
+ char path[30];
+
+ sprintf(name, "org.libdbus.server%d", child/2);
+ sprintf(path, "/org/libdbus/server%d", child/2);
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(child, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ // Wait for parent
+ while(ready_ptr[0] == 'n') {
+ }
+
+ if(child % 2 == 0) {
+ Receive(msize, (const char *)name, (const char *)path, false);
+
+ //send result(bandwidth) to parent
+ {
+ int wres;
+ close(returnp[child/2][0]);
+ wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+ if (wres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe sender");
+ exit(1);
+ }
+ close(returnp[child/2][1]);
+ }
+ }
+ else {
+ char client[30];
+ sprintf(client, "org.libdbus.client%d", child);
+ Send(msize, (const char *)name, (const char *)path, (const char *)client, false);
+ }
+
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ pids[child] = pid;
+ break;
+ }
+ }
+
+ sleep(1);
+ ready_ptr[0] = 'y';
+
+ Receive(msize, "org.libdbus.server0", "/org/libdbus/server0", false);
+ for(int child = 1; child < nprocs; child++) {
+ //receive result(bandwidth) from child(s)
+ if(child % 2 == 0) {
+ int rres;
+ unsigned long long child_bw;
+
+ close(returnp[child/2][1]);
+ rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+ if (rres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe receiver");
+ exit(1);
+ }
+ close(returnp[child/2][0]);
+ bw += child_bw;
+ }
+
+ waitpid(pids[child], NULL, 0);
+ }
+ ret = munmap(ready_ptr, sizeof(bool));
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink("isready");
+ if (ret != 0) {
+ perror("shm unlink");
+ //exit(1);
+ }
+ printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(1, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ Send(msize, "org.libdbus.server", "/org/libdbus/server", "org.libdbus.client", true);
+
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ Receive(msize, "org.libdbus.server", "/org/libdbus/server", true);
+ printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+ waitpid(pid, NULL, 0);
+ return;
+ }
+}
+
+ int
+main(int argc, char **argv)
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ nprocs = get_nprocs();
+ if(nprocs == 1)
+ nprocs = 2;
+
+ msize = 3;
+ lt_on = bw_on = false;
+ while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+ switch(opt) {
+ case 'm':
+ msize = atoi(optarg);
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ if(nprocs <= 0) {
+ printf("The number of process should be larger than 0\n");
+ exit(0);
+ }
+ if(nprocs % 2 != 0) {
+ printf("The number of process should be even\n");
+ exit(0);
+ }
+ break;
+ case 'b':
+ bw_on = true;
+ break;
+ case 'l':
+ lt_on = true;
+ break;
+ case 'h':
+ print_help(argv);
+ exit(0);
+ }
+ }
+
+ if(!lt_on && !bw_on) {
+ print_help(argv);
+ exit(0);
+ }
+
+ bw = 0;
+ lt_cnt = 0;
+ max = total = 0.0;
+ min = 1000000.0;
+
+ if(lt_on)
+ Measure_latency();
+
+ if(bw_on)
+ Measure_bandwidth();
+}
--- /dev/null
+/*
+ * lat_pipe.c - pipe IPC latency
+ *
+ */
+
+#include "common.h"
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+void Receive(int rfd1, int rfd2, register int size, bool is_lt)
+{
+ static int bw_cnt = 0;
+ unsigned long long start;
+ unsigned long long end;
+ register char *buf = (char *)malloc(size);
+
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ if(is_lt) {
+ if (read(rfd1, (void *)&start, sizeof(unsigned long long))
+ != sizeof(unsigned long long)) {
+ perror("(read 1) read/write on pipe receiver");
+ exit(1);
+ }
+ }
+
+ if (read(rfd2, buf, size) != size) {
+ perror("(read 2) read/write on pipe receiver");
+ exit(1);
+ }
+ else if(buf[0] == 'r') {
+ struct timespec clock;
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+ printf("latency: %0.4f\n", lt);
+#endif
+
+ if(lt > 0) {
+ lt_cnt++;
+ total += lt;
+ if(lt > max)
+ max = lt;
+
+ if(lt < min)
+ min = lt;
+ }
+ }
+ else {
+ bw_cnt++;
+ if(bw_cnt == 1) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ + (unsigned long long)clock.tv_nsec;
+ }
+
+ if(bw_cnt == REAL_TRY) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+ printf("bandwidth: %llu (/s)\n", bw);
+ }
+ }
+ }
+ }
+
+ free(buf);
+}
+
+void Send(int wfd1, int wfd2, register int size, bool is_lt)
+{
+ register char *cptr = (char *)malloc(size);
+
+ sleep(2);
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ int wres1, wres2;
+ struct timespec clock;
+
+ memset(cptr, 0, size);
+ if(i >= WARMUP_TRY)
+ cptr[0] = 'r';
+ else
+ cptr[0] = 'w';
+
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ unsigned long long start = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ wres1 = write(wfd1, (void *)&start, sizeof(unsigned long long));
+ if (wres1 != sizeof(unsigned long long)) {
+ perror("(write 1) read/write on pipe sender");
+ exit(1);
+ }
+ }
+ wres2 = write(wfd2, cptr, size);
+ if (wres2 != size) {
+ perror("(write 2) read/write on pipe sender");
+ exit(1);
+ }
+
+ if(is_lt) {
+ if(size <= ONE_PAGE_SIZE)
+ usleep(5000);
+ else if(size <= 10 * ONE_PAGE_SIZE)
+ usleep(10000);
+ else if(size <= 100 * ONE_PAGE_SIZE)
+ usleep(20000);
+ else
+ usleep(40000);
+ }
+ }
+
+ free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+ int ret;
+ int returnp[nprocs/2][2];
+ int p[nprocs/2][2];
+ int pids[nprocs];
+ int ready_fd;
+ char *ready_ptr;
+
+ ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(ready_fd == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(ready_fd, sizeof(char))) {
+ perror("Ftruncate");
+ return;
+ }
+ ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+ MAP_SHARED, ready_fd, 0);
+ if(ready_ptr == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ close(ready_fd);
+ ready_ptr[0] = "n";
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(returnp[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(p[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ for(int child = 1; child < nprocs; child++) {
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(child, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+ if(child % 2 == 0) {
+ close(p[child/2][1]);
+ }
+ else
+ close(p[child/2][0]);
+
+ // Wait for parent
+ while(ready_ptr[0] == "n") {
+ }
+
+ if(child % 2 == 0) {
+ Receive(0, p[child/2][0], msize, false);
+ close(p[child/2][0]);
+
+ //send result(bandwidth) to parent
+ {
+ int wres;
+ close(returnp[child/2][0]);
+ wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+ if (wres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe sender");
+ exit(1);
+ }
+ close(returnp[child/2][1]);
+ }
+ }
+ else {
+ Send(0, p[child/2][1], msize, false);
+ close(p[child/2][1]);
+ }
+
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ pids[child] = pid;
+ }
+ }
+
+ usleep(100000);
+ close(p[0][1]);
+ ready_ptr[0] = "y";
+
+ Receive(0, p[0][0], msize, false);
+ close(p[0][0]);
+ for(int child = 1; child < nprocs; child++) {
+ //receive result(bandwidth) from child(s)
+ if(child % 2 == 0) {
+ int rres;
+ unsigned long long child_bw;
+
+ close(returnp[child/2][1]);
+ rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+ if (rres != sizeof(unsigned long long)) {
+ perror("(read return) read/write on pipe receiver");
+ exit(1);
+ }
+ close(returnp[child/2][0]);
+ bw += child_bw;
+ }
+
+ waitpid(pids[child], NULL, 0);
+ }
+
+ ret = munmap(ready_ptr, sizeof(bool));
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink("isready");
+ if (ret != 0) {
+ perror("shm unlink");
+ //exit(1);
+ }
+ printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+ int p1[2], p2[2];
+
+ if (pipe(p1) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ if (pipe(p2) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(1, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+ close(p1[0]);
+ close(p2[0]);
+ Send(p1[1], p2[1], msize, true);
+ close(p1[1]);
+ close(p2[1]);
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ close(p1[1]);
+ close(p2[1]);
+ Receive(p1[0], p2[0], msize, true);
+ close(p1[0]);
+ close(p2[0]);
+ printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+ waitpid(pid, NULL, 0);
+ return;
+ }
+}
+
+ int
+main(int argc, char **argv)
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ nprocs = get_nprocs();
+ if(nprocs == 1)
+ nprocs = 2;
+
+ msize = 3;
+ lt_on = bw_on = false;
+ while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+ switch(opt) {
+ case 'm':
+ msize = atoi(optarg);
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ if(nprocs <= 0) {
+ printf("The number of process should be larger than 0\n");
+ exit(0);
+ }
+ if(nprocs % 2 != 0) {
+ printf("The number of process should be even\n");
+ exit(0);
+ }
+ break;
+ case 'b':
+ bw_on = true;
+ break;
+ case 'l':
+ lt_on = true;
+ break;
+ case 'h':
+ print_help(argv);
+ exit(0);
+ }
+ }
+
+ if(!lt_on && !bw_on) {
+ print_help(argv);
+ exit(0);
+ }
+
+ bw = 0;
+ lt_cnt = 0;
+ max = total = 0.0;
+ min = 1000000.0;
+
+ if(lt_on)
+ Measure_latency();
+
+ if(bw_on)
+ Measure_bandwidth();
+}
--- /dev/null
+/*
+ * lat_sharedmem.c - sharedmem IPC latency
+ *
+ */
+
+#include "common.h"
+
+#define SHM1 0
+#define SHM2 1
+
+const char *shm_name1 = "sharedmem1";
+const char *shm_name2 = "sharedmem2";
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+void Receive(void *r1, register char *r2, register int size, bool is_lt)
+{
+ static int bw_cnt = 0;
+ unsigned long long start;
+ unsigned long long end;
+ struct timespec clock;
+ register char read_cnt = 0;
+ register char *buf = (char *)malloc(size);
+
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+repeat:
+ if(r2[1] == read_cnt)
+ goto repeat;
+ else
+ read_cnt = r2[1];
+
+ memcpy(buf, r2, size);
+ r2[2] = read_cnt;
+ if(buf[0] != 'r')
+ continue;
+
+ if(is_lt) {
+ memcpy((void *)&start, r1, sizeof(unsigned long long));
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+ printf("latency: %0.4f\n", lt);
+#endif
+
+ if(lt > 0) {
+ lt_cnt++;
+ total += lt;
+ if(lt > max)
+ max = lt;
+
+ if(lt < min)
+ min = lt;
+ }
+ }
+ else {
+ bw_cnt++;
+ if(bw_cnt == 1) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ + (unsigned long long)clock.tv_nsec;
+ }
+
+ if(bw_cnt == REAL_TRY) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+ printf("bandwidth: %llu (/s)\n", bw);
+ }
+ }
+ }
+
+ sleep(2);
+ free(buf);
+}
+
+void Send(void *w1, register char *w2, register int size, bool is_lt)
+{
+ register char write_cnt = 0;
+ register char *cptr = (char *)malloc(size);
+
+ sleep(2);
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ struct timespec clock;
+repeat:
+ if(w2[2] == write_cnt) {
+ if(write_cnt == 127)
+ write_cnt = 1;
+ else
+ write_cnt++;
+ }
+ else {
+ goto repeat;
+ }
+
+ memset(cptr, 0, size);
+ if(i >= WARMUP_TRY)
+ cptr[0] = 'r';
+ else
+ cptr[0] = 'w';
+ cptr[1] = write_cnt;
+
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ unsigned long long start = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ memcpy(w1, (void *)&start, sizeof(unsigned long long));
+ }
+ memcpy(w2, cptr, size);
+
+ if(is_lt) {
+ if(size <= ONE_PAGE_SIZE)
+ usleep(5000);
+ else if(size <= 10 * ONE_PAGE_SIZE)
+ usleep(10000);
+ else if(size <= 100 * ONE_PAGE_SIZE)
+ usleep(20000);
+ else
+ usleep(40000);
+ }
+ }
+
+ sleep(1);
+ memset(w2, 0, size);
+ free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+ int ret;
+ char name[25];
+ int returnp[nprocs/2][2];
+ int shm_fd[nprocs/2];
+ void *shm_ptr[nprocs/2];
+ int pids[nprocs];
+ int ready_fd;
+ char *ready_ptr;
+
+ ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(ready_fd == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(ready_fd, sizeof(char))) {
+ perror("Ftruncate");
+ return;
+ }
+ ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+ MAP_SHARED, ready_fd, 0);
+ if(ready_ptr == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ close(ready_fd);
+ ready_ptr[0] = "n";
+
+ for(int i = 0; i < nprocs/2; i++) {
+ sprintf(name, "bwsharedmem%d", i);
+ shm_fd[i] = shm_open(name, O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(shm_fd[i] == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(shm_fd[i], msize)) {
+ perror("Ftruncate");
+ return;
+ }
+ shm_ptr[i] = mmap(0, msize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd[i], 0);
+ if(shm_ptr[i] == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ }
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(returnp[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ for(int child = 1; child < nprocs; child++) {
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(child, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ // Wait for parent
+ while(ready_ptr[0] == "n") {
+ }
+
+ if(child % 2 == 0) {
+ Receive(NULL, shm_ptr[child/2], msize, false);
+
+ //send result(bandwidth) to parent
+ {
+ int wres;
+ close(returnp[child/2][0]);
+ wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+ if (wres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe sender");
+ exit(1);
+ }
+ close(returnp[child/2][1]);
+ }
+ }
+ else {
+ Send(NULL, shm_ptr[child/2], msize, false);
+ }
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ pids[child] = pid;
+ break;
+ }
+ }
+
+ sleep(1);
+ ready_ptr[0] = "y";
+
+ Receive(NULL, shm_ptr[0], msize, false);
+ for(int child = 1; child < nprocs; child++) {
+ //receive result(bandwidth) from child(s)
+ if(child % 2 == 0) {
+ int rres;
+ unsigned long long child_bw;
+
+ close(returnp[child/2][1]);
+ rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+ if (rres != sizeof(unsigned long long)) {
+ perror("(read return) read/write on pipe receiver");
+ exit(1);
+ }
+ close(returnp[child/2][0]);
+ bw += child_bw;
+ }
+
+ waitpid(pids[child], NULL, 0);
+ }
+
+ ret = munmap(ready_ptr, sizeof(bool));
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink("isready");
+ if (ret != 0) {
+ perror("shm unlink");
+ //exit(1);
+ }
+
+ for(int i = 0; i < nprocs/2; i++) {
+ sprintf(name, "bwsharedmem%d", i);
+ ret = munmap(shm_ptr[i], msize);
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink(name);
+ if (ret != 0) {
+ perror("shm unlink");
+ //exit(1);
+ }
+ }
+
+ printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+ int ret;
+ int shm_fd[2];
+ void *shm_ptr[2];
+ // int seals = 0;
+ // seals | F_SEAL_SHRINK;
+ // seals | F_SEAL_WRITE;
+ //shm_fd[SHM1] = syscall(SYS_memfd_create, shm_name1, MFD_ALLOW_SEALING);
+ //shm_fd[SHM1] = memfd_create(shm_name1, MFD_ALLOW_SEALING);
+ shm_fd[SHM1] = shm_open(shm_name1, O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(shm_fd[SHM1] == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(shm_fd[SHM1], sizeof(unsigned long long))) {
+ perror("Ftruncate");
+ return;
+ }
+ shm_ptr[SHM1] = mmap(0, sizeof(unsigned long long), PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd[SHM1], 0);
+ if(shm_ptr[SHM1] == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ /*if(fcntl(shm_fd[SHM1], F_ADD_SEALS, seals) == -1) {
+ perror("Fcntl");
+ return;
+ }*/
+
+ //shm_fd[SHM2] = syscall(SYS_memfd_create, shm_name2, MFD_ALLOW_SEALING);
+ //shm_fd[SHM2] = memfd_create(shm_name2, MFD_ALLOW_SEALING);
+ shm_fd[SHM2] = shm_open(shm_name2, O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(shm_fd[SHM2] == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(shm_fd[SHM2], msize)) {
+ perror("Ftruncate");
+ return;
+ }
+ shm_ptr[SHM2] = mmap(0, msize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd[SHM2], 0);
+ if(shm_ptr[SHM2] == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ /*if(fcntl(shm_fd[SHM2], F_ADD_SEALS, seals) == -1) {
+ perror("Fcntl");
+ return;
+ }*/
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(1, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ Send(shm_ptr[SHM1], shm_ptr[SHM2], msize, true);
+
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ Receive(shm_ptr[SHM1], shm_ptr[SHM2], msize, true);
+ printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+ waitpid(pid, NULL, 0);
+ ret = munmap(shm_ptr[SHM1], sizeof(unsigned long long));
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+ ret = shm_unlink(shm_name1);
+ if (ret != 0) {
+ perror("munmap");
+ //exit(1);
+ }
+
+ ret = munmap(shm_ptr[SHM2], msize);
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink(shm_name2);
+ if (ret != 0) {
+ perror("munmap");
+ //exit(1);
+ }
+
+ return;
+ }
+}
+
+ int
+main(int argc, char **argv)
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ nprocs = get_nprocs();
+ if(nprocs == 1)
+ nprocs = 2;
+
+ msize = 3;
+ lt_on = bw_on = false;
+ while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+ switch(opt) {
+ case 'm':
+ msize = atoi(optarg);
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ if(nprocs <= 0) {
+ printf("The number of process should be larger than 0\n");
+ exit(0);
+ }
+ if(nprocs % 2 != 0) {
+ printf("The number of process should be even\n");
+ exit(0);
+ }
+ break;
+ case 'b':
+ bw_on = true;
+ break;
+ case 'l':
+ lt_on = true;
+ break;
+ case 'h':
+ print_help(argv);
+ exit(0);
+ }
+ }
+
+ if(!lt_on && !bw_on) {
+ print_help(argv);
+ exit(0);
+ }
+
+ bw = 0;
+ lt_cnt = 0;
+ max = total = 0.0;
+ min = 1000000.0;
+
+ if(lt_on)
+ Measure_latency();
+
+ if(bw_on)
+ Measure_bandwidth();
+}
--- /dev/null
+/*
+ * lat_socket.c - socket IPC latency
+ *
+ */
+
+#include "common.h"
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+void Receive(int rfd1, int rfd2, register int size, bool is_lt)
+{
+ static int bw_cnt = 0;
+ unsigned long long start;
+ unsigned long long end;
+ register char *buf = (char *)malloc(size);
+
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ if(is_lt) {
+ if (read(rfd1, (void *)&start, sizeof(unsigned long long))
+ != sizeof(unsigned long long)) {
+ perror("(read 1) read/write on socket parent");
+ exit(1);
+ }
+ }
+
+ if (read(rfd2, buf, size) != size) {
+ perror("(read 2) read/write on socket parent");
+ exit(1);
+ }
+ else if(buf[0] == 'r'){
+ struct timespec clock;
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+ printf("latency: %0.4f\n", lt);
+#endif
+
+ if(lt > 0) {
+ lt_cnt++;
+ total += lt;
+ if(lt > max)
+ max = lt;
+
+ if(lt < min)
+ min = lt;
+ }
+ }
+ else {
+ bw_cnt++;
+ if(bw_cnt == 1) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ start = (unsigned long long)clock.tv_sec * NS
+ + (unsigned long long)clock.tv_nsec;
+ }
+
+ if(bw_cnt == REAL_TRY) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ end = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+ bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+ printf("bandwidth: %llu (/s)\n", bw);
+ }
+ }
+ }
+ }
+
+ free(buf);
+}
+
+void Send(int wfd1, int wfd2, register int size, bool is_lt)
+{
+ register char *cptr = (char *)malloc(size);
+
+ sleep(2);
+ for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+ int wres1, wres2;
+ struct timespec clock;
+
+ memset(cptr, 0, size);
+ if(i >= WARMUP_TRY)
+ cptr[0] = 'r';
+ else
+ cptr[0] = 'w';
+
+ if(is_lt) {
+ clock_gettime (CLOCK_REALTIME, &clock);
+ unsigned long long start = (unsigned long long)clock.tv_sec * NS
+ +(unsigned long long)clock.tv_nsec;
+
+ wres1 = write(wfd1, (void *)&start, sizeof(unsigned long long));
+ if (wres1 != sizeof(unsigned long long)) {
+ perror("(write 1) read/write on socket child");
+ exit(1);
+ }
+ }
+ wres2 = write(wfd2, cptr, size);
+ if (wres2 != size) {
+ perror("(write 2) read/write on socket child");
+ exit(1);
+ }
+
+ if(is_lt) {
+ if(size <= ONE_PAGE_SIZE)
+ usleep(5000);
+ else if(size <= 10 * ONE_PAGE_SIZE)
+ usleep(10000);
+ else if(size <= 100 * ONE_PAGE_SIZE)
+ usleep(20000);
+ else
+ usleep(40000);
+ }
+ }
+
+ free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+ int ret;
+ int returnp[nprocs/2][2];
+ int fd[nprocs/2][2];
+ int pids[nprocs];
+ int ready_fd;
+ char *ready_ptr;
+
+ ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if(ready_fd == -1)
+ {
+ perror("Open");
+ return;
+ }
+ if(ftruncate(ready_fd, sizeof(char))) {
+ perror("Ftruncate");
+ return;
+ }
+ ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+ MAP_SHARED, ready_fd, 0);
+ if(ready_ptr == MAP_FAILED) {
+ perror("Mmap");
+ return;
+ }
+ close(ready_fd);
+ ready_ptr[0] = "n";
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(returnp[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd[i]) == -1) {
+ perror("socketpair");
+ exit(1);
+ }
+ }
+
+ for(int i = 0; i < nprocs/2; i++) {
+ if(pipe(returnp[i]) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ for(int child = 1; child < nprocs; child++) {
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(child, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+
+ // Wait for parent
+ while(ready_ptr[0] == "n") {
+ }
+
+ if(child % 2 == 0) {
+ Receive(0, fd[child/2][1], msize, false);
+ close(fd[child/2][1]);
+
+ //send result(bandwidth) to parent
+ {
+ int wres;
+ close(returnp[child/2][0]);
+ wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+ if (wres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe sender");
+ exit(1);
+ }
+ close(returnp[child/2][1]);
+ }
+ }
+ else {
+ Send(0, fd[child/2][0], msize, false);
+ close(fd[child/2][0]);
+ }
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ pids[child] = pid;
+ break;
+ }
+ }
+
+ sleep(1);
+ ready_ptr[0] = "y";
+
+ Receive(0, fd[0][1], msize, false);
+ close(fd[0][1]);
+ for(int child = 1; child < nprocs; child++) {
+ //receive result(bandwidth) from child(s)
+ if(child % 2 == 0) {
+ int rres;
+ unsigned long long child_bw;
+
+ close(returnp[child/2][1]);
+ rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+ if (rres != sizeof(unsigned long long)) {
+ perror("(write return) read/write on pipe receiver");
+ exit(1);
+ }
+ close(returnp[child/2][0]);
+ bw += child_bw;
+ }
+
+ waitpid(pids[child], NULL, 0);
+ }
+ ret = munmap(ready_ptr, sizeof(bool));
+ if (ret != 0) {
+ perror("munmap");
+ exit(1);
+ }
+
+ ret = shm_unlink("isready");
+ if (ret != 0) {
+ perror("shm unlink");
+ //exit(1);
+ }
+ printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+ int fd1[2], fd2[2];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd1) == -1) {
+ perror("socketpair");
+ exit(1);
+ }
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd2) == -1) {
+ perror("socketpair");
+ exit(1);
+ }
+
+ if(!cpu_pin(0, getpid())) {
+ perror("CPU pinning for parent");
+ exit(1);
+ }
+
+ int pid = fork();
+ switch (pid) {
+ //child
+ case 0:
+ if(!cpu_pin(1, getpid())) {
+ perror("CPU pinning for child");
+ exit(1);
+ }
+ Send(fd1[0], fd2[0], msize, true);
+ close(fd1[0]);
+ close(fd2[0]);
+ exit(0);
+ case -1:
+ perror("fork");
+ return;
+ default:
+ Receive(fd1[1], fd2[1], msize, true);
+ close(fd1[1]);
+ close(fd2[1]);
+ printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+ waitpid(pid, NULL, 0);
+ return;
+ }
+}
+
+ int
+main(int argc, char **argv)
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ nprocs = get_nprocs();
+ if(nprocs == 1)
+ nprocs = 2;
+
+ msize = 3;
+ lt_on = bw_on = false;
+ while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+ switch(opt) {
+ case 'm':
+ msize = atoi(optarg);
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ if(nprocs <= 0) {
+ printf("The number of process should be larger than 0\n");
+ exit(0);
+ }
+ if(nprocs % 2 != 0) {
+ printf("The number of process should be even\n");
+ exit(0);
+ }
+ break;
+ case 'b':
+ bw_on = true;
+ break;
+ case 'l':
+ lt_on = true;
+ break;
+ case 'h':
+ print_help(argv);
+ exit(0);
+ }
+ }
+
+ if(!lt_on && !bw_on) {
+ print_help(argv);
+ exit(0);
+ }
+
+ bw = 0;
+ lt_cnt = 0;
+ max = total = 0.0;
+ min = 1000000.0;
+
+ if(lt_on)
+ Measure_latency();
+
+ if(bw_on)
+ Measure_bandwidth();
+}
--- /dev/null
+#!/bin/bash
+
+ARCH="armv7l"
+USER="owner"
+DIR="/home/unsunglee/tizen/output/local/repos/public/$ARCH/RPMS"
+PACKAGE=${PWD##*/}
+TYPE="benchmark"
+VERSION="0.1-1"
+RESULT="/tmp/test_result"
+
+###Build
+gbs build -A $ARCH --include
+
+###Install package
+sdb root on
+sdb push $DIR/$PACKAGE-$TYPE-$VERSION.$ARCH.rpm /tmp
+sdb shell mount -o remount,rw /
+sdb shell rpm -ivh /tmp/$PACKAGE-$TYPE-$VERSION.$ARCH.rpm --nodeps --force
+
+###Running benchmark
+sdb push test_target.sh /home/$USER/test.sh
+#sdb shell chown #USER:users /dev/shm
+echo "##########Running benchmarks"
+echo "##########It takes a little bit of time"
+sdb shell su - $USER /home/$USER/test.sh
+sdb shell rm /home/$USER/test.sh
+sdb pull $RESULT .
+sdb shell rm $RESULT
+
--- /dev/null
+#!/bin/bash
+
+USER="owner"
+RESULT="/tmp/test_result"
+
+#running benchmark and store results in the file
+echo "##########Pipe##########" >> $RESULT
+pipe -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Socket##########" >> $RESULT
+socket -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Shared memory##########" >> $RESULT
+sharedmem -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Gdbus##########" >> $RESULT
+gdbus -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Libdbus##########" >> $RESULT
+libdbus -b -l >> $RESULT
+echo "" >> $RESULT
Requires: libxslt-tools cynara
Source: %{name}-%{version}.tar.gz
Source101: dbus-tools.manifest
-BuildArch: noarch
+#BuildArch: noarch
BuildRequires: autoconf
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(dbus-1)
%description
This package provides a set of tools for working with D-Bus.
It includes:
dbuspolicy-checker: a light-weight checker for D-Bus policy files.
It checks syntax and semantics, looking for common errors.
+benchmark: benchmarks to measure latency and bandwidth of IPC(pipe, shared memory, socket, libdbus, and gdbus).
+
+
+%package benchmark
+Summary: IPC benchmark
+
+%description benchmark
+This package provides a set of benchmarks to measure latency and bandwidth of IPC
+(pipe, shared memory, socket, libdbus, and gdbus).
%prep
%setup -q
cp %{SOURCE101} .
%build
+make
pushd policychecker
autoconf
%configure
popd
+make
%install
%make_install
%license LICENSE.APACHE2.0 LICENSE.MIT
%{_bindir}/dbuspolicy-checker
%{_datadir}/dbus-tools/policychecker/*
+
+%files benchmark
+%{_bindir}/pipe
+%{_bindir}/socket
+%{_bindir}/sharedmem
+%{_bindir}/gdbus
+%{_bindir}/libdbus