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>
This commit is contained in:
parent
ff74d0eb70
commit
1c3c9e34d6
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define VERSION "0.5"
|
||||
#define VERSION "0.5"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue