Xenomai、PREEMPT_RT、および Linux をそのまま Raspberry Pi でベンチマークしようとしていますが、問題が発生しています。
RT優先度と可変スリープ時間で、可変数のスレッドを作成しようとしています。スレッドの 1 つは RT 優先度が高く、GPIO から読み取り、別の GPIO に書き込み (オシロスコープなどでレイテンシを読み取るため)、RT 優先度が低い他のスレッドは算術演算のみを行います。GPIO はメモリにマップされるため、プロトコルのオーバーヘッドを回避できます。
このテストでは次のように考えていました。
問題は、一部のスレッドのみが作成されることです。また、スレッド数が多い場合は、メモリの問題が発生し、プロセスが停止します。それで、私はどのように進めるべきですか?コードが間違っていますか、時間が短すぎますか、それともスレッド数が多すぎますか?
これはコードです:
#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;
}