summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClark Williams <williams@redhat.com>2009-12-21 10:27:18 -0600
committerClark Williams <williams@redhat.com>2009-12-21 10:27:18 -0600
commit1c3c9e34d65b6774e9f56d9d49fdbe101d42dc6c (patch)
treee97090d7bc7dceb1634e6b82b03aea5988af47b8
parentff74d0eb70973fb13811eeb17be8f596291a9d7c (diff)
downloadrt-tests-1c3c9e34d65b6774e9f56d9d49fdbe101d42dc6c.tar.gz
convert source back to unix text (was DOS text)
Somehow the last set of tests added got converted to DOS text (CRLF line terminators). Change them back Signed-off-by: Clark Williams <williams@redhat.com>
-rw-r--r--src/backfire/Makefile28
-rw-r--r--src/backfire/backfire.c300
-rw-r--r--src/backfire/sendme.c582
-rw-r--r--src/backfire/version.h2
-rw-r--r--src/ptsematest/Makefile32
-rw-r--r--src/ptsematest/ptsematest.c846
-rw-r--r--src/sigwaittest/Makefile34
-rw-r--r--src/sigwaittest/sigwaittest.c1236
-rw-r--r--src/svsematest/Makefile32
-rw-r--r--src/svsematest/svsematest.c1408
10 files changed, 2250 insertions, 2250 deletions
diff --git a/src/backfire/Makefile b/src/backfire/Makefile
index 33a0e02..b5d2b3e 100644
--- a/src/backfire/Makefile
+++ b/src/backfire/Makefile
@@ -1,14 +1,14 @@
-obj-m := backfire.o
-
-all: modules modules_install
- @echo Done
-
-modules:
- make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
-
-modules_install:
- make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules_install
-
-clean:
- make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
- @rm -f *.o Module.markers modules.order
+obj-m := backfire.o
+
+all: modules modules_install
+ @echo Done
+
+modules:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+
+modules_install:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules_install
+
+clean:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+ @rm -f *.o Module.markers modules.order
diff --git a/src/backfire/backfire.c b/src/backfire/backfire.c
index 699031a..d737347 100644
--- a/src/backfire/backfire.c
+++ b/src/backfire/backfire.c
@@ -1,150 +1,150 @@
-/*
- * backfire - send signal back to caller
- *
- * Copyright (C) 2007 Carsten Emde <C.Emde@osadl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/cpumask.h>
-#include <linux/time.h>
-#include <linux/smp_lock.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define BACKFIRE_MINOR MISC_DYNAMIC_MINOR
-
-static spinlock_t backfire_state_lock = SPIN_LOCK_UNLOCKED;
-static int backfire_open_cnt; /* #times opened */
-static int backfire_open_mode; /* special open modes */
-static struct timeval sendtime; /* when the most recent signal was sent */
-#define BACKFIRE_WRITE 1 /* opened for writing (exclusive) */
-#define BACKFIRE_EXCL 2 /* opened with O_EXCL */
-
-/*
- * These are the file operation function for user access to /dev/backfire
- */
-static ssize_t
-backfire_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
- return snprintf(buf, count, "%d,%d\n", (int) sendtime.tv_sec,
- (int) sendtime.tv_usec);
-}
-
-static ssize_t
-backfire_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- int signo;
- struct pid *pid;
-
- if (sscanf(buf, "%d", &signo) >= 1) {
- if (signo > 0 && signo < 32) {
- pid = get_pid(task_pid(current));
- do_gettimeofday(&sendtime);
- kill_pid(pid, signo, 1);
- } else
- printk(KERN_ERR "Invalid signal no. %d\n", signo);
- }
- return strlen(buf);
-}
-
-static int
-backfire_open(struct inode *inode, struct file *file)
-{
- spin_lock(&backfire_state_lock);
-
- if ((backfire_open_cnt && (file->f_flags & O_EXCL)) ||
- (backfire_open_mode & BACKFIRE_EXCL)) {
- spin_unlock(&backfire_state_lock);
- return -EBUSY;
- }
-
- if (file->f_flags & O_EXCL)
- backfire_open_mode |= BACKFIRE_EXCL;
- if (file->f_mode & 2)
- backfire_open_mode |= BACKFIRE_WRITE;
- backfire_open_cnt++;
-
- spin_unlock(&backfire_state_lock);
-
- return 0;
-}
-
-static int
-backfire_release(struct inode *inode, struct file *file)
-{
- spin_lock(&backfire_state_lock);
-
- backfire_open_cnt--;
-
- if (backfire_open_cnt == 1 && backfire_open_mode & BACKFIRE_EXCL)
- backfire_open_mode &= ~BACKFIRE_EXCL;
- if (file->f_mode & 2)
- backfire_open_mode &= ~BACKFIRE_WRITE;
-
- spin_unlock(&backfire_state_lock);
-
- return 0;
-}
-
-static struct file_operations backfire_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .open = backfire_open,
- .read = backfire_read,
- .write = backfire_write,
- .release = backfire_release,
-};
-
-static struct miscdevice backfire_dev = {
- BACKFIRE_MINOR,
- "backfire",
- &backfire_fops
-};
-
-static int __init backfire_init(void)
-{
- int ret;
-
- ret = misc_register(&backfire_dev);
- if (ret)
- printk(KERN_ERR "backfire: can't register dynamic misc device\n");
- else
- printk(KERN_INFO "backfire driver v__VERSION_STRING__ misc device %d\n",
- backfire_dev.minor);
- return ret;
-}
-
-static void __exit backfire_exit(void)
-{
- misc_deregister(&backfire_dev);
-}
-
-module_init(backfire_init);
-module_exit(backfire_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Carsten Emde <C.Emde@osadl.org>");
-MODULE_DESCRIPTION("Send signal back to caller");
+/*
+ * backfire - send signal back to caller
+ *
+ * Copyright (C) 2007 Carsten Emde <C.Emde@osadl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/module.h>
+
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/time.h>
+#include <linux/smp_lock.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define BACKFIRE_MINOR MISC_DYNAMIC_MINOR
+
+static spinlock_t backfire_state_lock = SPIN_LOCK_UNLOCKED;
+static int backfire_open_cnt; /* #times opened */
+static int backfire_open_mode; /* special open modes */
+static struct timeval sendtime; /* when the most recent signal was sent */
+#define BACKFIRE_WRITE 1 /* opened for writing (exclusive) */
+#define BACKFIRE_EXCL 2 /* opened with O_EXCL */
+
+/*
+ * These are the file operation function for user access to /dev/backfire
+ */
+static ssize_t
+backfire_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ return snprintf(buf, count, "%d,%d\n", (int) sendtime.tv_sec,
+ (int) sendtime.tv_usec);
+}
+
+static ssize_t
+backfire_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ int signo;
+ struct pid *pid;
+
+ if (sscanf(buf, "%d", &signo) >= 1) {
+ if (signo > 0 && signo < 32) {
+ pid = get_pid(task_pid(current));
+ do_gettimeofday(&sendtime);
+ kill_pid(pid, signo, 1);
+ } else
+ printk(KERN_ERR "Invalid signal no. %d\n", signo);
+ }
+ return strlen(buf);
+}
+
+static int
+backfire_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&backfire_state_lock);
+
+ if ((backfire_open_cnt && (file->f_flags & O_EXCL)) ||
+ (backfire_open_mode & BACKFIRE_EXCL)) {
+ spin_unlock(&backfire_state_lock);
+ return -EBUSY;
+ }
+
+ if (file->f_flags & O_EXCL)
+ backfire_open_mode |= BACKFIRE_EXCL;
+ if (file->f_mode & 2)
+ backfire_open_mode |= BACKFIRE_WRITE;
+ backfire_open_cnt++;
+
+ spin_unlock(&backfire_state_lock);
+
+ return 0;
+}
+
+static int
+backfire_release(struct inode *inode, struct file *file)
+{
+ spin_lock(&backfire_state_lock);
+
+ backfire_open_cnt--;
+
+ if (backfire_open_cnt == 1 && backfire_open_mode & BACKFIRE_EXCL)
+ backfire_open_mode &= ~BACKFIRE_EXCL;
+ if (file->f_mode & 2)
+ backfire_open_mode &= ~BACKFIRE_WRITE;
+
+ spin_unlock(&backfire_state_lock);
+
+ return 0;
+}
+
+static struct file_operations backfire_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = backfire_open,
+ .read = backfire_read,
+ .write = backfire_write,
+ .release = backfire_release,
+};
+
+static struct miscdevice backfire_dev = {
+ BACKFIRE_MINOR,
+ "backfire",
+ &backfire_fops
+};
+
+static int __init backfire_init(void)
+{
+ int ret;
+
+ ret = misc_register(&backfire_dev);
+ if (ret)
+ printk(KERN_ERR "backfire: can't register dynamic misc device\n");
+ else
+ printk(KERN_INFO "backfire driver v__VERSION_STRING__ misc device %d\n",
+ backfire_dev.minor);
+ return ret;
+}
+
+static void __exit backfire_exit(void)
+{
+ misc_deregister(&backfire_dev);
+}
+
+module_init(backfire_init);
+module_exit(backfire_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Carsten Emde <C.Emde@osadl.org>");
+MODULE_DESCRIPTION("Send signal back to caller");
diff --git a/src/backfire/sendme.c b/src/backfire/sendme.c
index 190dbf5..3736ddb 100644
--- a/src/backfire/sendme.c
+++ b/src/backfire/sendme.c
@@ -1,291 +1,291 @@
-/*
- * sendme.c
- *
- * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#define __USE_GNU
-#include <fcntl.h>
-#include <getopt.h>
-#include <signal.h>
-#include <sched.h>
-#include <string.h>
-#include <time.h>
-#include "rt-utils.h"
-
-#define _GNU_SOURCE
-#include <utmpx.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-
-#define USEC_PER_SEC 1000000
-#define NSEC_PER_SEC 1000000000
-
-#define SIGTEST SIGHUP
-
-enum {
- AFFINITY_UNSPECIFIED,
- AFFINITY_SPECIFIED,
- AFFINITY_USECURRENT
-};
-static int setaffinity = AFFINITY_UNSPECIFIED;
-
-static int affinity;
-static int tracelimit;
-static int priority;
-static int shutdown;
-static int max_cycles;
-static volatile struct timeval after;
-static int interval = 1000;
-
-static int kernvar(int mode, const char *name, char *value, size_t sizeofvalue)
-{
- char filename[128];
- char *fileprefix = get_debugfileprefix();
- int retval = 1;
- int path;
-
- strncpy(filename, fileprefix, sizeof(filename));
- strncat(filename, name, sizeof(filename) - strlen(fileprefix));
- path = open(filename, mode);
- if (path >= 0) {
- if (mode == O_RDONLY) {
- int got;
- if ((got = read(path, value, sizeofvalue)) > 0) {
- retval = 0;
- value[got-1] = '\0';
- }
- } else if (mode == O_WRONLY) {
- if (write(path, value, sizeofvalue) == sizeofvalue)
- retval = 0;
- }
- close(path);
- }
- return retval;
-}
-
-void signalhandler(int signo)
-{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- after = tv;
- if (signo == SIGINT || signo == SIGTERM)
- shutdown = 1;
-}
-
-void stop_tracing(void)
-{
- kernvar(O_WRONLY, "tracing_enabled", "0", 1);
-}
-
-static void display_help(void)
-{
- printf("sendme V %1.2f\n", VERSION_STRING);
- puts("Usage: sendme <options>");
- puts("Function: send a signal from driver to userspace");
- puts(
- "Options:\n"
- "-a [NUM] --affinity pin to current processor\n"
- " with NUM pin to processor NUM\n"
- "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
- "-i INTV --interval=INTV base interval of thread in us default=1000\n"
- "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
- "-p PRIO --prio=PRIO priority\n");
- exit(1);
-}
-
-static void process_options (int argc, char *argv[])
-{
- int error = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- for (;;) {
- int option_index = 0;
- /** Options for getopt */
- static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"help", no_argument, NULL, '?'},
- {NULL, 0, NULL, 0}
- };
- int c = getopt_long (argc, argv, "a::b:i:l:p:",
- long_options, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'a':
- if (optarg != NULL) {
- affinity = atoi(optarg);
- setaffinity = AFFINITY_SPECIFIED;
- } else if (optind < argc && atoi(argv[optind])) {
- affinity = atoi(argv[optind]);
- setaffinity = AFFINITY_SPECIFIED;
- } else
- setaffinity = AFFINITY_USECURRENT;
- break;
- case 'b': tracelimit = atoi(optarg); break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case '?': error = 1; break;
- }
- }
-
- if (setaffinity == AFFINITY_SPECIFIED) {
- if (affinity < 0)
- error = 1;
- if (affinity >= max_cpus) {
- fprintf(stderr, "ERROR: CPU #%d not found, only %d CPUs available\n",
- affinity, max_cpus);
- error = 1;
- }
- }
-
- if (priority < 0 || priority > 99)
- error = 1;
-
- if (error)
- display_help ();
-}
-
-int main(int argc, char *argv[])
-{
- int path;
- cpu_set_t mask;
- int policy = SCHED_FIFO;
- struct sched_param schedp;
- struct flock fl;
- int retval = 0;
-
- process_options(argc, argv);
-
- if (check_privs())
- return 1;
-
- if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
- perror("mlockall");
- return 1;
- }
-
- memset(&schedp, 0, sizeof(schedp));
- schedp.sched_priority = priority;
- sched_setscheduler(0, policy, &schedp);
-
- if (setaffinity != AFFINITY_UNSPECIFIED) {
- CPU_ZERO(&mask);
- if (setaffinity == AFFINITY_USECURRENT)
- affinity = sched_getcpu();
- CPU_SET(affinity, &mask);
- if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
- fprintf(stderr, "WARNING: Could not set CPU affinity "
- "to CPU #%d\n", affinity);
- }
-
- path = open("/dev/backfire", O_RDWR);
- if (path < 0) {
- fprintf(stderr, "ERROR: Could not access backfire device, "
- "try 'modprobe backfire'\n");
- return 1;
- }
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 1;
- if (fcntl(path, F_SETLK, &fl) == -1) {
- fprintf(stderr, "ERRROR: backfire device locked\n");
- retval = 1;
- } else {
- char sigtest[8];
- char timestamp[32];
- struct timeval before, sendtime, diff;
- unsigned int diffno = 0;
- unsigned int mindiff1 = UINT_MAX, maxdiff1 = 0;
- unsigned int mindiff2 = UINT_MAX, maxdiff2 = 0;
- double sumdiff1 = 0.0, sumdiff2 = 0.0;
-
- if (tracelimit)
- kernvar(O_WRONLY, "tracing_enabled", "1", 1);
-
- sprintf(sigtest, "%d", SIGTEST);
- signal(SIGTEST, signalhandler);
- signal(SIGINT, signalhandler);
- signal(SIGTERM, signalhandler);
-
- while (1) {
- struct timespec ts;
-
- ts.tv_sec = interval / USEC_PER_SEC;
- ts.tv_nsec = (interval % USEC_PER_SEC) * 1000;
-
- gettimeofday(&before, NULL);
- write(path, sigtest, strlen(sigtest));
- while (after.tv_sec == 0);
- read(path, timestamp, sizeof(timestamp));
- if (sscanf(timestamp, "%lu,%lu\n", &sendtime.tv_sec,
- &sendtime.tv_usec) != 2)
- break;
- diffno++;
- if(max_cycles && diffno >= max_cycles)
- shutdown = 1;
-
- printf("Samples: %8d\n", diffno);
- timersub(&sendtime, &before, &diff);
- if (diff.tv_usec < mindiff1)
- mindiff1 = diff.tv_usec;
- if (diff.tv_usec > maxdiff1)
- maxdiff1 = diff.tv_usec;
- sumdiff1 += (double) diff.tv_usec;
- printf("To: Min %4d, Cur %4d, Avg %4d, Max %4d\n",
- mindiff1, (int) diff.tv_usec,
- (int) ((sumdiff1 / diffno) + 0.5),
- maxdiff1);
-
- timersub(&after, &sendtime, &diff);
- if (diff.tv_usec < mindiff2)
- mindiff2 = diff.tv_usec;
- if (diff.tv_usec > maxdiff2)
- maxdiff2 = diff.tv_usec;
- sumdiff2 += (double) diff.tv_usec;
- printf("From: Min %4d, Cur %4d, Avg %4d, Max %4d\n",
- mindiff2, (int) diff.tv_usec,
- (int) ((sumdiff2 / diffno) + 0.5),
- maxdiff2);
- after.tv_sec = 0;
- if ((tracelimit && diff.tv_usec > tracelimit) ||
- shutdown) {
- if (tracelimit)
- stop_tracing();
- break;
- }
- nanosleep(&ts, NULL);
- printf("\033[3A");
- }
- }
-
- close(path);
- return retval;
-}
+/*
+ * sendme.c
+ *
+ * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#define __USE_GNU
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <sched.h>
+#include <string.h>
+#include <time.h>
+#include "rt-utils.h"
+
+#define _GNU_SOURCE
+#include <utmpx.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#define USEC_PER_SEC 1000000
+#define NSEC_PER_SEC 1000000000
+
+#define SIGTEST SIGHUP
+
+enum {
+ AFFINITY_UNSPECIFIED,
+ AFFINITY_SPECIFIED,
+ AFFINITY_USECURRENT
+};
+static int setaffinity = AFFINITY_UNSPECIFIED;
+
+static int affinity;
+static int tracelimit;
+static int priority;
+static int shutdown;
+static int max_cycles;
+static volatile struct timeval after;
+static int interval = 1000;
+
+static int kernvar(int mode, const char *name, char *value, size_t sizeofvalue)
+{
+ char filename[128];
+ char *fileprefix = get_debugfileprefix();
+ int retval = 1;
+ int path;
+
+ strncpy(filename, fileprefix, sizeof(filename));
+ strncat(filename, name, sizeof(filename) - strlen(fileprefix));
+ path = open(filename, mode);
+ if (path >= 0) {
+ if (mode == O_RDONLY) {
+ int got;
+ if ((got = read(path, value, sizeofvalue)) > 0) {
+ retval = 0;
+ value[got-1] = '\0';
+ }
+ } else if (mode == O_WRONLY) {
+ if (write(path, value, sizeofvalue) == sizeofvalue)
+ retval = 0;
+ }
+ close(path);
+ }
+ return retval;
+}
+
+void signalhandler(int signo)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ after = tv;
+ if (signo == SIGINT || signo == SIGTERM)
+ shutdown = 1;
+}
+
+void stop_tracing(void)
+{
+ kernvar(O_WRONLY, "tracing_enabled", "0", 1);
+}
+
+static void display_help(void)
+{
+ printf("sendme V %1.2f\n", VERSION_STRING);
+ puts("Usage: sendme <options>");
+ puts("Function: send a signal from driver to userspace");
+ puts(
+ "Options:\n"
+ "-a [NUM] --affinity pin to current processor\n"
+ " with NUM pin to processor NUM\n"
+ "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
+ "-i INTV --interval=INTV base interval of thread in us default=1000\n"
+ "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ "-p PRIO --prio=PRIO priority\n");
+ exit(1);
+}
+
+static void process_options (int argc, char *argv[])
+{
+ int error = 0;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (;;) {
+ int option_index = 0;
+ /** Options for getopt */
+ static struct option long_options[] = {
+ {"affinity", optional_argument, NULL, 'a'},
+ {"breaktrace", required_argument, NULL, 'b'},
+ {"interval", required_argument, NULL, 'i'},
+ {"loops", required_argument, NULL, 'l'},
+ {"priority", required_argument, NULL, 'p'},
+ {"help", no_argument, NULL, '?'},
+ {NULL, 0, NULL, 0}
+ };
+ int c = getopt_long (argc, argv, "a::b:i:l:p:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'a':
+ if (optarg != NULL) {
+ affinity = atoi(optarg);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else if (optind < argc && atoi(argv[optind])) {
+ affinity = atoi(argv[optind]);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else
+ setaffinity = AFFINITY_USECURRENT;
+ break;
+ case 'b': tracelimit = atoi(optarg); break;
+ case 'i': interval = atoi(optarg); break;
+ case 'l': max_cycles = atoi(optarg); break;
+ case 'p': priority = atoi(optarg); break;
+ case '?': error = 1; break;
+ }
+ }
+
+ if (setaffinity == AFFINITY_SPECIFIED) {
+ if (affinity < 0)
+ error = 1;
+ if (affinity >= max_cpus) {
+ fprintf(stderr, "ERROR: CPU #%d not found, only %d CPUs available\n",
+ affinity, max_cpus);
+ error = 1;
+ }
+ }
+
+ if (priority < 0 || priority > 99)
+ error = 1;
+
+ if (error)
+ display_help ();
+}
+
+int main(int argc, char *argv[])
+{
+ int path;
+ cpu_set_t mask;
+ int policy = SCHED_FIFO;
+ struct sched_param schedp;
+ struct flock fl;
+ int retval = 0;
+
+ process_options(argc, argv);
+
+ if (check_privs())
+ return 1;
+
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
+ perror("mlockall");
+ return 1;
+ }
+
+ memset(&schedp, 0, sizeof(schedp));
+ schedp.sched_priority = priority;
+ sched_setscheduler(0, policy, &schedp);
+
+ if (setaffinity != AFFINITY_UNSPECIFIED) {
+ CPU_ZERO(&mask);
+ if (setaffinity == AFFINITY_USECURRENT)
+ affinity = sched_getcpu();
+ CPU_SET(affinity, &mask);
+ if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
+ fprintf(stderr, "WARNING: Could not set CPU affinity "
+ "to CPU #%d\n", affinity);
+ }
+
+ path = open("/dev/backfire", O_RDWR);
+ if (path < 0) {
+ fprintf(stderr, "ERROR: Could not access backfire device, "
+ "try 'modprobe backfire'\n");
+ return 1;
+ }
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 1;
+ if (fcntl(path, F_SETLK, &fl) == -1) {
+ fprintf(stderr, "ERRROR: backfire device locked\n");
+ retval = 1;
+ } else {
+ char sigtest[8];
+ char timestamp[32];
+ struct timeval before, sendtime, diff;
+ unsigned int diffno = 0;
+ unsigned int mindiff1 = UINT_MAX, maxdiff1 = 0;
+ unsigned int mindiff2 = UINT_MAX, maxdiff2 = 0;
+ double sumdiff1 = 0.0, sumdiff2 = 0.0;
+
+ if (tracelimit)
+ kernvar(O_WRONLY, "tracing_enabled", "1", 1);
+
+ sprintf(sigtest, "%d", SIGTEST);
+ signal(SIGTEST, signalhandler);
+ signal(SIGINT, signalhandler);
+ signal(SIGTERM, signalhandler);
+
+ while (1) {
+ struct timespec ts;
+
+ ts.tv_sec = interval / USEC_PER_SEC;
+ ts.tv_nsec = (interval % USEC_PER_SEC) * 1000;
+
+ gettimeofday(&before, NULL);
+ write(path, sigtest, strlen(sigtest));
+ while (after.tv_sec == 0);
+ read(path, timestamp, sizeof(timestamp));
+ if (sscanf(timestamp, "%lu,%lu\n", &sendtime.tv_sec,
+ &sendtime.tv_usec) != 2)
+ break;
+ diffno++;
+ if(max_cycles && diffno >= max_cycles)
+ shutdown = 1;
+
+ printf("Samples: %8d\n", diffno);
+ timersub(&sendtime, &before, &diff);
+ if (diff.tv_usec < mindiff1)
+ mindiff1 = diff.tv_usec;
+ if (diff.tv_usec > maxdiff1)
+ maxdiff1 = diff.tv_usec;
+ sumdiff1 += (double) diff.tv_usec;
+ printf("To: Min %4d, Cur %4d, Avg %4d, Max %4d\n",
+ mindiff1, (int) diff.tv_usec,
+ (int) ((sumdiff1 / diffno) + 0.5),
+ maxdiff1);
+
+ timersub(&after, &sendtime, &diff);
+ if (diff.tv_usec < mindiff2)
+ mindiff2 = diff.tv_usec;
+ if (diff.tv_usec > maxdiff2)
+ maxdiff2 = diff.tv_usec;
+ sumdiff2 += (double) diff.tv_usec;
+ printf("From: Min %4d, Cur %4d, Avg %4d, Max %4d\n",
+ mindiff2, (int) diff.tv_usec,
+ (int) ((sumdiff2 / diffno) + 0.5),
+ maxdiff2);
+ after.tv_sec = 0;
+ if ((tracelimit && diff.tv_usec > tracelimit) ||
+ shutdown) {
+ if (tracelimit)
+ stop_tracing();
+ break;
+ }
+ nanosleep(&ts, NULL);
+ printf("\033[3A");
+ }
+ }
+
+ close(path);
+ return retval;
+}
diff --git a/src/backfire/version.h b/src/backfire/version.h
index cbe3858..669b388 100644
--- a/src/backfire/version.h
+++ b/src/backfire/version.h
@@ -1 +1 @@
-#define VERSION "0.5"
+#define VERSION "0.5"
diff --git a/src/ptsematest/Makefile b/src/ptsematest/Makefile
index c0bfa7c..dc12bc2 100644
--- a/src/ptsematest/Makefile
+++ b/src/ptsematest/Makefile
@@ -1,16 +1,16 @@
-CFLAGS += -Wall -O2
-LDFLAGS += -lpthread
-
-all: ptsematest
- @echo Done
-
-ptsematest.o: ptsematest.c
-
-ptsematest:
-
-clean:
- @rm -f *.o
-
-tar: clean
- @rm -f ptsematest
- $(shell bn=`basename $$PWD`; cd ..; tar -zcf $$bn.tgz $$bn)
+CFLAGS += -Wall -O2
+LDFLAGS += -lpthread
+
+all: ptsematest
+ @echo Done
+
+ptsematest.o: ptsematest.c
+
+ptsematest:
+
+clean:
+ @rm -f *.o
+
+tar: clean
+ @rm -f ptsematest
+ $(shell bn=`basename $$PWD`; cd ..; tar -zcf $$bn.tgz $$bn)
diff --git a/src/ptsematest/ptsematest.c b/src/ptsematest/ptsematest.c
index c4426f3..aaae92a 100644
--- a/src/ptsematest/ptsematest.c
+++ b/src/ptsematest/ptsematest.c
@@ -1,423 +1,423 @@
-/*
- * ptsematest.c
- *
- * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <linux/unistd.h>
-#include <utmpx.h>
-#include "rt-utils.h"
-
-#define __USE_GNU
-#include <pthread.h>
-
-#define gettid() syscall(__NR_gettid)
-
-#define USEC_PER_SEC 1000000
-
-enum {
- AFFINITY_UNSPECIFIED,
- AFFINITY_SPECIFIED,
- AFFINITY_USEALL
-};
-
-static pthread_mutex_t *testmutex;
-static pthread_mutex_t *syncmutex;
-
-struct params {
- int num;
- int cpu;
- int priority;
- int affinity;
- int sender;
- int samples;
- int max_cycles;
- int tracelimit;
- int tid;
- int shutdown;
- int stopped;
- struct timespec delay;
- unsigned int mindiff, maxdiff;
- double sumdiff;
- struct timeval unblocked, received, diff;
- pthread_t threadid;
- struct params *neighbor;
- char error[MAX_PATH * 2];
-};
-
-void *semathread(void *param)
-{
- int mustgetcpu = 0;
- int first = 1;
- struct params *par = param;
- cpu_set_t mask;
- int policy = SCHED_FIFO;
- struct sched_param schedp;
-
- memset(&schedp, 0, sizeof(schedp));
- schedp.sched_priority = par->priority;
- sched_setscheduler(0, policy, &schedp);
-
- if (par->cpu != -1) {
- CPU_ZERO(&mask);
- CPU_SET(par->cpu, &mask);
- if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
- fprintf(stderr, "WARNING: Could not set CPU affinity "
- "to CPU #%d\n", par->cpu);
- } else
- mustgetcpu = 1;
-
- par->tid = gettid();
-
- while (!par->shutdown) {
- if (par->sender) {
- pthread_mutex_lock(&syncmutex[par->num]);
-
- /* Release lock: Start of latency measurement ... */
- gettimeofday(&par->unblocked, NULL);
- pthread_mutex_unlock(&testmutex[par->num]);
- par->samples++;
- if(par->max_cycles && par->samples >= par->max_cycles)
- par->shutdown = 1;
- if (mustgetcpu) {
- par->cpu = sched_getcpu();
- }
- } else {
- /* Receiver */
- if (!first) {
- pthread_mutex_lock(&syncmutex[par->num]);
- first = 1;
- }
- pthread_mutex_lock(&testmutex[par->num]);
-
- /* ... Got the lock: End of latency measurement */
- gettimeofday(&par->received, NULL);
- par->samples++;
- timersub(&par->received, &par->neighbor->unblocked,
- &par->diff);
-
- if (par->diff.tv_usec < par->mindiff)
- par->mindiff = par->diff.tv_usec;
- if (par->diff.tv_usec > par->maxdiff)
- par->maxdiff = par->diff.tv_usec;
- par->sumdiff += (double) par->diff.tv_usec;
- if (par->tracelimit && par->maxdiff > par->tracelimit) {
- char tracing_enabled_file[MAX_PATH];
-
- strcpy(tracing_enabled_file, get_debugfileprefix());
- strcat(tracing_enabled_file, "tracing_enabled");
- int tracing_enabled =
- open(tracing_enabled_file, O_WRONLY);
- if (tracing_enabled >= 0) {
- write(tracing_enabled, "0", 1);
- close(tracing_enabled);
- } else
- snprintf(par->error, sizeof(par->error),
- "Could not access %s\n",
- tracing_enabled_file);
- par->shutdown = 1;
- par->neighbor->shutdown = 1;
- }
-
- if (par->max_cycles && par->samples >= par->max_cycles)
- par->shutdown = 1;
- if (mustgetcpu) {
- par->cpu = sched_getcpu();
- }
- nanosleep(&par->delay, NULL);
- pthread_mutex_unlock(&syncmutex[par->num]);
- }
- }
- par->stopped = 1;
- return NULL;
-}
-
-
-static void display_help(void)
-{
- printf("ptsematest V %1.2f\n", VERSION_STRING);
- puts("Usage: ptsematest <options>");
- puts("Function: test POSIX threads mutex latency");
- puts(
- "Options:\n"
- "-a [NUM] --affinity run thread #N on processor #N, if possible\n"
- " with NUM pin all threads to the processor NUM\n"
- "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
- "-d DIST --distance=DIST distance of thread intervals in us default=500\n"
- "-i INTV --interval=INTV base interval of thread in us default=1000\n"
- "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
- "-p PRIO --prio=PRIO priority\n"
- "-t --threads one thread per available processor\n"
- "-t [NUM] --threads=NUM number of threads:\n"
- " without NUM, threads = max_cpus\n"
- " without -t default = 1\n");
- exit(1);
-}
-
-
-static int setaffinity = AFFINITY_UNSPECIFIED;
-static int affinity;
-static int tracelimit;
-static int priority;
-static int num_threads = 1;
-static int max_cycles;
-static int interval = 1000;
-static int distance = 500;
-
-static void process_options (int argc, char *argv[])
-{
- int error = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- for (;;) {
- int option_index = 0;
- /** Options for getopt */
- static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"threads", optional_argument, NULL, 't'},
- {"help", no_argument, NULL, '?'},
- {NULL, 0, NULL, 0}
- };
- int c = getopt_long (argc, argv, "a::b:d:i:l:p:t::",
- long_options, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'a':
- if (optarg != NULL) {
- affinity = atoi(optarg);
- setaffinity = AFFINITY_SPECIFIED;
- } else if (optind<argc && atoi(argv[optind])) {
- affinity = atoi(argv[optind]);
- setaffinity = AFFINITY_SPECIFIED;
- } else {
- setaffinity = AFFINITY_USEALL;
- }
- break;
- case 'b': tracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 't':
- if (optarg != NULL)
- num_threads = atoi(optarg);
- else if (optind<argc && atoi(argv[optind]))
- num_threads = atoi(argv[optind]);
- else
- num_threads = max_cpus;
- break;
- case '?': error = 1; break;
- }
- }
-
- if (setaffinity == AFFINITY_SPECIFIED) {
- if (affinity < 0)
- error = 1;
- if (affinity >= max_cpus) {
- fprintf(stderr, "ERROR: CPU #%d not found, only %d CPUs available\n",
- affinity, max_cpus);
- error = 1;
- }
- }
-
- if (num_threads < 0 || num_threads > 255)
- error = 1;
-
- if (priority < 0 || priority > 99)
- error = 1;
-
- if (num_threads < 1)
- error = 1;
-
- if (error)
- display_help ();
-}
-
-
-static int volatile shutdown;
-
-static void sighand(int sig)
-{
- shutdown = 1;
-}
-
-int main(int argc, char *argv[])
-{
- int i;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
- int oldsamples = 1;
- struct params *receiver = NULL;
- struct params *sender = NULL;
- sigset_t sigset;
- struct timespec maindelay;
-
- process_options(argc, argv);
-
- if (check_privs())
- return 1;
-
- if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
- perror("mlockall");
- return 1;
- }
-
- signal(SIGINT, sighand);
- signal(SIGTERM, sighand);
-
- receiver = calloc(num_threads, sizeof(struct params));
- sender = calloc(num_threads, sizeof(struct params));
- if (receiver == NULL || sender == NULL)
- goto nomem;
-
- testmutex = (pthread_mutex_t *) calloc(num_threads, sizeof(pthread_mutex_t));
- syncmutex = (pthread_mutex_t *) calloc(num_threads, sizeof(pthread_mutex_t));
- if (testmutex == NULL || syncmutex == NULL)
- goto nomem;
-
- for (i = 0; i < num_threads; i++) {
- receiver[i].mindiff = UINT_MAX;
- receiver[i].maxdiff = 0;
- receiver[i].sumdiff = 0.0;
-
-
- pthread_mutex_init(&testmutex[i], NULL);
- pthread_mutex_init(&syncmutex[i], NULL);
-
- /* Wait on first attempt */
- pthread_mutex_lock(&testmutex[i]);
-
- receiver[i].num = i;
- receiver[i].cpu = i;
- switch (setaffinity) {
- case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
- case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
- case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
- }
- receiver[i].priority = priority;
- receiver[i].tracelimit = tracelimit;
- if (priority > 0)
- priority--;
- receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
- receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
- interval += distance;
- receiver[i].max_cycles = max_cycles;
- receiver[i].sender = 0;
- receiver[i].neighbor = &sender[i];
- pthread_create(&receiver[i].threadid, NULL, semathread, &receiver[i]);
- memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
- sender[i].sender = 1;
- sender[i].neighbor = &receiver[i];
- pthread_create(&sender[i].threadid, NULL, semathread, &sender[i]);
- }
-
- maindelay.tv_sec = 0;
- maindelay.tv_nsec = 50000000; /* 50 ms */
-
- while (!shutdown) {
- int printed;
- int errorlines = 0;
-
- for (i = 0; i < num_threads; i++)
- shutdown |= receiver[i].shutdown | sender[i].shutdown;
-
- if (receiver[0].samples > oldsamples || shutdown) {
- for (i = 0; i < num_threads; i++) {
- printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: ID%d, P%d, CPU%d, Cycles %d\n",
- i*2, receiver[i].tid, receiver[i].priority, receiver[i].cpu,
- receiver[i].delay.tv_nsec / 1000,
- i*2+1, sender[i].tid, sender[i].priority, sender[i].cpu,
- sender[i].samples);
- }
- for (i = 0; i < num_threads; i++) {
- printf("#%d -> #%d, Min %4d, Cur %4d, Avg %4d, Max %4d\n",
- i*2+1, i*2,
- receiver[i].mindiff, (int) receiver[i].diff.tv_usec,
- (int) ((receiver[i].sumdiff / receiver[i].samples) + 0.5),
- receiver[i].maxdiff);
- if (receiver[i].error[0] != '\0') {
- printf(receiver[i].error);
- errorlines++;
- receiver[i].error[0] = '\0';
- }
- if (sender[i].error[0] != '\0') {
- printf(sender[i].error);
- errorlines++;
- receiver[i].error[0] = '\0';
- }
- }
- printed = 1;
- } else
- printed = 0;
-
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGTERM);
- sigaddset(&sigset, SIGINT);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- nanosleep(&maindelay, NULL);
-
- sigemptyset(&sigset);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- if (printed && !shutdown)
- printf("\033[%dA", num_threads*2 + errorlines);
- }
-
- for (i = 0; i < num_threads; i++) {
- receiver[i].shutdown = 1;
- sender[i].shutdown = 1;
- pthread_mutex_unlock(&testmutex[i]);
- pthread_mutex_unlock(&syncmutex[i]);
- }
- nanosleep(&receiver[0].delay, NULL);
-
- for (i = 0; i < num_threads; i++) {
- if (!receiver[i].stopped)
- pthread_kill(receiver[i].threadid, SIGTERM);
- if (!sender[i].stopped)
- pthread_kill(sender[i].threadid, SIGTERM);
- }
-
- for (i = 0; i < num_threads; i++) {
- pthread_mutex_destroy(&testmutex[i]);
- pthread_mutex_destroy(&syncmutex[i]);
- }
-
- nomem:
-
- return 0;
-}
+/*
+ * ptsematest.c
+ *
+ * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <linux/unistd.h>
+#include <utmpx.h>
+#include "rt-utils.h"
+
+#define __USE_GNU
+#include <pthread.h>
+
+#define gettid() syscall(__NR_gettid)
+
+#define USEC_PER_SEC 1000000
+
+enum {
+ AFFINITY_UNSPECIFIED,
+ AFFINITY_SPECIFIED,
+ AFFINITY_USEALL
+};
+
+static pthread_mutex_t *testmutex;
+static pthread_mutex_t *syncmutex;
+
+struct params {
+ int num;
+ int cpu;
+ int priority;
+ int affinity;
+ int sender;
+ int samples;
+ int max_cycles;
+ int tracelimit;
+ int tid;
+ int shutdown;
+ int stopped;
+ struct timespec delay;
+ unsigned int mindiff, maxdiff;
+ double sumdiff;
+ struct timeval unblocked, received, diff;
+ pthread_t threadid;
+ struct params *neighbor;
+ char error[MAX_PATH * 2];
+};
+
+void *semathread(void *param)
+{
+ int mustgetcpu = 0;
+ int first = 1;
+ struct params *par = param;
+ cpu_set_t mask;
+ int policy = SCHED_FIFO;
+ struct sched_param schedp;
+
+ memset(&schedp, 0, sizeof(schedp));
+ schedp.sched_priority = par->priority;
+ sched_setscheduler(0, policy, &schedp);
+
+ if (par->cpu != -1) {
+ CPU_ZERO(&mask);
+ CPU_SET(par->cpu, &mask);
+ if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
+ fprintf(stderr, "WARNING: Could not set CPU affinity "
+ "to CPU #%d\n", par->cpu);
+ } else
+ mustgetcpu = 1;
+
+ par->tid = gettid();
+
+ while (!par->shutdown) {
+ if (par->sender) {
+ pthread_mutex_lock(&syncmutex[par->num]);
+
+ /* Release lock: Start of latency measurement ... */
+ gettimeofday(&par->unblocked, NULL);
+ pthread_mutex_unlock(&testmutex[par->num]);
+ par->samples++;
+ if(par->max_cycles && par->samples >= par->max_cycles)
+ par->shutdown = 1;
+ if (mustgetcpu) {
+ par->cpu = sched_getcpu();
+ }
+ } else {
+ /* Receiver */
+ if (!first) {
+ pthread_mutex_lock(&syncmutex[par->num]);
+ first = 1;
+ }
+ pthread_mutex_lock(&testmutex[par->num]);
+
+ /* ... Got the lock: End of latency measurement */
+ gettimeofday(&par->received, NULL);
+ par->samples++;
+ timersub(&par->received, &par->neighbor->unblocked,
+ &par->diff);
+
+ if (par->diff.tv_usec < par->mindiff)
+ par->mindiff = par->diff.tv_usec;
+ if (par->diff.tv_usec > par->maxdiff)
+ par->maxdiff = par->diff.tv_usec;
+ par->sumdiff += (double) par->diff.tv_usec;
+ if (par->tracelimit && par->maxdiff > par->tracelimit) {
+ char tracing_enabled_file[MAX_PATH];
+
+ strcpy(tracing_enabled_file, get_debugfileprefix());
+ strcat(tracing_enabled_file, "tracing_enabled");
+ int tracing_enabled =
+ open(tracing_enabled_file, O_WRONLY);
+ if (tracing_enabled >= 0) {
+ write(tracing_enabled, "0", 1);
+ close(tracing_enabled);
+ } else
+ snprintf(par->error, sizeof(par->error),
+ "Could not access %s\n",
+ tracing_enabled_file);
+ par->shutdown = 1;
+ par->neighbor->shutdown = 1;
+ }
+
+ if (par->max_cycles && par->samples >= par->max_cycles)
+ par->shutdown = 1;
+ if (mustgetcpu) {
+ par->cpu = sched_getcpu();
+ }
+ nanosleep(&par->delay, NULL);
+ pthread_mutex_unlock(&syncmutex[par->num]);
+ }
+ }
+ par->stopped = 1;
+ return NULL;
+}
+
+
+static void display_help(void)
+{
+ printf("ptsematest V %1.2f\n", VERSION_STRING);
+ puts("Usage: ptsematest <options>");
+ puts("Function: test POSIX threads mutex latency");
+ puts(
+ "Options:\n"
+ "-a [NUM] --affinity run thread #N on processor #N, if possible\n"
+ " with NUM pin all threads to the processor NUM\n"
+ "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
+ "-d DIST --distance=DIST distance of thread intervals in us default=500\n"
+ "-i INTV --interval=INTV base interval of thread in us default=1000\n"
+ "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ "-p PRIO --prio=PRIO priority\n"
+ "-t --threads one thread per available processor\n"
+ "-t [NUM] --threads=NUM number of threads:\n"
+ " without NUM, threads = max_cpus\n"
+ " without -t default = 1\n");
+ exit(1);
+}
+
+
+static int setaffinity = AFFINITY_UNSPECIFIED;
+static int affinity;
+static int tracelimit;
+static int priority;
+static int num_threads = 1;
+static int max_cycles;
+static int interval = 1000;
+static int distance = 500;
+
+static void process_options (int argc, char *argv[])
+{
+ int error = 0;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (;;) {
+ int option_index = 0;
+ /** Options for getopt */
+ static struct option long_options[] = {
+ {"affinity", optional_argument, NULL, 'a'},
+ {"breaktrace", required_argument, NULL, 'b'},
+ {"distance", required_argument, NULL, 'd'},
+ {"interval", required_argument, NULL, 'i'},
+ {"loops", required_argument, NULL, 'l'},
+ {"priority", required_argument, NULL, 'p'},
+ {"threads", optional_argument, NULL, 't'},
+ {"help", no_argument, NULL, '?'},
+ {NULL, 0, NULL, 0}
+ };
+ int c = getopt_long (argc, argv, "a::b:d:i:l:p:t::",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'a':
+ if (optarg != NULL) {
+ affinity = atoi(optarg);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else if (optind<argc && atoi(argv[optind])) {
+ affinity = atoi(argv[optind]);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else {
+ setaffinity = AFFINITY_USEALL;
+ }
+ break;
+ case 'b': tracelimit = atoi(optarg); break;
+ case 'd': distance = atoi(optarg); break;
+ case 'i': interval = atoi(optarg); break;
+ case 'l': max_cycles = atoi(optarg); break;
+ case 'p': priority = atoi(optarg); break;
+ case 't':
+ if (optarg != NULL)
+ num_threads = atoi(optarg);
+ else if (optind<argc && atoi(argv[optind]))
+ num_threads = atoi(argv[optind]);
+ else
+ num_threads = max_cpus;
+ break;
+ case '?': error = 1; break;
+ }
+ }
+
+ if (setaffinity == AFFINITY_SPECIFIED) {
+ if (affinity < 0)
+ error = 1;
+ if (affinity >= max_cpus) {
+ fprintf(stderr, "ERROR: CPU #%d not found, only %d CPUs available\n",
+ affinity, max_cpus);
+ error = 1;
+ }
+ }
+
+ if (num_threads < 0 || num_threads > 255)
+ error = 1;
+
+ if (priority < 0 || priority > 99)
+ error = 1;
+
+ if (num_threads < 1)
+ error = 1;
+
+ if (error)
+ display_help ();
+}
+
+
+static int volatile shutdown;
+
+static void sighand(int sig)
+{
+ shutdown = 1;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ int oldsamples = 1;
+ struct params *receiver = NULL;
+ struct params *sender = NULL;
+ sigset_t sigset;
+ struct timespec maindelay;
+
+ process_options(argc, argv);
+
+ if (check_privs())
+ return 1;
+
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
+ perror("mlockall");
+ return 1;
+ }
+
+ signal(SIGINT, sighand);
+ signal(SIGTERM, sighand);
+
+ receiver = calloc(num_threads, sizeof(struct params));
+ sender = calloc(num_threads, sizeof(struct params));
+ if (receiver == NULL || sender == NULL)
+ goto nomem;
+
+ testmutex = (pthread_mutex_t *) calloc(num_threads, sizeof(pthread_mutex_t));
+ syncmutex = (pthread_mutex_t *) calloc(num_threads, sizeof(pthread_mutex_t));
+ if (testmutex == NULL || syncmutex == NULL)
+ goto nomem;
+
+ for (i = 0; i < num_threads; i++) {
+ receiver[i].mindiff = UINT_MAX;
+ receiver[i].maxdiff = 0;
+ receiver[i].sumdiff = 0.0;
+
+
+ pthread_mutex_init(&testmutex[i], NULL);
+ pthread_mutex_init(&syncmutex[i], NULL);
+
+ /* Wait on first attempt */
+ pthread_mutex_lock(&testmutex[i]);
+
+ receiver[i].num = i;
+ receiver[i].cpu = i;
+ switch (setaffinity) {
+ case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
+ case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
+ case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
+ }
+ receiver[i].priority = priority;
+ receiver[i].tracelimit = tracelimit;
+ if (priority > 0)
+ priority--;
+ receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
+ receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
+ interval += distance;
+ receiver[i].max_cycles = max_cycles;
+ receiver[i].sender = 0;
+ receiver[i].neighbor = &sender[i];
+ pthread_create(&receiver[i].threadid, NULL, semathread, &receiver[i]);
+ memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
+ sender[i].sender = 1;
+ sender[i].neighbor = &receiver[i];
+ pthread_create(&sender[i].threadid, NULL, semathread, &sender[i]);
+ }
+
+ maindelay.tv_sec = 0;
+ maindelay.tv_nsec = 50000000; /* 50 ms */
+
+ while (!shutdown) {
+ int printed;
+ int errorlines = 0;
+
+ for (i = 0; i < num_threads; i++)
+ shutdown |= receiver[i].shutdown | sender[i].shutdown;
+
+ if (receiver[0].samples > oldsamples || shutdown) {
+ for (i = 0; i < num_threads; i++) {
+ printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: ID%d, P%d, CPU%d, Cycles %d\n",
+ i*2, receiver[i].tid, receiver[i].priority, receiver[i].cpu,
+ receiver[i].delay.tv_nsec / 1000,
+ i*2+1, sender[i].tid, sender[i].priority, sender[i].cpu,
+ sender[i].samples);
+ }
+ for (i = 0; i < num_threads; i++) {
+ printf("#%d -> #%d, Min %4d, Cur %4d, Avg %4d, Max %4d\n",
+ i*2+1, i*2,
+ receiver[i].mindiff, (int) receiver[i].diff.tv_usec,
+ (int) ((receiver[i].sumdiff / receiver[i].samples) + 0.5),
+ receiver[i].maxdiff);
+ if (receiver[i].error[0] != '\0') {
+ printf(receiver[i].error);
+ errorlines++;
+ receiver[i].error[0] = '\0';
+ }
+ if (sender[i].error[0] != '\0') {
+ printf(sender[i].error);
+ errorlines++;
+ receiver[i].error[0] = '\0';
+ }
+ }
+ printed = 1;
+ } else
+ printed = 0;
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTERM);
+ sigaddset(&sigset, SIGINT);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ nanosleep(&maindelay, NULL);
+
+ sigemptyset(&sigset);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ if (printed && !shutdown)
+ printf("\033[%dA", num_threads*2 + errorlines);
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ receiver[i].shutdown = 1;
+ sender[i].shutdown = 1;
+ pthread_mutex_unlock(&testmutex[i]);
+ pthread_mutex_unlock(&syncmutex[i]);
+ }
+ nanosleep(&receiver[0].delay, NULL);
+
+ for (i = 0; i < num_threads; i++) {
+ if (!receiver[i].stopped)
+ pthread_kill(receiver[i].threadid, SIGTERM);
+ if (!sender[i].stopped)
+ pthread_kill(sender[i].threadid, SIGTERM);
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ pthread_mutex_destroy(&testmutex[i]);
+ pthread_mutex_destroy(&syncmutex[i]);
+ }
+
+ nomem:
+
+ return 0;
+}
diff --git a/src/sigwaittest/Makefile b/src/sigwaittest/Makefile
index 521daeb..697e3d5 100644
--- a/src/sigwaittest/Makefile
+++ b/src/sigwaittest/Makefile
@@ -1,17 +1,17 @@
-CFLAGS += -Wall -O2
-LDFLAGS += -lpthread -lrt
-
-all: sigwaittest
- @echo Done
-
-sigwaittest.o: sigwaittest.c
-
-sigwaittest:
-
-clean:
- @rm -f *.o
-
-tar: clean
- @rm -f sigwaittest
- $(shell bn=`basename $$PWD`; cd ..; tar -zcf $$bn.tgz $$bn)
-
+CFLAGS += -Wall -O2
+LDFLAGS += -lpthread -lrt
+
+all: sigwaittest
+ @echo Done
+
+sigwaittest.o: sigwaittest.c
+
+sigwaittest:
+
+clean:
+ @rm -f *.o
+
+tar: clean
+ @rm -f sigwaittest
+ $(shell bn=`basename $$PWD`; cd ..; tar -zcf $$bn.tgz $$bn)
+
diff --git a/src/sigwaittest/sigwaittest.c b/src/sigwaittest/sigwaittest.c
index 740e13d..adb51cf 100644
--- a/src/sigwaittest/sigwaittest.c
+++ b/src/sigwaittest/sigwaittest.c
@@ -1,618 +1,618 @@
-/*
- * sigwaittest.c
- *
- * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <getopt.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-#include <utmpx.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <linux/unistd.h>
-#include <utmpx.h>
-#include "rt-utils.h"
-
-#define __USE_GNU
-#include <pthread.h>
-
-#define gettid() syscall(__NR_gettid)
-
-#define USEC_PER_SEC 1000000
-
-enum {
- AFFINITY_UNSPECIFIED,
- AFFINITY_SPECIFIED,
- AFFINITY_USEALL
-};
-
-struct params {
- int num;
- int num_threads;
- int cpu;
- int priority;
- int affinity;
- int sender;
- int samples;
- int max_cycles;
- int tracelimit;
- int tid;
- pid_t pid;
- int shutdown;
- int stopped;
- struct timespec delay;
- unsigned int mindiff, maxdiff;
- double sumdiff;
- struct timeval unblocked, received, diff;
- pthread_t threadid;
- struct params *neighbor;
- char error[MAX_PATH * 2];
-};
-
-static int mustfork;
-static int wasforked;
-static int wasforked_sender = -1;
-static int wasforked_threadno = -1;
-static int tracelimit;
-
-void *semathread(void *param)
-{
- int mustgetcpu = 0;
- struct params *par = param;
- cpu_set_t mask;
- int policy = SCHED_FIFO;
- struct sched_param schedp;
-
- memset(&schedp, 0, sizeof(schedp));
- schedp.sched_priority = par->priority;
- sched_setscheduler(0, policy, &schedp);
-
- if (par->cpu != -1) {
- CPU_ZERO(&mask);
- CPU_SET(par->cpu, &mask);
- if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
- fprintf(stderr, "WARNING: Could not set CPU affinity "
- "to CPU #%d\n", par->cpu);
- } else {
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- if (max_cpus > 1)
- mustgetcpu = 1;
- else
- par->cpu = 0;
- }
-
- if (!wasforked)
- par->tid = gettid();
-
- while (!par->shutdown) {
- int sig;
- int first = 1;
- sigset_t sigset;
- struct params *neighbor = NULL;
-
- if (par->sender) {
- if (wasforked)
- neighbor = par - par->num_threads;
- else
- neighbor = par->neighbor;
- if (first) {
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGUSR1);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
- first = 0;
- }
-
- /* Sending signal: Start of latency measurement ... */
- gettimeofday(&par->unblocked, NULL);
- if (wasforked)
- kill(neighbor->pid, SIGUSR2);
- else
- pthread_kill(neighbor->threadid, SIGUSR2);
- par->samples++;
- if(par->max_cycles && par->samples >= par->max_cycles)
- par->shutdown = 1;
-
- if (mustgetcpu) {
- par->cpu = sched_getcpu();
- }
- sigwait(&sigset, &sig);
- } else {
- /* Receiver */
- if (wasforked)
- neighbor = par + par->num_threads;
- else
- neighbor = par->neighbor;
- if (first) {
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGUSR2);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
- first = 0;
- }
- sigwait(&sigset, &sig);
-
- /* ... Signal received: End of latency measurement */
- gettimeofday(&par->received, NULL);
- par->samples++;
- if (par->max_cycles && par->samples >= par->max_cycles)
- par->shutdown = 1;
-
- if (mustgetcpu) {
- par->cpu = sched_getcpu();
- }
- /*
- * Latency is the time spent between sending and
- * receiving the signal.
- */
- timersub(&par->received, &neighbor->unblocked,
- &par->diff);
-
- if (par->diff.tv_usec < par->mindiff)
- par->mindiff = par->diff.tv_usec;
- if (par->diff.tv_usec > par->maxdiff)
- par->maxdiff = par->diff.tv_usec;
- par->sumdiff += (double) par->diff.tv_usec;
- if (par->tracelimit && par->maxdiff > par->tracelimit) {
- char tracing_enabled_file[MAX_PATH];
-
- strcpy(tracing_enabled_file, get_debugfileprefix());
- strcat(tracing_enabled_file, "tracing_enabled");
- int tracing_enabled =
- open(tracing_enabled_file, O_WRONLY);
- if (tracing_enabled >= 0) {
- write(tracing_enabled, "0", 1);
- close(tracing_enabled);
- } else
- snprintf(par->error, sizeof(par->error),
- "Could not access %s\n",
- tracing_enabled_file);
- par->shutdown = 1;
- neighbor->shutdown = 1;
- }
-
- nanosleep(&par->delay, NULL);
-
- if (wasforked)
- kill(neighbor->pid, SIGUSR1);
- else
- pthread_kill(neighbor->threadid, SIGUSR1);
- }
- }
- par->stopped = 1;
- return NULL;
-}
-
-
-static void display_help(void)
-{
- printf("sigwaittest V %1.2f\n", VERSION_STRING);
- puts("Usage: sigwaittest <options>");
- puts("Function: test sigwait() latency");
- puts(
- "Options:\n"
- "-a [NUM] --affinity run thread #N on processor #N, if possible\n"
- " with NUM pin all threads to the processor NUM\n"
- "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
- "-d DIST --distance=DIST distance of thread intervals in us default=500\n"
- "-f --fork fork new processes instead of creating threads\n"
- "-i INTV --interval=INTV base interval of thread in us default=1000\n"
- "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
- "-p PRIO --prio=PRIO priority\n"
- "-t --threads one thread per available processor\n"
- "-t [NUM] --threads=NUM number of threads:\n"
- " without NUM, threads = max_cpus\n"
- " without -t default = 1\n");
- exit(1);
-}
-
-
-static int setaffinity = AFFINITY_UNSPECIFIED;
-static int affinity;
-static int priority;
-static int num_threads = 1;
-static int max_cycles;
-static int interval = 1000;
-static int distance = 500;
-
-static void process_options (int argc, char *argv[])
-{
- int error = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
- int thistracelimit = 0;
-
- for (;;) {
- int option_index = 0;
- /** Options for getopt */
- static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"fork", optional_argument, NULL, 'f'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"threads", optional_argument, NULL, 't'},
- {"help", no_argument, NULL, '?'},
- {NULL, 0, NULL, 0}
- };
- int c = getopt_long (argc, argv, "a::b:d:f::i:l:p:t::",
- long_options, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'a':
- if (optarg != NULL) {
- affinity = atoi(optarg);
- setaffinity = AFFINITY_SPECIFIED;
- } else if (optind<argc && atoi(argv[optind])) {
- affinity = atoi(argv[optind]);
- setaffinity = AFFINITY_SPECIFIED;
- } else {
- setaffinity = AFFINITY_USEALL;
- }
- break;
- case 'b': thistracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'f':
- if (optarg != NULL) {
- wasforked = 1;
- if (optarg[0] == 's')
- wasforked_sender = 1;
- else if (optarg[0] == 'r')
- wasforked_sender = 0;
- wasforked_threadno = atoi(optarg+1);
- } else
- mustfork = 1;
- break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 't':
- if (optarg != NULL)
- num_threads = atoi(optarg);
- else if (optind<argc && atoi(argv[optind]))
- num_threads = atoi(argv[optind]);
- else
- num_threads = max_cpus;
- break;
- case '?': error = 1; break;
- }
- }
-
- if (!wasforked) {
- if (setaffinity == AFFINITY_SPECIFIED) {
- if (affinity < 0)
- error = 1;
- if (affinity >= max_cpus) {
- fprintf(stderr, "ERROR: CPU #%d not found, "
- "only %d CPUs available\n",
- affinity, max_cpus);
- error = 1;
- }
- }
-
- if (num_threads < 1 || num_threads > 255)
- error = 1;
-
- if (priority < 0 || priority > 99)
- error = 1;
-
- tracelimit = thistracelimit;
- }
- if (error)
- display_help ();
-}
-
-
-static int volatile mustshutdown;
-
-static void sighand(int sig)
-{
- mustshutdown = 1;
-}
-
-
-int main(int argc, char *argv[])
-{
- int i, totalsize = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
- int oldsamples = 1;
- struct params *receiver = NULL;
- struct params *sender = NULL;
- sigset_t sigset;
- void *param = NULL;
- char f_opt[8];
- struct timespec launchdelay, maindelay;
-
- process_options(argc, argv);
-
- if (check_privs())
- return 1;
-
- if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
- perror("mlockall");
- return 1;
- }
-
- if (mustfork) {
- int shmem;
-
- /*
- * In fork mode (-f), the shared memory contains two
- * subsequent arrays, receiver[num_threads] and
- * sender[num_threads].
- */
- totalsize = num_threads * sizeof(struct params) * 2;
-
- shm_unlink("/sigwaittest");
- shmem = shm_open("/sigwaittest", O_CREAT|O_EXCL|O_RDWR,
- S_IRUSR|S_IWUSR);
- if (shmem < 0) {
- fprintf(stderr, "Could not create shared memory\n");
- return 1;
- }
- ftruncate(shmem, totalsize);
- param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
- shmem, 0);
- if (param == MAP_FAILED) {
- fprintf(stderr, "Could not map shared memory\n");
- close(shmem);
- return 1;
- }
-
- receiver = (struct params *) param;
- sender = receiver + num_threads;
- } else if (wasforked) {
- struct stat buf;
- int shmem, totalsize, expect_totalsize;
-
- if (wasforked_threadno == -1 || wasforked_sender == -1) {
- fprintf(stderr, "Invalid fork option\n");
- return 1;
- }
- shmem = shm_open("/sigwaittest", O_RDWR, S_IRUSR|S_IWUSR);
- if (fstat(shmem, &buf)) {
- fprintf(stderr,
- "Could not determine shared memory size\n");
- close(shmem);
- return 1;
- }
- totalsize = buf.st_size;
- param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
- shmem, 0);
- close(shmem);
- if (param == MAP_FAILED) {
- fprintf(stderr, "Could not map shared memory\n");
- return 1;
- }
-
- receiver = (struct params *) param;
- expect_totalsize = receiver->num_threads *
- sizeof(struct params) * 2;
- if (totalsize != expect_totalsize) {
- fprintf(stderr, "Memory size problem (expected %d, "
- "found %d\n", expect_totalsize, totalsize);
- munmap(param, totalsize);
- return 1;
- }
- sender = receiver + receiver->num_threads;
- if (wasforked_sender)
- semathread(sender + wasforked_threadno);
- else
- semathread(receiver + wasforked_threadno);
- munmap(param, totalsize);
- return 0;
- }
-
- signal(SIGINT, sighand);
- signal(SIGTERM, sighand);
- sigemptyset(&sigset);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- if (!mustfork && !wasforked) {
- receiver = calloc(num_threads, sizeof(struct params));
- sender = calloc(num_threads, sizeof(struct params));
- if (receiver == NULL || sender == NULL)
- goto nomem;
- }
-
- launchdelay.tv_sec = 0;
- launchdelay.tv_nsec = 10000000; /* 10 ms */
-
- maindelay.tv_sec = 0;
- maindelay.tv_nsec = 50000000; /* 50 ms */
-
- for (i = 0; i < num_threads; i++) {
- receiver[i].mindiff = UINT_MAX;
- receiver[i].maxdiff = 0;
- receiver[i].sumdiff = 0.0;
-
- receiver[i].num = i;
- receiver[i].cpu = i;
- receiver[i].priority = priority;
- receiver[i].tracelimit = tracelimit;
- if (priority > 0)
- priority--;
- switch (setaffinity) {
- case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
- case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
- case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
- }
- receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
- receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
- interval += distance;
- receiver[i].max_cycles = max_cycles;
- receiver[i].sender = 0;
- receiver[i].neighbor = &sender[i];
- if (mustfork) {
- pid_t pid = fork();
- if (pid == -1) {
- fprintf(stderr, "Could not fork\n");
- return 1;
- } else if (pid == 0) {
- char *args[3];
-
- receiver[i].num_threads = num_threads;
- receiver[i].pid = getpid();
- sprintf(f_opt, "-fr%d", i);
- args[0] = argv[0];
- args[1] = f_opt;
- args[2] = NULL;
- execvp(args[0], args);
- fprintf(stderr,
- "Could not execute receiver child process "
- "#%d\n", i);
- }
- } else
- pthread_create(&receiver[i].threadid, NULL,
- semathread, &receiver[i]);
-
- nanosleep(&launchdelay, NULL);
-
- memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
- sender[i].sender = 1;
- sender[i].neighbor = &receiver[i];
- if (mustfork) {
- pid_t pid = fork();
- if (pid == -1) {
- fprintf(stderr, "Could not fork\n");
- return 1;
- } else if (pid == 0) {
- char *args[3];
-
- sender[i].num_threads = num_threads;
- sender[i].pid = getpid();
- sprintf(f_opt, "-fs%d", i);
- args[0] = argv[0];
- args[1] = f_opt;
- args[2] = NULL;
- execvp(args[0], args);
- fprintf(stderr,
- "Could not execute sender child process "
- "#%d\n", i);
- }
- } else
- pthread_create(&sender[i].threadid, NULL, semathread,
- &sender[i]);
- }
-
- while (!mustshutdown) {
- int printed;
- int errorlines = 0;
-
- for (i = 0; i < num_threads; i++)
- mustshutdown |= receiver[i].shutdown |
- sender[i].shutdown;
-
- if (receiver[0].samples > oldsamples || mustshutdown) {
- for (i = 0; i < num_threads; i++) {
- int receiver_pid, sender_pid;
- if (mustfork) {
- receiver_pid = receiver[i].pid;
- sender_pid = sender[i].pid;
- } else {
- receiver_pid = receiver[i].tid;
- sender_pid = sender[i].tid;
- }
- printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: "
- "ID%d, P%d, CPU%d, Cycles %d\n",
- i*2, receiver_pid, receiver[i].priority,
- receiver[i].cpu, receiver[i].delay.tv_nsec /
- 1000, i*2+1, sender_pid, sender[i].priority,
- sender[i].cpu, sender[i].samples);
- }
- for (i = 0; i < num_threads; i++) {
- if (receiver[i].mindiff == -1)
- printf("#%d -> #%d (not yet ready)\n",
- i*2+1, i*2);
- else
- printf("#%d -> #%d, Min %4d, Cur %4d, "
- "Avg %4d, Max %4d\n",
- i*2+1, i*2, receiver[i].mindiff,
- (int) receiver[i].diff.tv_usec,
- (int) ((receiver[i].sumdiff /
- receiver[i].samples) + 0.5),
- receiver[i].maxdiff);
- if (receiver[i].error[0] != '\0') {
- printf(receiver[i].error);
- receiver[i].error[0] = '\0';
- errorlines++;
- }
- if (sender[i].error[0] != '\0') {
- printf(sender[i].error);
- sender[i].error[0] = '\0';
- errorlines++;
- }
- }
- printed = 1;
- } else
- printed = 0;
-
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGTERM);
- sigaddset(&sigset, SIGINT);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- nanosleep(&maindelay, NULL);
-
- sigemptyset(&sigset);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- if (printed && !mustshutdown)
- printf("\033[%dA", num_threads*2 + errorlines);
- }
-
- for (i = 0; i < num_threads; i++) {
- receiver[i].shutdown = 1;
- sender[i].shutdown = 1;
- }
- nanosleep(&receiver[0].delay, NULL);
-
- for (i = 0; i < num_threads; i++) {
- if (!receiver[i].stopped) {
- if (mustfork)
- kill(receiver[i].pid, SIGTERM);
- else
- pthread_kill(receiver[i].threadid, SIGTERM);
- }
- if (!sender[i].stopped) {
- if (mustfork)
- kill(sender[i].pid, SIGTERM);
- else
- pthread_kill(sender[i].threadid, SIGTERM);
- }
- }
-
- nomem:
- if (mustfork) {
- munmap(param, totalsize);
- shm_unlink("/sigwaittest");
- }
-
- return 0;
-}
+/*
+ * sigwaittest.c
+ *
+ * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <getopt.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <utmpx.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <linux/unistd.h>
+#include <utmpx.h>
+#include "rt-utils.h"
+
+#define __USE_GNU
+#include <pthread.h>
+
+#define gettid() syscall(__NR_gettid)
+
+#define USEC_PER_SEC 1000000
+
+enum {
+ AFFINITY_UNSPECIFIED,
+ AFFINITY_SPECIFIED,
+ AFFINITY_USEALL
+};
+
+struct params {
+ int num;
+ int num_threads;
+ int cpu;
+ int priority;
+ int affinity;
+ int sender;
+ int samples;
+ int max_cycles;
+ int tracelimit;
+ int tid;
+ pid_t pid;
+ int shutdown;
+ int stopped;
+ struct timespec delay;
+ unsigned int mindiff, maxdiff;
+ double sumdiff;
+ struct timeval unblocked, received, diff;
+ pthread_t threadid;
+ struct params *neighbor;
+ char error[MAX_PATH * 2];
+};
+
+static int mustfork;
+static int wasforked;
+static int wasforked_sender = -1;
+static int wasforked_threadno = -1;
+static int tracelimit;
+
+void *semathread(void *param)
+{
+ int mustgetcpu = 0;
+ struct params *par = param;
+ cpu_set_t mask;
+ int policy = SCHED_FIFO;
+ struct sched_param schedp;
+
+ memset(&schedp, 0, sizeof(schedp));
+ schedp.sched_priority = par->priority;
+ sched_setscheduler(0, policy, &schedp);
+
+ if (par->cpu != -1) {
+ CPU_ZERO(&mask);
+ CPU_SET(par->cpu, &mask);
+ if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
+ fprintf(stderr, "WARNING: Could not set CPU affinity "
+ "to CPU #%d\n", par->cpu);
+ } else {
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ if (max_cpus > 1)
+ mustgetcpu = 1;
+ else
+ par->cpu = 0;
+ }
+
+ if (!wasforked)
+ par->tid = gettid();
+
+ while (!par->shutdown) {
+ int sig;
+ int first = 1;
+ sigset_t sigset;
+ struct params *neighbor = NULL;
+
+ if (par->sender) {
+ if (wasforked)
+ neighbor = par - par->num_threads;
+ else
+ neighbor = par->neighbor;
+ if (first) {
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGUSR1);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+ first = 0;
+ }
+
+ /* Sending signal: Start of latency measurement ... */
+ gettimeofday(&par->unblocked, NULL);
+ if (wasforked)
+ kill(neighbor->pid, SIGUSR2);
+ else
+ pthread_kill(neighbor->threadid, SIGUSR2);
+ par->samples++;
+ if(par->max_cycles && par->samples >= par->max_cycles)
+ par->shutdown = 1;
+
+ if (mustgetcpu) {
+ par->cpu = sched_getcpu();
+ }
+ sigwait(&sigset, &sig);
+ } else {
+ /* Receiver */
+ if (wasforked)
+ neighbor = par + par->num_threads;
+ else
+ neighbor = par->neighbor;
+ if (first) {
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGUSR2);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+ first = 0;
+ }
+ sigwait(&sigset, &sig);
+
+ /* ... Signal received: End of latency measurement */
+ gettimeofday(&par->received, NULL);
+ par->samples++;
+ if (par->max_cycles && par->samples >= par->max_cycles)
+ par->shutdown = 1;
+
+ if (mustgetcpu) {
+ par->cpu = sched_getcpu();
+ }
+ /*
+ * Latency is the time spent between sending and
+ * receiving the signal.
+ */
+ timersub(&par->received, &neighbor->unblocked,
+ &par->diff);
+
+ if (par->diff.tv_usec < par->mindiff)
+ par->mindiff = par->diff.tv_usec;
+ if (par->diff.tv_usec > par->maxdiff)
+ par->maxdiff = par->diff.tv_usec;
+ par->sumdiff += (double) par->diff.tv_usec;
+ if (par->tracelimit && par->maxdiff > par->tracelimit) {
+ char tracing_enabled_file[MAX_PATH];
+
+ strcpy(tracing_enabled_file, get_debugfileprefix());
+ strcat(tracing_enabled_file, "tracing_enabled");
+ int tracing_enabled =
+ open(tracing_enabled_file, O_WRONLY);
+ if (tracing_enabled >= 0) {
+ write(tracing_enabled, "0", 1);
+ close(tracing_enabled);
+ } else
+ snprintf(par->error, sizeof(par->error),
+ "Could not access %s\n",
+ tracing_enabled_file);
+ par->shutdown = 1;
+ neighbor->shutdown = 1;
+ }
+
+ nanosleep(&par->delay, NULL);
+
+ if (wasforked)
+ kill(neighbor->pid, SIGUSR1);
+ else
+ pthread_kill(neighbor->threadid, SIGUSR1);
+ }
+ }
+ par->stopped = 1;
+ return NULL;
+}
+
+
+static void display_help(void)
+{
+ printf("sigwaittest V %1.2f\n", VERSION_STRING);
+ puts("Usage: sigwaittest <options>");
+ puts("Function: test sigwait() latency");
+ puts(
+ "Options:\n"
+ "-a [NUM] --affinity run thread #N on processor #N, if possible\n"
+ " with NUM pin all threads to the processor NUM\n"
+ "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
+ "-d DIST --distance=DIST distance of thread intervals in us default=500\n"
+ "-f --fork fork new processes instead of creating threads\n"
+ "-i INTV --interval=INTV base interval of thread in us default=1000\n"
+ "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ "-p PRIO --prio=PRIO priority\n"
+ "-t --threads one thread per available processor\n"
+ "-t [NUM] --threads=NUM number of threads:\n"
+ " without NUM, threads = max_cpus\n"
+ " without -t default = 1\n");
+ exit(1);
+}
+
+
+static int setaffinity = AFFINITY_UNSPECIFIED;
+static int affinity;
+static int priority;
+static int num_threads = 1;
+static int max_cycles;
+static int interval = 1000;
+static int distance = 500;
+
+static void process_options (int argc, char *argv[])
+{
+ int error = 0;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ int thistracelimit = 0;
+
+ for (;;) {
+ int option_index = 0;
+ /** Options for getopt */
+ static struct option long_options[] = {
+ {"affinity", optional_argument, NULL, 'a'},
+ {"breaktrace", required_argument, NULL, 'b'},
+ {"distance", required_argument, NULL, 'd'},
+ {"fork", optional_argument, NULL, 'f'},
+ {"interval", required_argument, NULL, 'i'},
+ {"loops", required_argument, NULL, 'l'},
+ {"priority", required_argument, NULL, 'p'},
+ {"threads", optional_argument, NULL, 't'},
+ {"help", no_argument, NULL, '?'},
+ {NULL, 0, NULL, 0}
+ };
+ int c = getopt_long (argc, argv, "a::b:d:f::i:l:p:t::",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'a':
+ if (optarg != NULL) {
+ affinity = atoi(optarg);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else if (optind<argc && atoi(argv[optind])) {
+ affinity = atoi(argv[optind]);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else {
+ setaffinity = AFFINITY_USEALL;
+ }
+ break;
+ case 'b': thistracelimit = atoi(optarg); break;
+ case 'd': distance = atoi(optarg); break;
+ case 'f':
+ if (optarg != NULL) {
+ wasforked = 1;
+ if (optarg[0] == 's')
+ wasforked_sender = 1;
+ else if (optarg[0] == 'r')
+ wasforked_sender = 0;
+ wasforked_threadno = atoi(optarg+1);
+ } else
+ mustfork = 1;
+ break;
+ case 'i': interval = atoi(optarg); break;
+ case 'l': max_cycles = atoi(optarg); break;
+ case 'p': priority = atoi(optarg); break;
+ case 't':
+ if (optarg != NULL)
+ num_threads = atoi(optarg);
+ else if (optind<argc && atoi(argv[optind]))
+ num_threads = atoi(argv[optind]);
+ else
+ num_threads = max_cpus;
+ break;
+ case '?': error = 1; break;
+ }
+ }
+
+ if (!wasforked) {
+ if (setaffinity == AFFINITY_SPECIFIED) {
+ if (affinity < 0)
+ error = 1;
+ if (affinity >= max_cpus) {
+ fprintf(stderr, "ERROR: CPU #%d not found, "
+ "only %d CPUs available\n",
+ affinity, max_cpus);
+ error = 1;
+ }
+ }
+
+ if (num_threads < 1 || num_threads > 255)
+ error = 1;
+
+ if (priority < 0 || priority > 99)
+ error = 1;
+
+ tracelimit = thistracelimit;
+ }
+ if (error)
+ display_help ();
+}
+
+
+static int volatile mustshutdown;
+
+static void sighand(int sig)
+{
+ mustshutdown = 1;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int i, totalsize = 0;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ int oldsamples = 1;
+ struct params *receiver = NULL;
+ struct params *sender = NULL;
+ sigset_t sigset;
+ void *param = NULL;
+ char f_opt[8];
+ struct timespec launchdelay, maindelay;
+
+ process_options(argc, argv);
+
+ if (check_privs())
+ return 1;
+
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
+ perror("mlockall");
+ return 1;
+ }
+
+ if (mustfork) {
+ int shmem;
+
+ /*
+ * In fork mode (-f), the shared memory contains two
+ * subsequent arrays, receiver[num_threads] and
+ * sender[num_threads].
+ */
+ totalsize = num_threads * sizeof(struct params) * 2;
+
+ shm_unlink("/sigwaittest");
+ shmem = shm_open("/sigwaittest", O_CREAT|O_EXCL|O_RDWR,
+ S_IRUSR|S_IWUSR);
+ if (shmem < 0) {
+ fprintf(stderr, "Could not create shared memory\n");
+ return 1;
+ }
+ ftruncate(shmem, totalsize);
+ param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
+ shmem, 0);
+ if (param == MAP_FAILED) {
+ fprintf(stderr, "Could not map shared memory\n");
+ close(shmem);
+ return 1;
+ }
+
+ receiver = (struct params *) param;
+ sender = receiver + num_threads;
+ } else if (wasforked) {
+ struct stat buf;
+ int shmem, totalsize, expect_totalsize;
+
+ if (wasforked_threadno == -1 || wasforked_sender == -1) {
+ fprintf(stderr, "Invalid fork option\n");
+ return 1;
+ }
+ shmem = shm_open("/sigwaittest", O_RDWR, S_IRUSR|S_IWUSR);
+ if (fstat(shmem, &buf)) {
+ fprintf(stderr,
+ "Could not determine shared memory size\n");
+ close(shmem);
+ return 1;
+ }
+ totalsize = buf.st_size;
+ param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
+ shmem, 0);
+ close(shmem);
+ if (param == MAP_FAILED) {
+ fprintf(stderr, "Could not map shared memory\n");
+ return 1;
+ }
+
+ receiver = (struct params *) param;
+ expect_totalsize = receiver->num_threads *
+ sizeof(struct params) * 2;
+ if (totalsize != expect_totalsize) {
+ fprintf(stderr, "Memory size problem (expected %d, "
+ "found %d\n", expect_totalsize, totalsize);
+ munmap(param, totalsize);
+ return 1;
+ }
+ sender = receiver + receiver->num_threads;
+ if (wasforked_sender)
+ semathread(sender + wasforked_threadno);
+ else
+ semathread(receiver + wasforked_threadno);
+ munmap(param, totalsize);
+ return 0;
+ }
+
+ signal(SIGINT, sighand);
+ signal(SIGTERM, sighand);
+ sigemptyset(&sigset);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ if (!mustfork && !wasforked) {
+ receiver = calloc(num_threads, sizeof(struct params));
+ sender = calloc(num_threads, sizeof(struct params));
+ if (receiver == NULL || sender == NULL)
+ goto nomem;
+ }
+
+ launchdelay.tv_sec = 0;
+ launchdelay.tv_nsec = 10000000; /* 10 ms */
+
+ maindelay.tv_sec = 0;
+ maindelay.tv_nsec = 50000000; /* 50 ms */
+
+ for (i = 0; i < num_threads; i++) {
+ receiver[i].mindiff = UINT_MAX;
+ receiver[i].maxdiff = 0;
+ receiver[i].sumdiff = 0.0;
+
+ receiver[i].num = i;
+ receiver[i].cpu = i;
+ receiver[i].priority = priority;
+ receiver[i].tracelimit = tracelimit;
+ if (priority > 0)
+ priority--;
+ switch (setaffinity) {
+ case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
+ case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
+ case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
+ }
+ receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
+ receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
+ interval += distance;
+ receiver[i].max_cycles = max_cycles;
+ receiver[i].sender = 0;
+ receiver[i].neighbor = &sender[i];
+ if (mustfork) {
+ pid_t pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Could not fork\n");
+ return 1;
+ } else if (pid == 0) {
+ char *args[3];
+
+ receiver[i].num_threads = num_threads;
+ receiver[i].pid = getpid();
+ sprintf(f_opt, "-fr%d", i);
+ args[0] = argv[0];
+ args[1] = f_opt;
+ args[2] = NULL;
+ execvp(args[0], args);
+ fprintf(stderr,
+ "Could not execute receiver child process "
+ "#%d\n", i);
+ }
+ } else
+ pthread_create(&receiver[i].threadid, NULL,
+ semathread, &receiver[i]);
+
+ nanosleep(&launchdelay, NULL);
+
+ memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
+ sender[i].sender = 1;
+ sender[i].neighbor = &receiver[i];
+ if (mustfork) {
+ pid_t pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Could not fork\n");
+ return 1;
+ } else if (pid == 0) {
+ char *args[3];
+
+ sender[i].num_threads = num_threads;
+ sender[i].pid = getpid();
+ sprintf(f_opt, "-fs%d", i);
+ args[0] = argv[0];
+ args[1] = f_opt;
+ args[2] = NULL;
+ execvp(args[0], args);
+ fprintf(stderr,
+ "Could not execute sender child process "
+ "#%d\n", i);
+ }
+ } else
+ pthread_create(&sender[i].threadid, NULL, semathread,
+ &sender[i]);
+ }
+
+ while (!mustshutdown) {
+ int printed;
+ int errorlines = 0;
+
+ for (i = 0; i < num_threads; i++)
+ mustshutdown |= receiver[i].shutdown |
+ sender[i].shutdown;
+
+ if (receiver[0].samples > oldsamples || mustshutdown) {
+ for (i = 0; i < num_threads; i++) {
+ int receiver_pid, sender_pid;
+ if (mustfork) {
+ receiver_pid = receiver[i].pid;
+ sender_pid = sender[i].pid;
+ } else {
+ receiver_pid = receiver[i].tid;
+ sender_pid = sender[i].tid;
+ }
+ printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: "
+ "ID%d, P%d, CPU%d, Cycles %d\n",
+ i*2, receiver_pid, receiver[i].priority,
+ receiver[i].cpu, receiver[i].delay.tv_nsec /
+ 1000, i*2+1, sender_pid, sender[i].priority,
+ sender[i].cpu, sender[i].samples);
+ }
+ for (i = 0; i < num_threads; i++) {
+ if (receiver[i].mindiff == -1)
+ printf("#%d -> #%d (not yet ready)\n",
+ i*2+1, i*2);
+ else
+ printf("#%d -> #%d, Min %4d, Cur %4d, "
+ "Avg %4d, Max %4d\n",
+ i*2+1, i*2, receiver[i].mindiff,
+ (int) receiver[i].diff.tv_usec,
+ (int) ((receiver[i].sumdiff /
+ receiver[i].samples) + 0.5),
+ receiver[i].maxdiff);
+ if (receiver[i].error[0] != '\0') {
+ printf(receiver[i].error);
+ receiver[i].error[0] = '\0';
+ errorlines++;
+ }
+ if (sender[i].error[0] != '\0') {
+ printf(sender[i].error);
+ sender[i].error[0] = '\0';
+ errorlines++;
+ }
+ }
+ printed = 1;
+ } else
+ printed = 0;
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTERM);
+ sigaddset(&sigset, SIGINT);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ nanosleep(&maindelay, NULL);
+
+ sigemptyset(&sigset);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ if (printed && !mustshutdown)
+ printf("\033[%dA", num_threads*2 + errorlines);
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ receiver[i].shutdown = 1;
+ sender[i].shutdown = 1;
+ }
+ nanosleep(&receiver[0].delay, NULL);
+
+ for (i = 0; i < num_threads; i++) {
+ if (!receiver[i].stopped) {
+ if (mustfork)
+ kill(receiver[i].pid, SIGTERM);
+ else
+ pthread_kill(receiver[i].threadid, SIGTERM);
+ }
+ if (!sender[i].stopped) {
+ if (mustfork)
+ kill(sender[i].pid, SIGTERM);
+ else
+ pthread_kill(sender[i].threadid, SIGTERM);
+ }
+ }
+
+ nomem:
+ if (mustfork) {
+ munmap(param, totalsize);
+ shm_unlink("/sigwaittest");
+ }
+
+ return 0;
+}
diff --git a/src/svsematest/Makefile b/src/svsematest/Makefile
index aab2da0..da8d32d 100644
--- a/src/svsematest/Makefile
+++ b/src/svsematest/Makefile
@@ -1,16 +1,16 @@
-CFLAGS += -Wall -O2
-LDFLAGS += -lpthread -lrt
-
-all: svsematest
- @echo Done
-
-svsematest.o: svsematest.c
-
-svsematest:
-
-clean:
- @rm -f *.o
-
-tar: clean
- @rm -f svsematest
- $(shell bn=`basename $$PWD`; cd ..; tar -zcf $$bn.tgz $$bn)
+CFLAGS += -Wall -O2
+LDFLAGS += -lpthread -lrt
+
+all: svsematest
+ @echo Done
+
+svsematest.o: svsematest.c
+
+svsematest:
+
+clean:
+ @rm -f *.o
+
+tar: clean
+ @rm -f svsematest
+ $(shell bn=`basename $$PWD`; cd ..; tar -zcf $$bn.tgz $$bn)
diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c
index 3f1ea48..50224de 100644
--- a/src/svsematest/svsematest.c
+++ b/src/svsematest/svsematest.c
@@ -1,704 +1,704 @@
-/*
- * svsematest.c
- *
- * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#define __USE_GNU
-#include <fcntl.h>
-#include <getopt.h>
-#include <pthread.h>
-#include <signal.h>
-#include <sched.h>
-#include <string.h>
-#include <time.h>
-#include <utmpx.h>
-
-#include <linux/unistd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sem.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include "rt-utils.h"
-
-#define HAS_SCHED_GETCPU
-
-#define gettid() syscall(__NR_gettid)
-#ifndef HAS_SCHED_GETCPU
-#define getcpu(cpu, node, cache) syscall(__NR_getcpu, cpu, node, cache)
-#endif
-
-#define USEC_PER_SEC 1000000
-
-#define SEM_WAIT_FOR_RECEIVER 0
-#define SEM_WAIT_FOR_SENDER 1
-
-#define SEM_LOCK -1
-#define SEM_UNLOCK 1
-
-enum {
- AFFINITY_UNSPECIFIED,
- AFFINITY_SPECIFIED,
- AFFINITY_USEALL
-};
-
-struct params {
- int num;
- int num_threads;
- int cpu;
- int priority;
- int affinity;
- int semid;
- int sender;
- int samples;
- int max_cycles;
- int tracelimit;
- int tid;
- pid_t pid;
- int shutdown;
- int stopped;
- struct timespec delay;
- unsigned int mindiff, maxdiff;
- double sumdiff;
- struct timeval unblocked, received, diff;
- pthread_t threadid;
- struct params *neighbor;
- char error[MAX_PATH * 2];
-};
-
-static int mustfork;
-static int wasforked;
-static int wasforked_sender = -1;
-static int wasforked_threadno = -1;
-static int tracelimit;
-
-void *semathread(void *param)
-{
- int mustgetcpu = 0;
- struct params *par = param;
- cpu_set_t mask;
- int policy = SCHED_FIFO;
- struct sched_param schedp;
- struct sembuf sb = { 0, 0, 0};
- sigset_t sigset;
-
- sigemptyset(&sigset);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- memset(&schedp, 0, sizeof(schedp));
- schedp.sched_priority = par->priority;
- sched_setscheduler(0, policy, &schedp);
-
- if (par->cpu != -1) {
- CPU_ZERO(&mask);
- CPU_SET(par->cpu, &mask);
- if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
- snprintf(par->error, sizeof(par->error),
- "WARNING: Could not set CPU affinity "
- "to CPU #%d\n", par->cpu);
- } else {
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- if (max_cpus > 1)
- mustgetcpu = 1;
- else
- par->cpu = 0;
- }
-
- if (!wasforked)
- par->tid = gettid();
-
- while (!par->shutdown) {
- if (par->sender) {
- sb.sem_num = SEM_WAIT_FOR_SENDER;
- sb.sem_op = SEM_UNLOCK;
- /*
- * Unlocking the semaphore:
- * Start of latency measurement ...
- */
- gettimeofday(&par->unblocked, NULL);
- semop(par->semid, &sb, 1);
- par->samples++;
- if(par->max_cycles && par->samples >= par->max_cycles)
- par->shutdown = 1;
-
- if (mustgetcpu) {
-#ifdef HAS_SCHED_GETCPU
- par->cpu = sched_getcpu();
-#else
- int c, s;
- s = getcpu(&c, NULL, NULL);
- par->cpu = (s == -1) ? s : c;
-#endif
- }
-
- sb.sem_num = SEM_WAIT_FOR_RECEIVER;
- sb.sem_op = SEM_LOCK;
- semop(par->semid, &sb, 1);
-
- sb.sem_num = SEM_WAIT_FOR_SENDER;
- sb.sem_op = SEM_LOCK;
- semop(par->semid, &sb, 1);
- } else {
- /* Receiver */
- struct params *neighbor;
-
- if (wasforked)
- neighbor = par + par->num_threads;
- else
- neighbor = par->neighbor;
-
- sb.sem_num = SEM_WAIT_FOR_SENDER;
- sb.sem_op = SEM_LOCK;
- semop(par->semid, &sb, 1);
-
- /*
- * ... We got the lock:
- * End of latency measurement
- */
- gettimeofday(&par->received, NULL);
- par->samples++;
- if (par->max_cycles && par->samples >= par->max_cycles)
- par->shutdown = 1;
-
- if (mustgetcpu) {
-#ifdef HAS_SCHED_GETCPU
- par->cpu = sched_getcpu();
-#else
- int c, s;
- s = getcpu(&c, NULL, NULL);
- par->cpu = (s == -1) ? s : c;
-#endif
- }
-
- timersub(&par->received, &neighbor->unblocked,
- &par->diff);
-
- if (par->diff.tv_usec < par->mindiff)
- par->mindiff = par->diff.tv_usec;
- if (par->diff.tv_usec > par->maxdiff)
- par->maxdiff = par->diff.tv_usec;
- par->sumdiff += (double) par->diff.tv_usec;
- if (par->tracelimit && par->maxdiff > par->tracelimit) {
- char tracing_enabled_file[MAX_PATH];
-
- strcpy(tracing_enabled_file, get_debugfileprefix());
- strcat(tracing_enabled_file, "tracing_enabled");
- int tracing_enabled =
- open(tracing_enabled_file, O_WRONLY);
- if (tracing_enabled >= 0) {
- write(tracing_enabled, "0", 1);
- close(tracing_enabled);
- } else
- snprintf(par->error, sizeof(par->error),
- "Could not access %s\n",
- tracing_enabled_file);
- par->shutdown = 1;
- neighbor->shutdown = 1;
- }
-
- sb.sem_num = SEM_WAIT_FOR_RECEIVER;
- sb.sem_op = SEM_UNLOCK;
- semop(par->semid, &sb, 1);
-
- nanosleep(&par->delay, NULL);
-
- sb.sem_num = SEM_WAIT_FOR_SENDER;
- sb.sem_op = SEM_UNLOCK;
- semop(par->semid, &sb, 1);
- }
- }
- if (par->sender) {
- sb.sem_num = SEM_WAIT_FOR_SENDER;
- sb.sem_op = SEM_UNLOCK;
- semop(par->semid, &sb, 1);
-
- sb.sem_num = SEM_WAIT_FOR_RECEIVER;
- sb.sem_op = SEM_UNLOCK;
- semop(par->semid, &sb, 1);
- }
- par->stopped = 1;
- return NULL;
-}
-
-
-union semun {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
-};
-
-
-static void display_help(void)
-{
- printf("svsematest V %1.2f\n", VERSION_STRING);
- puts("Usage: svsematest <options>");
- puts("Function: test SYSV semaphore latency");
- puts(
- "Options:\n"
- "-a [NUM] --affinity run thread #N on processor #N, if possible\n"
- " with NUM pin all threads to the processor NUM\n"
- "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
- "-d DIST --distance=DIST distance of thread intervals in us default=500\n"
- "-f --fork fork new processes instead of creating threads\n"
- "-i INTV --interval=INTV base interval of thread in us default=1000\n"
- "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
- "-p PRIO --prio=PRIO priority\n"
- "-t --threads one thread per available processor\n"
- "-t [NUM] --threads=NUM number of threads:\n"
- " without NUM, threads = max_cpus\n"
- " without -t default = 1\n");
- exit(1);
-}
-
-
-static int setaffinity = AFFINITY_UNSPECIFIED;
-static int affinity;
-static int priority;
-static int num_threads = 1;
-static int max_cycles;
-static int interval = 1000;
-static int distance = 500;
-
-static void process_options (int argc, char *argv[])
-{
- int error = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
- int thistracelimit = 0;
-
- for (;;) {
- int option_index = 0;
- /** Options for getopt */
- static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"fork", optional_argument, NULL, 'f'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"threads", optional_argument, NULL, 't'},
- {"help", no_argument, NULL, '?'},
- {NULL, 0, NULL, 0}
- };
- int c = getopt_long (argc, argv, "a::b:d:f::i:l:p:t::",
- long_options, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'a':
- if (optarg != NULL) {
- affinity = atoi(optarg);
- setaffinity = AFFINITY_SPECIFIED;
- } else if (optind<argc && atoi(argv[optind])) {
- affinity = atoi(argv[optind]);
- setaffinity = AFFINITY_SPECIFIED;
- } else {
- setaffinity = AFFINITY_USEALL;
- }
- break;
- case 'b': thistracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'f':
- if (optarg != NULL) {
- wasforked = 1;
- if (optarg[0] == 's')
- wasforked_sender = 1;
- else if (optarg[0] == 'r')
- wasforked_sender = 0;
- wasforked_threadno = atoi(optarg+1);
- } else
- mustfork = 1;
- break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 't':
- if (optarg != NULL)
- num_threads = atoi(optarg);
- else if (optind<argc && atoi(argv[optind]))
- num_threads = atoi(argv[optind]);
- else
- num_threads = max_cpus;
- break;
- case '?': error = 1; break;
- }
- }
-
- if (!wasforked) {
- if (setaffinity == AFFINITY_SPECIFIED) {
- if (affinity < 0)
- error = 1;
- if (affinity >= max_cpus) {
- fprintf(stderr, "ERROR: CPU #%d not found, "
- "only %d CPUs available\n",
- affinity, max_cpus);
- error = 1;
- }
- }
-
- if (num_threads < 1 || num_threads > 255)
- error = 1;
-
- if (priority < 0 || priority > 99)
- error = 1;
-
- tracelimit = thistracelimit;
- }
- if (error)
- display_help ();
-}
-
-
-static int volatile mustshutdown;
-
-static void sighand(int sig)
-{
- mustshutdown = 1;
-}
-
-int main(int argc, char *argv[])
-{
- char *myfile;
- int i, totalsize = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
- int oldsamples = 1;
- key_t key;
- union semun args;
- struct params *receiver = NULL;
- struct params *sender = NULL;
- sigset_t sigset;
- void *param = NULL;
- char f_opt[8];
- struct timespec launchdelay, maindelay;
-
- myfile = getenv("_");
- if (myfile == NULL)
- myfile = argv[0];
-
- process_options(argc, argv);
-
- if (check_privs())
- return 1;
-
- if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
- perror("mlockall");
- return 1;
- }
-
- if (mustfork) {
- int shmem;
-
- /*
- * In fork mode (-f), the shared memory contains two
- * subsequent arrays, receiver[num_threads] and
- * sender[num_threads].
- */
- totalsize = num_threads * sizeof(struct params) * 2;
-
- shm_unlink("/sigwaittest");
- shmem = shm_open("/sigwaittest", O_CREAT|O_EXCL|O_RDWR,
- S_IRUSR|S_IWUSR);
- if (shmem < 0) {
- fprintf(stderr, "Could not create shared memory\n");
- return 1;
- }
- ftruncate(shmem, totalsize);
- param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
- shmem, 0);
- if (param == MAP_FAILED) {
- fprintf(stderr, "Could not map shared memory\n");
- close(shmem);
- return 1;
- }
-
- receiver = (struct params *) param;
- sender = receiver + num_threads;
- } else if (wasforked) {
- struct stat buf;
- int shmem, totalsize, expect_totalsize;
-
- if (wasforked_threadno == -1 || wasforked_sender == -1) {
- fprintf(stderr, "Invalid fork option\n");
- return 1;
- }
- shmem = shm_open("/sigwaittest", O_RDWR, S_IRUSR|S_IWUSR);
- if (fstat(shmem, &buf)) {
- fprintf(stderr,
- "Could not determine shared memory size\n");
- close(shmem);
- return 1;
- }
- totalsize = buf.st_size;
- param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
- shmem, 0);
- close(shmem);
- if (param == MAP_FAILED) {
- fprintf(stderr, "Could not map shared memory\n");
- return 1;
- }
-
- receiver = (struct params *) param;
- expect_totalsize = receiver->num_threads *
- sizeof(struct params) * 2;
- if (totalsize != expect_totalsize) {
- fprintf(stderr, "Memory size problem (expected %d, "
- "found %d\n", expect_totalsize, totalsize);
- munmap(param, totalsize);
- return 1;
- }
- sender = receiver + receiver->num_threads;
- if (wasforked_sender)
- semathread(sender + wasforked_threadno);
- else
- semathread(receiver + wasforked_threadno);
- munmap(param, totalsize);
- return 0;
- }
-
- signal(SIGINT, sighand);
- signal(SIGTERM, sighand);
-
- sigemptyset(&sigset);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- if (!mustfork && !wasforked) {
- receiver = calloc(num_threads, sizeof(struct params));
- sender = calloc(num_threads, sizeof(struct params));
- if (receiver == NULL || sender == NULL)
- goto nomem;
- }
-
- launchdelay.tv_sec = 0;
- launchdelay.tv_nsec = 10000000; /* 10 ms */
-
- maindelay.tv_sec = 0;
- maindelay.tv_nsec = 50000000; /* 50 ms */
-
- for (i = 0; i < num_threads; i++) {
- struct sembuf sb = { 0, 0, 0};
-
- receiver[i].mindiff = UINT_MAX;
- receiver[i].maxdiff = 0;
- receiver[i].sumdiff = 0.0;
-
- if ((key = ftok(myfile, i)) == -1) {
- perror("ftok");
- goto nosem;
- }
-
- if ((receiver[i].semid = semget(key, 2, 0666 | IPC_CREAT)) == -1) {
- perror("semget");
- goto nosem;
- }
-
- args.val = 1;
- if (semctl(receiver[i].semid, SEM_WAIT_FOR_RECEIVER, SETVAL, args) == -1) {
- perror("semctl sema #0");
- goto nosem;
- }
-
- if (semctl(receiver[i].semid, SEM_WAIT_FOR_SENDER, SETVAL, args) == -1) {
- perror("semctl sema #1");
- goto nosem;
- }
-
- sb.sem_num = SEM_WAIT_FOR_RECEIVER;
- sb.sem_op = SEM_LOCK;
- semop(receiver[i].semid, &sb, 1);
-
- sb.sem_num = SEM_WAIT_FOR_SENDER;
- sb.sem_op = SEM_LOCK;
- semop(receiver[i].semid, &sb, 1);
-
- receiver[i].cpu = i;
- switch (setaffinity) {
- case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
- case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
- case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
- }
- receiver[i].priority = priority;
- receiver[i].tracelimit = tracelimit;
- if (priority > 0)
- priority--;
- receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
- receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
- interval += distance;
- receiver[i].max_cycles = max_cycles;
- receiver[i].sender = 0;
- receiver[i].neighbor = &sender[i];
- if (mustfork) {
- pid_t pid = fork();
- if (pid == -1) {
- fprintf(stderr, "Could not fork\n");
- return 1;
- } else if (pid == 0) {
- char *args[3];
-
- receiver[i].num_threads = num_threads;
- receiver[i].pid = getpid();
- sprintf(f_opt, "-fr%d", i);
- args[0] = argv[0];
- args[1] = f_opt;
- args[2] = NULL;
- execvp(args[0], args);
- fprintf(stderr,
- "Could not execute receiver child process "
- "#%d\n", i);
- }
- } else
- pthread_create(&receiver[i].threadid, NULL,
- semathread, &receiver[i]);
-
- nanosleep(&launchdelay, NULL);
-
- memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
- sender[i].sender = 1;
- sender[i].neighbor = &receiver[i];
- if (mustfork) {
- pid_t pid = fork();
- if (pid == -1) {
- fprintf(stderr, "Could not fork\n");
- return 1;
- } else if (pid == 0) {
- char *args[3];
-
- sender[i].num_threads = num_threads;
- sender[i].pid = getpid();
- sprintf(f_opt, "-fs%d", i);
- args[0] = argv[0];
- args[1] = f_opt;
- args[2] = NULL;
- execvp(args[0], args);
- fprintf(stderr,
- "Could not execute sender child process "
- "#%d\n", i);
- }
- } else
- pthread_create(&sender[i].threadid, NULL, semathread,
- &sender[i]);
- }
-
- while (!mustshutdown) {
- int printed;
- int errorlines = 0;
-
- for (i = 0; i < num_threads; i++)
- mustshutdown |= receiver[i].shutdown |
- sender[i].shutdown;
-
- if (receiver[0].samples > oldsamples || mustshutdown) {
- for (i = 0; i < num_threads; i++) {
- int receiver_pid, sender_pid;
-
- if (mustfork) {
- receiver_pid = receiver[i].pid;
- sender_pid = sender[i].pid;
- } else {
- receiver_pid = receiver[i].tid;
- sender_pid = sender[i].tid;
- }
- printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: "
- "ID%d, P%d, CPU%d, Cycles %d\n",
- i*2, receiver_pid, receiver[i].priority,
- receiver[i].cpu, receiver[i].delay.tv_nsec /
- 1000, i*2+1, sender_pid, sender[i].priority,
- sender[i].cpu, sender[i].samples);
- }
- for (i = 0; i < num_threads; i++) {
- if (receiver[i].mindiff == -1)
- printf("#%d -> #%d (not yet ready)\n",
- i*2+1, i*2);
- else
- printf("#%d -> #%d, Min %4d, Cur %4d, "
- "Avg %4d, Max %4d\n",
- i*2+1, i*2, receiver[i].mindiff,
- (int) receiver[i].diff.tv_usec,
- (int) ((receiver[i].sumdiff /
- receiver[i].samples) + 0.5),
- receiver[i].maxdiff);
- if (receiver[i].error[0] != '\0') {
- printf(receiver[i].error);
- receiver[i].error[0] = '\0';
- errorlines++;
- }
- if (sender[i].error[0] != '\0') {
- printf(sender[i].error);
- sender[i].error[0] = '\0';
- errorlines++;
- }
- }
- printed = 1;
- } else
- printed = 0;
-
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGTERM);
- sigaddset(&sigset, SIGINT);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- nanosleep(&maindelay, NULL);
-
- sigemptyset(&sigset);
- pthread_sigmask(SIG_SETMASK, &sigset, NULL);
-
- if (printed && !mustshutdown)
- printf("\033[%dA", num_threads*2 + errorlines);
- }
-
- for (i = 0; i < num_threads; i++) {
- receiver[i].shutdown = 1;
- sender[i].shutdown = 1;
- }
- nanosleep(&receiver[0].delay, NULL);
-
- for (i = 0; i < num_threads; i++) {
- if (!receiver[i].stopped) {
- if (mustfork)
- kill(receiver[i].pid, SIGTERM);
- else
- pthread_kill(receiver[i].threadid, SIGTERM);
- }
- if (!sender[i].stopped) {
- if (mustfork)
- kill(sender[i].pid, SIGTERM);
- else
- pthread_kill(sender[i].threadid, SIGTERM);
- }
- }
-
- nosem:
- for (i = 0; i < num_threads; i++)
- semctl(receiver[i].semid, -1, IPC_RMID);
-
- nomem:
- if (mustfork) {
- munmap(param, totalsize);
- shm_unlink("/sigwaittest");
- }
-
- return 0;
-}
+/*
+ * svsematest.c
+ *
+ * Copyright (C) 2009 Carsten Emde <C.Emde@osadl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#define __USE_GNU
+#include <fcntl.h>
+#include <getopt.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sched.h>
+#include <string.h>
+#include <time.h>
+#include <utmpx.h>
+
+#include <linux/unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sem.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include "rt-utils.h"
+
+#define HAS_SCHED_GETCPU
+
+#define gettid() syscall(__NR_gettid)
+#ifndef HAS_SCHED_GETCPU
+#define getcpu(cpu, node, cache) syscall(__NR_getcpu, cpu, node, cache)
+#endif
+
+#define USEC_PER_SEC 1000000
+
+#define SEM_WAIT_FOR_RECEIVER 0
+#define SEM_WAIT_FOR_SENDER 1
+
+#define SEM_LOCK -1
+#define SEM_UNLOCK 1
+
+enum {
+ AFFINITY_UNSPECIFIED,
+ AFFINITY_SPECIFIED,
+ AFFINITY_USEALL
+};
+
+struct params {
+ int num;
+ int num_threads;
+ int cpu;
+ int priority;
+ int affinity;
+ int semid;
+ int sender;
+ int samples;
+ int max_cycles;
+ int tracelimit;
+ int tid;
+ pid_t pid;
+ int shutdown;
+ int stopped;
+ struct timespec delay;
+ unsigned int mindiff, maxdiff;
+ double sumdiff;
+ struct timeval unblocked, received, diff;
+ pthread_t threadid;
+ struct params *neighbor;
+ char error[MAX_PATH * 2];
+};
+
+static int mustfork;
+static int wasforked;
+static int wasforked_sender = -1;
+static int wasforked_threadno = -1;
+static int tracelimit;
+
+void *semathread(void *param)
+{
+ int mustgetcpu = 0;
+ struct params *par = param;
+ cpu_set_t mask;
+ int policy = SCHED_FIFO;
+ struct sched_param schedp;
+ struct sembuf sb = { 0, 0, 0};
+ sigset_t sigset;
+
+ sigemptyset(&sigset);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ memset(&schedp, 0, sizeof(schedp));
+ schedp.sched_priority = par->priority;
+ sched_setscheduler(0, policy, &schedp);
+
+ if (par->cpu != -1) {
+ CPU_ZERO(&mask);
+ CPU_SET(par->cpu, &mask);
+ if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
+ snprintf(par->error, sizeof(par->error),
+ "WARNING: Could not set CPU affinity "
+ "to CPU #%d\n", par->cpu);
+ } else {
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ if (max_cpus > 1)
+ mustgetcpu = 1;
+ else
+ par->cpu = 0;
+ }
+
+ if (!wasforked)
+ par->tid = gettid();
+
+ while (!par->shutdown) {
+ if (par->sender) {
+ sb.sem_num = SEM_WAIT_FOR_SENDER;
+ sb.sem_op = SEM_UNLOCK;
+ /*
+ * Unlocking the semaphore:
+ * Start of latency measurement ...
+ */
+ gettimeofday(&par->unblocked, NULL);
+ semop(par->semid, &sb, 1);
+ par->samples++;
+ if(par->max_cycles && par->samples >= par->max_cycles)
+ par->shutdown = 1;
+
+ if (mustgetcpu) {
+#ifdef HAS_SCHED_GETCPU
+ par->cpu = sched_getcpu();
+#else
+ int c, s;
+ s = getcpu(&c, NULL, NULL);
+ par->cpu = (s == -1) ? s : c;
+#endif
+ }
+
+ sb.sem_num = SEM_WAIT_FOR_RECEIVER;
+ sb.sem_op = SEM_LOCK;
+ semop(par->semid, &sb, 1);
+
+ sb.sem_num = SEM_WAIT_FOR_SENDER;
+ sb.sem_op = SEM_LOCK;
+ semop(par->semid, &sb, 1);
+ } else {
+ /* Receiver */
+ struct params *neighbor;
+
+ if (wasforked)
+ neighbor = par + par->num_threads;
+ else
+ neighbor = par->neighbor;
+
+ sb.sem_num = SEM_WAIT_FOR_SENDER;
+ sb.sem_op = SEM_LOCK;
+ semop(par->semid, &sb, 1);
+
+ /*
+ * ... We got the lock:
+ * End of latency measurement
+ */
+ gettimeofday(&par->received, NULL);
+ par->samples++;
+ if (par->max_cycles && par->samples >= par->max_cycles)
+ par->shutdown = 1;
+
+ if (mustgetcpu) {
+#ifdef HAS_SCHED_GETCPU
+ par->cpu = sched_getcpu();
+#else
+ int c, s;
+ s = getcpu(&c, NULL, NULL);
+ par->cpu = (s == -1) ? s : c;
+#endif
+ }
+
+ timersub(&par->received, &neighbor->unblocked,
+ &par->diff);
+
+ if (par->diff.tv_usec < par->mindiff)
+ par->mindiff = par->diff.tv_usec;
+ if (par->diff.tv_usec > par->maxdiff)
+ par->maxdiff = par->diff.tv_usec;
+ par->sumdiff += (double) par->diff.tv_usec;
+ if (par->tracelimit && par->maxdiff > par->tracelimit) {
+ char tracing_enabled_file[MAX_PATH];
+
+ strcpy(tracing_enabled_file, get_debugfileprefix());
+ strcat(tracing_enabled_file, "tracing_enabled");
+ int tracing_enabled =
+ open(tracing_enabled_file, O_WRONLY);
+ if (tracing_enabled >= 0) {
+ write(tracing_enabled, "0", 1);
+ close(tracing_enabled);
+ } else
+ snprintf(par->error, sizeof(par->error),
+ "Could not access %s\n",
+ tracing_enabled_file);
+ par->shutdown = 1;
+ neighbor->shutdown = 1;
+ }
+
+ sb.sem_num = SEM_WAIT_FOR_RECEIVER;
+ sb.sem_op = SEM_UNLOCK;
+ semop(par->semid, &sb, 1);
+
+ nanosleep(&par->delay, NULL);
+
+ sb.sem_num = SEM_WAIT_FOR_SENDER;
+ sb.sem_op = SEM_UNLOCK;
+ semop(par->semid, &sb, 1);
+ }
+ }
+ if (par->sender) {
+ sb.sem_num = SEM_WAIT_FOR_SENDER;
+ sb.sem_op = SEM_UNLOCK;
+ semop(par->semid, &sb, 1);
+
+ sb.sem_num = SEM_WAIT_FOR_RECEIVER;
+ sb.sem_op = SEM_UNLOCK;
+ semop(par->semid, &sb, 1);
+ }
+ par->stopped = 1;
+ return NULL;
+}
+
+
+union semun {
+ int val; /* Value for SETVAL */
+ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* Array for GETALL, SETALL */
+ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
+};
+
+
+static void display_help(void)
+{
+ printf("svsematest V %1.2f\n", VERSION_STRING);
+ puts("Usage: svsematest <options>");
+ puts("Function: test SYSV semaphore latency");
+ puts(
+ "Options:\n"
+ "-a [NUM] --affinity run thread #N on processor #N, if possible\n"
+ " with NUM pin all threads to the processor NUM\n"
+ "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
+ "-d DIST --distance=DIST distance of thread intervals in us default=500\n"
+ "-f --fork fork new processes instead of creating threads\n"
+ "-i INTV --interval=INTV base interval of thread in us default=1000\n"
+ "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ "-p PRIO --prio=PRIO priority\n"
+ "-t --threads one thread per available processor\n"
+ "-t [NUM] --threads=NUM number of threads:\n"
+ " without NUM, threads = max_cpus\n"
+ " without -t default = 1\n");
+ exit(1);
+}
+
+
+static int setaffinity = AFFINITY_UNSPECIFIED;
+static int affinity;
+static int priority;
+static int num_threads = 1;
+static int max_cycles;
+static int interval = 1000;
+static int distance = 500;
+
+static void process_options (int argc, char *argv[])
+{
+ int error = 0;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ int thistracelimit = 0;
+
+ for (;;) {
+ int option_index = 0;
+ /** Options for getopt */
+ static struct option long_options[] = {
+ {"affinity", optional_argument, NULL, 'a'},
+ {"breaktrace", required_argument, NULL, 'b'},
+ {"distance", required_argument, NULL, 'd'},
+ {"fork", optional_argument, NULL, 'f'},
+ {"interval", required_argument, NULL, 'i'},
+ {"loops", required_argument, NULL, 'l'},
+ {"priority", required_argument, NULL, 'p'},
+ {"threads", optional_argument, NULL, 't'},
+ {"help", no_argument, NULL, '?'},
+ {NULL, 0, NULL, 0}
+ };
+ int c = getopt_long (argc, argv, "a::b:d:f::i:l:p:t::",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'a':
+ if (optarg != NULL) {
+ affinity = atoi(optarg);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else if (optind<argc && atoi(argv[optind])) {
+ affinity = atoi(argv[optind]);
+ setaffinity = AFFINITY_SPECIFIED;
+ } else {
+ setaffinity = AFFINITY_USEALL;
+ }
+ break;
+ case 'b': thistracelimit = atoi(optarg); break;
+ case 'd': distance = atoi(optarg); break;
+ case 'f':
+ if (optarg != NULL) {
+ wasforked = 1;
+ if (optarg[0] == 's')
+ wasforked_sender = 1;
+ else if (optarg[0] == 'r')
+ wasforked_sender = 0;
+ wasforked_threadno = atoi(optarg+1);
+ } else
+ mustfork = 1;
+ break;
+ case 'i': interval = atoi(optarg); break;
+ case 'l': max_cycles = atoi(optarg); break;
+ case 'p': priority = atoi(optarg); break;
+ case 't':
+ if (optarg != NULL)
+ num_threads = atoi(optarg);
+ else if (optind<argc && atoi(argv[optind]))
+ num_threads = atoi(argv[optind]);
+ else
+ num_threads = max_cpus;
+ break;
+ case '?': error = 1; break;
+ }
+ }
+
+ if (!wasforked) {
+ if (setaffinity == AFFINITY_SPECIFIED) {
+ if (affinity < 0)
+ error = 1;
+ if (affinity >= max_cpus) {
+ fprintf(stderr, "ERROR: CPU #%d not found, "
+ "only %d CPUs available\n",
+ affinity, max_cpus);
+ error = 1;
+ }
+ }
+
+ if (num_threads < 1 || num_threads > 255)
+ error = 1;
+
+ if (priority < 0 || priority > 99)
+ error = 1;
+
+ tracelimit = thistracelimit;
+ }
+ if (error)
+ display_help ();
+}
+
+
+static int volatile mustshutdown;
+
+static void sighand(int sig)
+{
+ mustshutdown = 1;
+}
+
+int main(int argc, char *argv[])
+{
+ char *myfile;
+ int i, totalsize = 0;
+ int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ int oldsamples = 1;
+ key_t key;
+ union semun args;
+ struct params *receiver = NULL;
+ struct params *sender = NULL;
+ sigset_t sigset;
+ void *param = NULL;
+ char f_opt[8];
+ struct timespec launchdelay, maindelay;
+
+ myfile = getenv("_");
+ if (myfile == NULL)
+ myfile = argv[0];
+
+ process_options(argc, argv);
+
+ if (check_privs())
+ return 1;
+
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
+ perror("mlockall");
+ return 1;
+ }
+
+ if (mustfork) {
+ int shmem;
+
+ /*
+ * In fork mode (-f), the shared memory contains two
+ * subsequent arrays, receiver[num_threads] and
+ * sender[num_threads].
+ */
+ totalsize = num_threads * sizeof(struct params) * 2;
+
+ shm_unlink("/sigwaittest");
+ shmem = shm_open("/sigwaittest", O_CREAT|O_EXCL|O_RDWR,
+ S_IRUSR|S_IWUSR);
+ if (shmem < 0) {
+ fprintf(stderr, "Could not create shared memory\n");
+ return 1;
+ }
+ ftruncate(shmem, totalsize);
+ param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
+ shmem, 0);
+ if (param == MAP_FAILED) {
+ fprintf(stderr, "Could not map shared memory\n");
+ close(shmem);
+ return 1;
+ }
+
+ receiver = (struct params *) param;
+ sender = receiver + num_threads;
+ } else if (wasforked) {
+ struct stat buf;
+ int shmem, totalsize, expect_totalsize;
+
+ if (wasforked_threadno == -1 || wasforked_sender == -1) {
+ fprintf(stderr, "Invalid fork option\n");
+ return 1;
+ }
+ shmem = shm_open("/sigwaittest", O_RDWR, S_IRUSR|S_IWUSR);
+ if (fstat(shmem, &buf)) {
+ fprintf(stderr,
+ "Could not determine shared memory size\n");
+ close(shmem);
+ return 1;
+ }
+ totalsize = buf.st_size;
+ param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
+ shmem, 0);
+ close(shmem);
+ if (param == MAP_FAILED) {
+ fprintf(stderr, "Could not map shared memory\n");
+ return 1;
+ }
+
+ receiver = (struct params *) param;
+ expect_totalsize = receiver->num_threads *
+ sizeof(struct params) * 2;
+ if (totalsize != expect_totalsize) {
+ fprintf(stderr, "Memory size problem (expected %d, "
+ "found %d\n", expect_totalsize, totalsize);
+ munmap(param, totalsize);
+ return 1;
+ }
+ sender = receiver + receiver->num_threads;
+ if (wasforked_sender)
+ semathread(sender + wasforked_threadno);
+ else
+ semathread(receiver + wasforked_threadno);
+ munmap(param, totalsize);
+ return 0;
+ }
+
+ signal(SIGINT, sighand);
+ signal(SIGTERM, sighand);
+
+ sigemptyset(&sigset);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ if (!mustfork && !wasforked) {
+ receiver = calloc(num_threads, sizeof(struct params));
+ sender = calloc(num_threads, sizeof(struct params));
+ if (receiver == NULL || sender == NULL)
+ goto nomem;
+ }
+
+ launchdelay.tv_sec = 0;
+ launchdelay.tv_nsec = 10000000; /* 10 ms */
+
+ maindelay.tv_sec = 0;
+ maindelay.tv_nsec = 50000000; /* 50 ms */
+
+ for (i = 0; i < num_threads; i++) {
+ struct sembuf sb = { 0, 0, 0};
+
+ receiver[i].mindiff = UINT_MAX;
+ receiver[i].maxdiff = 0;
+ receiver[i].sumdiff = 0.0;
+
+ if ((key = ftok(myfile, i)) == -1) {
+ perror("ftok");
+ goto nosem;
+ }
+
+ if ((receiver[i].semid = semget(key, 2, 0666 | IPC_CREAT)) == -1) {
+ perror("semget");
+ goto nosem;
+ }
+
+ args.val = 1;
+ if (semctl(receiver[i].semid, SEM_WAIT_FOR_RECEIVER, SETVAL, args) == -1) {
+ perror("semctl sema #0");
+ goto nosem;
+ }
+
+ if (semctl(receiver[i].semid, SEM_WAIT_FOR_SENDER, SETVAL, args) == -1) {
+ perror("semctl sema #1");
+ goto nosem;
+ }
+
+ sb.sem_num = SEM_WAIT_FOR_RECEIVER;
+ sb.sem_op = SEM_LOCK;
+ semop(receiver[i].semid, &sb, 1);
+
+ sb.sem_num = SEM_WAIT_FOR_SENDER;
+ sb.sem_op = SEM_LOCK;
+ semop(receiver[i].semid, &sb, 1);
+
+ receiver[i].cpu = i;
+ switch (setaffinity) {
+ case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
+ case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
+ case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
+ }
+ receiver[i].priority = priority;
+ receiver[i].tracelimit = tracelimit;
+ if (priority > 0)
+ priority--;
+ receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
+ receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
+ interval += distance;
+ receiver[i].max_cycles = max_cycles;
+ receiver[i].sender = 0;
+ receiver[i].neighbor = &sender[i];
+ if (mustfork) {
+ pid_t pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Could not fork\n");
+ return 1;
+ } else if (pid == 0) {
+ char *args[3];
+
+ receiver[i].num_threads = num_threads;
+ receiver[i].pid = getpid();
+ sprintf(f_opt, "-fr%d", i);
+ args[0] = argv[0];
+ args[1] = f_opt;
+ args[2] = NULL;
+ execvp(args[0], args);
+ fprintf(stderr,
+ "Could not execute receiver child process "
+ "#%d\n", i);
+ }
+ } else
+ pthread_create(&receiver[i].threadid, NULL,
+ semathread, &receiver[i]);
+
+ nanosleep(&launchdelay, NULL);
+
+ memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
+ sender[i].sender = 1;
+ sender[i].neighbor = &receiver[i];
+ if (mustfork) {
+ pid_t pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Could not fork\n");
+ return 1;
+ } else if (pid == 0) {
+ char *args[3];
+
+ sender[i].num_threads = num_threads;
+ sender[i].pid = getpid();
+ sprintf(f_opt, "-fs%d", i);
+ args[0] = argv[0];
+ args[1] = f_opt;
+ args[2] = NULL;
+ execvp(args[0], args);
+ fprintf(stderr,
+ "Could not execute sender child process "
+ "#%d\n", i);
+ }
+ } else
+ pthread_create(&sender[i].threadid, NULL, semathread,
+ &sender[i]);
+ }
+
+ while (!mustshutdown) {
+ int printed;
+ int errorlines = 0;
+
+ for (i = 0; i < num_threads; i++)
+ mustshutdown |= receiver[i].shutdown |
+ sender[i].shutdown;
+
+ if (receiver[0].samples > oldsamples || mustshutdown) {
+ for (i = 0; i < num_threads; i++) {
+ int receiver_pid, sender_pid;
+
+ if (mustfork) {
+ receiver_pid = receiver[i].pid;
+ sender_pid = sender[i].pid;
+ } else {
+ receiver_pid = receiver[i].tid;
+ sender_pid = sender[i].tid;
+ }
+ printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: "
+ "ID%d, P%d, CPU%d, Cycles %d\n",
+ i*2, receiver_pid, receiver[i].priority,
+ receiver[i].cpu, receiver[i].delay.tv_nsec /
+ 1000, i*2+1, sender_pid, sender[i].priority,
+ sender[i].cpu, sender[i].samples);
+ }
+ for (i = 0; i < num_threads; i++) {
+ if (receiver[i].mindiff == -1)
+ printf("#%d -> #%d (not yet ready)\n",
+ i*2+1, i*2);
+ else
+ printf("#%d -> #%d, Min %4d, Cur %4d, "
+ "Avg %4d, Max %4d\n",
+ i*2+1, i*2, receiver[i].mindiff,
+ (int) receiver[i].diff.tv_usec,
+ (int) ((receiver[i].sumdiff /
+ receiver[i].samples) + 0.5),
+ receiver[i].maxdiff);
+ if (receiver[i].error[0] != '\0') {
+ printf(receiver[i].error);
+ receiver[i].error[0] = '\0';
+ errorlines++;
+ }
+ if (sender[i].error[0] != '\0') {
+ printf(sender[i].error);
+ sender[i].error[0] = '\0';
+ errorlines++;
+ }
+ }
+ printed = 1;
+ } else
+ printed = 0;
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTERM);
+ sigaddset(&sigset, SIGINT);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ nanosleep(&maindelay, NULL);
+
+ sigemptyset(&sigset);
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL);
+
+ if (printed && !mustshutdown)
+ printf("\033[%dA", num_threads*2 + errorlines);
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ receiver[i].shutdown = 1;
+ sender[i].shutdown = 1;
+ }
+ nanosleep(&receiver[0].delay, NULL);
+
+ for (i = 0; i < num_threads; i++) {
+ if (!receiver[i].stopped) {
+ if (mustfork)
+ kill(receiver[i].pid, SIGTERM);
+ else
+ pthread_kill(receiver[i].threadid, SIGTERM);
+ }
+ if (!sender[i].stopped) {
+ if (mustfork)
+ kill(sender[i].pid, SIGTERM);
+ else
+ pthread_kill(sender[i].threadid, SIGTERM);
+ }
+ }
+
+ nosem:
+ for (i = 0; i < num_threads; i++)
+ semctl(receiver[i].semid, -1, IPC_RMID);
+
+ nomem:
+ if (mustfork) {
+ munmap(param, totalsize);
+ shm_unlink("/sigwaittest");
+ }
+
+ return 0;
+}