我正在尝试在 Raspberry Pi 中按原样对 Xenomai、PREEMPT_RT 和 Linux 进行基准测试,但遇到了一些麻烦。
我正在尝试创建可变数量的线程,具有 RT 优先级和可变的睡眠时间。其中一个线程具有较高的 RT 优先级,从 GPIO 读取,并写入另一个 GPIO(以读取示波器或类似设备上的延迟),而具有较低 RT 优先级的其他线程仅执行算术运算。GPIO 映射到内存上,因此可以避免协议开销。
我在这个测试中考虑: 1 线程 1 us 50 线程 10 us 100 线程 100 us 150 线程 1 ms 200 线程 10 ms 250 线程 100 ms
问题是只创建了一些线程。当线程数很高时,就会出现内存问题并且进程停止。那么,我应该如何进行呢?是代码不对,是时间太短,还是线程数太高?
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
void *gpio_map;
volatile unsigned *gpio;
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
#define GPIO_READ(g) (*(gpio + 13)&(1<<(g)))>>(g)
void *default_thread(void *arg)
{
struct timespec delay;
int digits = 2000;
int arr[digits + 1];
int i, j, sum, carry;
unsigned long over;
delay.tv_sec = 0;
delay.tv_nsec = *(long *)arg;
while(1)
{
carry = 0;
for (i = digits; i > 0; i-= 14) {
sum = 0;
for (j = i; j > 0; --j) {
sum = sum * j + 10000;
sum %= (j * 2 - 1);
}
carry = sum % 10000;
}
clock_nanosleep(CLOCK_REALTIME, 0, &delay, NULL);
}
return NULL;
}
void *productive_thread(void *arg)
{
struct timespec delay, sleep;
unsigned long over;
delay.tv_sec = 0;
delay.tv_nsec = 10000; // 10 usec
sleep.tv_sec = 0;
sleep.tv_nsec = *(long *)arg;
while(1)
{
while(GPIO_READ(4) != 1);
GPIO_SET = 1 << 17;
clock_nanosleep(CLOCK_REALTIME, 0, &sleep, NULL);
GPIO_CLR = 1 << 17;
clock_nanosleep(CLOCK_REALTIME, 0, &sleep, NULL);
}
return NULL;
}
int main(int argc, char* argv[]) {
int n,i,t,fd;
pthread_t *threads;
struct sched_param prio1, prio2;
struct timespec time, interval;
mlockall(MCL_CURRENT | MCL_FUTURE);
if (argc != 5)
{
printf ("Usage: %s n t p1 p2\n", argv[0]);
printf("n: number of threads\n");
printf("t: time period in ns (less than 1s)\n");
printf("p1: priority of the gpio task from %d to %d\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
printf("p2: priority of the sytem load tasks from %d to %d\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
exit(1);
}
// Use GPIO PB31 (A1) as input, and PB13 (A2) as output.
fd = open("/dev/mem", O_RDWR|O_SYNC);
if(fd < 0)
exit(1);
gpio_map = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
if(gpio_map == MAP_FAILED)
exit(1);
close(fd);
gpio = (volatile unsigned *)gpio_map;
INP_GPIO(4);
INP_GPIO(17);
OUT_GPIO(17);
n=atoi(argv[1]);
t = atoi(argv[2]);
// Set priorites
prio1.sched_priority = atoi(argv[3]);
prio2.sched_priority = atoi(argv[4]);
// Initialize thread vector
threads=(pthread_t *)malloc(n*sizeof(pthread_t));
// Start threads
pthread_create(&threads[0], NULL, productive_thread, &t);
pthread_setschedparam(threads[0], SCHED_FIFO, &prio1);
for (i=1; i<n; i++)
{
pthread_create(&threads[i], NULL, default_thread, &t);
//pthread_setschedparam(threads[i], SCHED_FIFO, &prio2);
}
// Wait for ending
for (i=0; i<n; i++)
{
pthread_join(threads[i],NULL);
}
munmap(gpio_map, BLOCK_SIZE);
return 1;
}