2010-08-15 13:58:08 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
|
|
|
* RWTH Aachen University
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
* This file is part of MetalSVM.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <metalsvm/stddef.h>
|
|
|
|
#include <metalsvm/stdio.h>
|
|
|
|
#include <metalsvm/time.h>
|
|
|
|
#include <metalsvm/tasks.h>
|
|
|
|
#include <metalsvm/semaphore.h>
|
|
|
|
#include <metalsvm/mailbox.h>
|
|
|
|
#include <metalsvm/syscall.h>
|
2011-08-15 07:16:12 -07:00
|
|
|
#include <metalsvm/vma.h>
|
2011-08-16 03:29:54 -07:00
|
|
|
#include <metalsvm/page.h>
|
2012-07-15 06:06:38 -07:00
|
|
|
#ifdef CONFIG_LWIP
|
|
|
|
#include <lwip/opt.h>
|
|
|
|
#endif
|
2011-04-24 07:27:27 -07:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
#include <asm/icc.h>
|
2011-06-27 12:31:06 +02:00
|
|
|
#include <asm/RCCE.h>
|
|
|
|
#include <asm/RCCE_lib.h>
|
|
|
|
#include <asm/iRCCE.h>
|
|
|
|
#include <asm/iRCCE_lib.h>
|
|
|
|
#include <asm/SCC_API.h>
|
2011-09-18 21:30:00 +02:00
|
|
|
#include <asm/svm.h>
|
2011-04-24 07:27:27 -07:00
|
|
|
#endif
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2012-07-16 21:55:42 +02:00
|
|
|
#include "tests.h"
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2011-10-21 14:16:39 -07:00
|
|
|
int laplace(void* arg);
|
2011-12-21 05:22:16 -08:00
|
|
|
int jacobi(void* arg);
|
2013-11-14 13:17:14 +01:00
|
|
|
int memory(void* arg);
|
2012-07-16 21:55:42 +02:00
|
|
|
void echo_init(void);
|
|
|
|
void netio_init(void);
|
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
#if defined(START_CONSUMER_PRODUCER) || defined(START_CHIEFTEST)
|
2012-07-16 21:55:42 +02:00
|
|
|
static sem_t consuming, producing;
|
|
|
|
static mailbox_int32_t mbox;
|
|
|
|
static int val = 0;
|
2011-10-21 14:16:39 -07:00
|
|
|
|
2011-08-01 22:01:39 +02:00
|
|
|
static int consumer(void* arg)
|
2010-08-15 13:58:08 +00:00
|
|
|
{
|
|
|
|
int i, m = 0;
|
|
|
|
|
|
|
|
for(i=0; i<5; i++) {
|
2011-08-06 15:55:34 +02:00
|
|
|
sem_wait(&consuming, 0);
|
2012-07-16 21:55:42 +02:00
|
|
|
kprintf("Consumer got %d\n", val);
|
|
|
|
val = 0;
|
|
|
|
sem_post(&producing);
|
|
|
|
}
|
2010-08-15 13:58:08 +00:00
|
|
|
|
|
|
|
for(i=0; i<5; i++) {
|
2011-08-06 15:55:34 +02:00
|
|
|
mailbox_int32_fetch(&mbox, &m, 0);
|
2010-08-15 13:58:08 +00:00
|
|
|
kprintf("Got mail %d\n", m);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-01 22:01:39 +02:00
|
|
|
static int producer(void* arg)
|
2010-08-15 13:58:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int mail[5] = {1, 2, 3, 4, 5};
|
|
|
|
|
|
|
|
for(i=0; i<5; i++) {
|
2011-08-06 15:55:34 +02:00
|
|
|
sem_wait(&producing, 0);
|
2010-08-15 13:58:08 +00:00
|
|
|
kprintf("Produce value: current val %d\n", val);
|
|
|
|
val = 42;
|
|
|
|
sem_post(&consuming);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<5; i++) {
|
|
|
|
//kprintf("Send mail %d\n", mail[i]);
|
|
|
|
mailbox_int32_post(&mbox, mail[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-09-16 16:48:55 +02:00
|
|
|
|
|
|
|
static int producer_consumer(void)
|
|
|
|
{
|
|
|
|
tid_t id1, id2, ret;
|
|
|
|
int result1, result2, result;
|
|
|
|
|
|
|
|
create_kernel_task(&id1, producer, NULL, NORMAL_PRIO);
|
|
|
|
create_kernel_task(&id2, consumer, NULL, NORMAL_PRIO);
|
|
|
|
|
|
|
|
ret = wait(&result);
|
|
|
|
if (ret == id1) result1 = result;
|
|
|
|
else result2 = result;
|
|
|
|
|
|
|
|
ret = wait(&result);
|
|
|
|
if (ret == id1) result1 = result;
|
|
|
|
else result2 = result;
|
|
|
|
|
|
|
|
return result1 || result2;
|
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
#if defined(START_FOO) || defined(START_JOIN_TEST) || defined(START_CHIEFTEST)
|
2011-08-01 22:01:39 +02:00
|
|
|
static int foo(void* arg)
|
2010-08-15 13:58:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!arg)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for(i=0; i<5; i++) {
|
2012-07-16 21:55:42 +02:00
|
|
|
kprintf("Message from core %u: %s\n", CORE_ID, (char*) arg);
|
2010-08-15 13:58:08 +00:00
|
|
|
sleep(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 42;
|
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2012-09-17 14:58:58 +02:00
|
|
|
#if (defined(START_MAIL_PING) || defined(START_CHIEFTEST)) && defined(CONFIG_ROCKCREEK)
|
2011-08-18 01:29:55 -07:00
|
|
|
static int mail_ping(void* arg) {
|
2011-12-04 04:48:52 -08:00
|
|
|
int i;
|
|
|
|
|
2011-12-21 05:22:16 -08:00
|
|
|
//for(i=0; i<5; ++i)
|
|
|
|
// icc_mail_ping();
|
2011-12-14 01:39:55 -08:00
|
|
|
for(i=0; i<5; ++i)
|
2011-12-13 03:39:21 -08:00
|
|
|
icc_mail_ping_irq();
|
2011-12-14 01:39:55 -08:00
|
|
|
//icc_mail_ping_jitter();
|
2011-08-29 01:49:59 -07:00
|
|
|
//icc_irq_ping();
|
2011-11-07 13:01:57 -08:00
|
|
|
//icc_mail_datarates();
|
2011-08-29 01:49:59 -07:00
|
|
|
//icc_halt();
|
2011-04-24 07:27:27 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2011-04-24 07:27:27 -07:00
|
|
|
|
2012-07-16 21:55:42 +02:00
|
|
|
#ifdef START_MAIL_NOISE
|
2011-08-20 07:09:37 -07:00
|
|
|
static int mail_noise(void*arg) {
|
2011-07-18 01:14:18 -07:00
|
|
|
icc_mail_noise(); // generate noise in the mesh
|
2011-04-24 07:27:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
|
|
|
|
2012-09-17 14:58:58 +02:00
|
|
|
#if (defined(START_SVM_TEST) || defined(START_CHIEFTEST)) && defined(CONFIG_ROCKCREEK)
|
2011-08-15 07:16:12 -07:00
|
|
|
|
2011-11-10 01:09:31 -08:00
|
|
|
/* N has to be multiple of UEs */
|
|
|
|
|
2011-12-05 02:40:53 -08:00
|
|
|
#define N 1024
|
|
|
|
//#define N 512
|
2011-12-04 04:48:52 -08:00
|
|
|
//#define N 128
|
|
|
|
|
|
|
|
//#define SVM_TYPE SVM_STRONG
|
|
|
|
#define SVM_TYPE SVM_LAZYRELEASE
|
2011-08-15 07:16:12 -07:00
|
|
|
|
|
|
|
volatile static int* A[N];
|
|
|
|
volatile static int* B[N];
|
|
|
|
volatile static int* C[N];
|
|
|
|
|
2011-08-29 06:10:53 -07:00
|
|
|
#if 0
|
|
|
|
#define GET_B(i, j) B[i][j]
|
|
|
|
#else
|
|
|
|
#define GET_B(i, j) B[j][i]
|
|
|
|
#endif
|
|
|
|
|
2011-08-15 07:16:12 -07:00
|
|
|
static int svm_test(void *arg)
|
|
|
|
{
|
2011-08-19 00:11:36 -07:00
|
|
|
uint64_t start, end;
|
2011-08-20 01:03:18 -07:00
|
|
|
uint32_t i, j, k;
|
2011-11-07 07:39:08 -08:00
|
|
|
|
2011-12-05 02:40:53 -08:00
|
|
|
uint32_t svm_flags;
|
2011-11-07 07:39:08 -08:00
|
|
|
|
2011-08-15 07:16:12 -07:00
|
|
|
int my_ue, num_ues;
|
2011-08-29 20:33:45 -07:00
|
|
|
register int tmp;
|
2011-08-15 07:16:12 -07:00
|
|
|
|
2011-11-08 09:22:49 -08:00
|
|
|
kputs("Start SVM test...\n");
|
|
|
|
|
2011-08-15 07:16:12 -07:00
|
|
|
RCCE_barrier(&RCCE_COMM_WORLD);
|
|
|
|
my_ue = RCCE_ue();
|
|
|
|
num_ues = RCCE_num_ues();
|
|
|
|
|
2012-07-15 05:55:53 -07:00
|
|
|
#if 1
|
2011-08-22 13:15:49 -07:00
|
|
|
if (!my_ue) {
|
|
|
|
// allocate and initialize SVM region
|
|
|
|
A[0] = (int*) kmalloc(3*N*N*sizeof(int));
|
2012-09-17 14:51:10 +02:00
|
|
|
if (!A[0])
|
|
|
|
return 1; // Let the others hang in the barrier. People will notice that things went wrong.
|
2011-08-22 13:15:49 -07:00
|
|
|
memset((void*) A[0], 0x00, 3*N*N*sizeof(int));
|
|
|
|
|
|
|
|
// initialize matrices
|
|
|
|
for(i=0; i<N; i++) {
|
|
|
|
A[i] = A[0] + i*N;
|
|
|
|
B[i] = A[0] + (i*N + N*N);
|
|
|
|
C[i] = A[0] + (i*N + 2*N*N);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<N; i++) {
|
|
|
|
A[i][i] = 1;
|
|
|
|
for(j=0; j<N; j++)
|
2011-08-29 06:10:53 -07:00
|
|
|
GET_B(i,j) = i+j;
|
2011-08-22 13:15:49 -07:00
|
|
|
}
|
|
|
|
|
2012-09-15 18:20:31 +02:00
|
|
|
kputs("Start sequential calculation...\n");
|
2011-08-22 13:15:49 -07:00
|
|
|
|
|
|
|
start = rdtsc();
|
|
|
|
start = rdtsc();
|
|
|
|
|
|
|
|
// start calculation
|
2011-08-29 20:33:45 -07:00
|
|
|
for(i=0; i<N; i++) {
|
|
|
|
for(j=0; j<N; j++) {
|
|
|
|
tmp = C[i][j];
|
2011-08-22 13:15:49 -07:00
|
|
|
for(k=0; k<N; k++)
|
2011-08-29 06:10:53 -07:00
|
|
|
C[i][j] += A[i][k] * GET_B(k,j);
|
2011-08-29 20:33:45 -07:00
|
|
|
C[i][j] = tmp;
|
|
|
|
}
|
|
|
|
}
|
2011-08-22 13:15:49 -07:00
|
|
|
|
|
|
|
end = rdtsc();
|
|
|
|
|
2011-08-29 01:49:59 -07:00
|
|
|
kprintf("Calculation time (seq): %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start);
|
2011-08-22 13:15:49 -07:00
|
|
|
kfree(A[0], 3*N*N*sizeof(int));
|
|
|
|
}
|
|
|
|
|
|
|
|
RCCE_barrier(&RCCE_COMM_WORLD);
|
|
|
|
#endif
|
|
|
|
|
2011-08-15 07:16:12 -07:00
|
|
|
// allocate and initialize SVM region
|
2011-11-07 07:39:08 -08:00
|
|
|
|
2011-12-04 04:48:52 -08:00
|
|
|
svm_flags = SVM_TYPE;
|
|
|
|
if (svm_flags & SVM_LAZYRELEASE)
|
|
|
|
kputs("Use Lazy Release consistency!\n");
|
|
|
|
else
|
|
|
|
kputs("Use Strong Release consistency!\n");
|
2011-11-07 07:39:08 -08:00
|
|
|
|
2011-11-10 01:09:31 -08:00
|
|
|
A[0] = (int*) svm_malloc(3*N*N*sizeof(int), svm_flags);
|
2012-09-17 14:51:10 +02:00
|
|
|
if (!A[0])
|
|
|
|
return 1;
|
2011-11-07 07:39:08 -08:00
|
|
|
|
2012-07-15 05:55:53 -07:00
|
|
|
#if 1
|
2011-11-10 01:09:31 -08:00
|
|
|
if (!my_ue)
|
2011-08-15 07:16:12 -07:00
|
|
|
memset((void*) A[0], 0x00, 3*N*N*sizeof(int));
|
2011-12-13 05:40:59 -08:00
|
|
|
#endif
|
2011-08-15 07:16:12 -07:00
|
|
|
|
|
|
|
// initialize matrices
|
|
|
|
for(i=0; i<N; i++) {
|
|
|
|
A[i] = A[0] + i*N;
|
2011-08-19 00:11:36 -07:00
|
|
|
B[i] = A[0] + (i*N + N*N);
|
|
|
|
C[i] = A[0] + (i*N + 2*N*N);
|
2011-08-15 07:16:12 -07:00
|
|
|
}
|
2011-12-13 05:40:59 -08:00
|
|
|
|
|
|
|
#if 1
|
|
|
|
// distriubute page frames over all MC via affinity on first touch
|
|
|
|
for(i=my_ue*(N/num_ues); i<(my_ue+1)*(N/num_ues); i++) {
|
|
|
|
memset(A[i], 0x00, N*sizeof(int));
|
|
|
|
memset(B[i], 0x00, N*sizeof(int));
|
|
|
|
memset(C[i], 0x00, N*sizeof(int));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
|
2011-08-15 07:16:12 -07:00
|
|
|
if (!my_ue) {
|
|
|
|
for(i=0; i<N; i++) {
|
|
|
|
A[i][i] = 1;
|
|
|
|
for(j=0; j<N; j++)
|
2011-08-29 06:10:53 -07:00
|
|
|
GET_B(i,j) = i+j;
|
2011-08-15 07:16:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-10 01:09:31 -08:00
|
|
|
svm_barrier(svm_flags);
|
2011-08-15 07:16:12 -07:00
|
|
|
|
2011-08-19 00:11:36 -07:00
|
|
|
kputs("Start parallel calculation...\n");
|
|
|
|
|
2011-12-13 05:40:59 -08:00
|
|
|
start = rdtsc();
|
2011-08-19 00:11:36 -07:00
|
|
|
start = rdtsc();
|
2011-08-16 03:29:54 -07:00
|
|
|
|
2011-08-22 22:13:06 -07:00
|
|
|
// Now, we need only read access on A and B
|
2011-12-13 05:40:59 -08:00
|
|
|
//change_page_permissions((size_t) A[0], (size_t) (A[0]+2*N*N), VMA_CACHEABLE|VMA_READ);
|
|
|
|
//svm_barrier(SVM_TYPE);
|
2011-08-22 22:13:06 -07:00
|
|
|
|
2011-08-15 07:16:12 -07:00
|
|
|
// start calculation
|
2011-08-29 20:33:45 -07:00
|
|
|
for(i=my_ue*(N/num_ues); i<(my_ue+1)*(N/num_ues); i++) {
|
|
|
|
for(j=0; j<N; j++) {
|
|
|
|
tmp = C[i][j];
|
2011-08-15 07:16:12 -07:00
|
|
|
for(k=0; k<N; k++)
|
2011-08-29 20:33:45 -07:00
|
|
|
tmp += A[i][k] * GET_B(k,j);
|
|
|
|
C[i][j] = tmp;
|
|
|
|
}
|
|
|
|
}
|
2011-08-19 00:11:36 -07:00
|
|
|
|
2011-12-04 04:48:52 -08:00
|
|
|
svm_barrier(SVM_TYPE);
|
2011-11-10 01:09:31 -08:00
|
|
|
|
2011-08-22 13:15:49 -07:00
|
|
|
end = rdtsc();
|
2011-08-19 00:11:36 -07:00
|
|
|
|
|
|
|
kputs("Check results...\n");
|
|
|
|
|
2012-09-17 14:51:10 +02:00
|
|
|
uint32_t err = 0; // Be paranoid for a test case. return != 0 if calculation was not correct.
|
2011-08-19 00:11:36 -07:00
|
|
|
if (!my_ue) {
|
2011-08-23 07:58:35 -07:00
|
|
|
svm_invalidate();
|
|
|
|
for(i=0; (i<N) && (err < 32); i++) {
|
|
|
|
for(j=0; (j<N) && (err < 32); j++) {
|
2011-08-19 00:11:36 -07:00
|
|
|
if (C[i][j] != i+j) {
|
|
|
|
err++;
|
2011-12-13 05:40:59 -08:00
|
|
|
kprintf("Wrong value at C[%u][%u] = %u, B[%u][%u] = %u = %u\n", i, j, C[i][j], i, j, GET_B(i,j), B[i][j]);
|
2011-08-19 00:11:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-08-15 07:16:12 -07:00
|
|
|
|
2011-12-04 04:48:52 -08:00
|
|
|
svm_barrier(SVM_TYPE);
|
2011-08-15 07:16:12 -07:00
|
|
|
|
2011-08-29 01:49:59 -07:00
|
|
|
kprintf("Calculation time (par): %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start);
|
2011-08-16 16:08:04 -07:00
|
|
|
|
2011-11-10 01:09:31 -08:00
|
|
|
svm_free((void*) A[0], 3*N*sizeof(int));
|
2011-08-15 07:16:12 -07:00
|
|
|
|
2011-08-22 22:13:06 -07:00
|
|
|
svm_statistics();
|
|
|
|
|
2012-09-17 14:51:10 +02:00
|
|
|
return err;
|
2011-08-15 07:16:12 -07:00
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2011-12-05 02:40:53 -08:00
|
|
|
|
2012-09-17 14:58:58 +02:00
|
|
|
#if (defined(START_SVM_BENCH) || defined(START_CHIEFTEST)) && defined(CONFIG_ROCKCREEK)
|
2011-12-05 02:40:53 -08:00
|
|
|
static int svm_bench(void *arg)
|
|
|
|
{
|
|
|
|
volatile uint32_t* array = NULL;
|
|
|
|
uint64_t start, end;
|
|
|
|
uint32_t i;
|
|
|
|
const uint32_t size = N*N*sizeof(uint32_t);
|
|
|
|
const uint32_t svm_flags = SVM_TYPE;
|
|
|
|
|
|
|
|
if (RCCE_IAM > 1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (svm_flags & SVM_LAZYRELEASE)
|
|
|
|
kputs("Use Lazy Release consistency!\n");
|
|
|
|
else
|
|
|
|
kputs("Use Strong Release consistency!\n");
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
|
|
|
|
start = rdtsc();
|
|
|
|
start = rdtsc();
|
|
|
|
array = (volatile uint32_t*) svm_malloc(size, svm_flags);
|
2012-09-17 14:51:10 +02:00
|
|
|
if (!array)
|
|
|
|
return -1;
|
2011-12-05 02:40:53 -08:00
|
|
|
end = rdtsc();
|
|
|
|
|
|
|
|
if (BUILTIN_EXPECT(!array, 0)) {
|
|
|
|
kprintf("Out of memory\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
kprintf("Time to allocate %u Bytes: %llu usec (%llu ticks)\n", size, (end-start)/get_cpu_frequency(), end-start);
|
|
|
|
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
if (!RCCE_IAM) {
|
|
|
|
start = rdtsc();
|
2012-09-15 18:20:31 +02:00
|
|
|
// The pages are created by touching them for the first time.
|
2011-12-05 02:40:53 -08:00
|
|
|
for(i=0; i<size/sizeof(uint32_t); i+=PAGE_SIZE/sizeof(uint32_t))
|
|
|
|
array[i] = 0;
|
|
|
|
end = rdtsc();
|
|
|
|
|
|
|
|
kprintf("Time to create %u page frames: %llu usec (%llu ticks)\n", size >> PAGE_SHIFT, (end-start)/get_cpu_frequency(), end-start);
|
|
|
|
}
|
|
|
|
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
if (RCCE_IAM) {
|
|
|
|
start = rdtsc();
|
2012-09-15 18:20:31 +02:00
|
|
|
// Touching these pages from another core means moving them
|
|
|
|
// to another owner as well as mapping them in the other core's
|
|
|
|
// memory space.
|
2011-12-05 02:40:53 -08:00
|
|
|
for(i=0; i<size/sizeof(uint32_t); i+=PAGE_SIZE/sizeof(uint32_t))
|
|
|
|
array[i] = 1;
|
|
|
|
end = rdtsc();
|
|
|
|
|
|
|
|
kprintf("Time to map %u page frames: %llu usec (%llu ticks)\n", size >> PAGE_SHIFT, (end-start)/get_cpu_frequency(), end-start);
|
|
|
|
}
|
|
|
|
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
if (!RCCE_IAM) {
|
|
|
|
start = rdtsc();
|
2012-09-15 18:20:31 +02:00
|
|
|
// Touching the pages from the first core again only involves
|
|
|
|
// moving the pages without the need to map them again.
|
2011-12-05 02:40:53 -08:00
|
|
|
for(i=0; i<size/sizeof(uint32_t); i+=PAGE_SIZE/sizeof(uint32_t))
|
|
|
|
array[i] = 0;
|
|
|
|
end = rdtsc();
|
|
|
|
|
|
|
|
kprintf("Time to get access permissions of %u page frames: %llu usec (%llu ticks)\n", size >> PAGE_SHIFT, (end-start)/get_cpu_frequency(), end-start);
|
|
|
|
}
|
|
|
|
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
start = rdtsc();
|
|
|
|
change_page_permissions((size_t) array, size, VMA_CACHEABLE|VMA_READ);
|
|
|
|
end = rdtsc();
|
|
|
|
kprintf("Time to change access permissions of %u page frames: %llu usec (%llu ticks)\n", size >> PAGE_SHIFT, (end-start)/get_cpu_frequency(), end-start);
|
|
|
|
|
|
|
|
svm_barrier(svm_flags);
|
|
|
|
svm_free((void*) array, N*N*sizeof(uint32_t));
|
|
|
|
|
|
|
|
svm_statistics();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-09-17 14:51:10 +02:00
|
|
|
|
|
|
|
static int testcase_svm_bench(void)
|
|
|
|
{
|
|
|
|
if (RCCE_IAM > 1) {
|
|
|
|
int i;
|
|
|
|
for (i=0; i < 6; i++)
|
|
|
|
// Need as many barriers for the other cores as they occur in the benchmark.
|
|
|
|
svm_barrier(SVM_TYPE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return svm_bench(NULL);
|
|
|
|
}
|
2011-04-24 07:27:27 -07:00
|
|
|
#endif
|
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
#if defined(START_JOIN_TEST) || defined(START_CHIEFTEST)
|
2011-08-01 22:01:39 +02:00
|
|
|
static int join_test(void* arg)
|
2010-08-15 13:58:08 +00:00
|
|
|
{
|
2011-03-02 13:49:36 +01:00
|
|
|
tid_t id, ret;
|
|
|
|
int result = -1234;
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2011-09-22 10:58:54 +02:00
|
|
|
create_kernel_task(&id, foo, "Hello from foo2", HIGH_PRIO-1);
|
2011-03-02 13:49:36 +01:00
|
|
|
|
|
|
|
kprintf("Wait for child %u\n", id);
|
|
|
|
do {
|
|
|
|
ret = wait(&result);
|
|
|
|
} while(ret != id);
|
|
|
|
|
|
|
|
kprintf("Child %u finished: result = %d\n", id, result);
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
return result != 42;
|
2010-08-15 13:58:08 +00:00
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2012-07-16 21:55:42 +02:00
|
|
|
#ifdef START_PI
|
2011-10-07 16:03:11 +02:00
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979323846264338327950288 /* pi */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int pi(void* arg)
|
|
|
|
{
|
|
|
|
double x, sum, step;
|
|
|
|
int i, num_steps = 100000000;
|
|
|
|
|
|
|
|
sum = 0.0;
|
|
|
|
step = 1.0 / (double)num_steps;
|
|
|
|
|
|
|
|
for (i = 0; i < num_steps; i++) {
|
|
|
|
x = (i + 0.5) * step;
|
|
|
|
sum += 4.0 / (1.0 + x * x);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = M_PI - sum * step;
|
|
|
|
x *= 10000.0;
|
|
|
|
|
|
|
|
kprintf("Distance to PI = %u/10000\n", (uint32_t) x);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2011-10-07 16:03:11 +02:00
|
|
|
|
2012-07-16 21:55:42 +02:00
|
|
|
#ifdef START_MEASURE_CTX_SWITCH
|
2012-04-15 19:40:51 +02:00
|
|
|
#define REPS 10000
|
|
|
|
|
|
|
|
volatile uint64_t t1, t2;
|
|
|
|
volatile int stop = !!0;
|
|
|
|
volatile int sid = 0;
|
|
|
|
|
|
|
|
static int measure_ctx_switch(void* arg)
|
2012-04-09 20:01:39 +02:00
|
|
|
{
|
2012-04-15 19:40:51 +02:00
|
|
|
int id = !!(int)arg;
|
|
|
|
int oid = !id;
|
|
|
|
uint64_t freq = get_cpu_frequency() *1000 *1000;
|
|
|
|
uint64_t diff, min = (uint64_t)-1, max = 0, avg = 0;
|
|
|
|
int i;
|
|
|
|
uint32_t a=0,b,c,d;
|
|
|
|
|
|
|
|
// Size of a timeslice in ticks
|
|
|
|
uint64_t timeslice = freq / TIMER_FREQ;
|
|
|
|
|
|
|
|
kprintf("ID: %d, ", id);
|
2012-05-21 15:04:05 +02:00
|
|
|
kprintf("Measuring SW task switching.\n");
|
2012-04-09 20:01:39 +02:00
|
|
|
|
2012-04-15 19:40:51 +02:00
|
|
|
for (i=0; i < REPS && stop == 0; i++) {
|
2012-07-16 21:55:42 +02:00
|
|
|
while(id == sid && stop == 0) {
|
|
|
|
t2 = rdtsc();
|
2012-09-15 18:20:31 +02:00
|
|
|
// Calling rdtsc that often it is better
|
|
|
|
// to serialize the calls in the pipeline.
|
2012-07-16 21:55:42 +02:00
|
|
|
cpuid(0,&a,&b,&c,&d);
|
|
|
|
}
|
|
|
|
|
|
|
|
cpuid(0,&a,&b,&c,&d);
|
|
|
|
diff = rdtsc() -t2;
|
|
|
|
|
|
|
|
// The last measurement is garbage
|
|
|
|
if (stop) break;
|
|
|
|
// The first ones are garbage, too
|
|
|
|
if (i < 5) goto next_try;
|
|
|
|
if (diff >= timeslice) {
|
|
|
|
i--;
|
|
|
|
goto next_try;
|
|
|
|
}
|
|
|
|
|
|
|
|
kprintf("%i: diff= %llu, i= %i\n", id, diff, i);
|
|
|
|
if (diff > max) max = diff;
|
|
|
|
if (diff < min) min = diff;
|
|
|
|
avg += diff;
|
2012-04-15 19:40:51 +02:00
|
|
|
|
|
|
|
next_try:
|
2012-07-16 21:55:42 +02:00
|
|
|
sid = id;
|
2012-04-15 19:40:51 +02:00
|
|
|
}
|
|
|
|
avg /= i-5;
|
|
|
|
|
|
|
|
stop = 1;
|
2012-04-09 20:01:39 +02:00
|
|
|
|
|
|
|
kprintf("maximum gap: %llu ticks\n", max);
|
2012-04-15 19:40:51 +02:00
|
|
|
kprintf("minimum gap: %llu ticks\n", min);
|
|
|
|
kprintf("average gap: %llu ticks\n", avg);
|
|
|
|
kprintf("Timeslice size: %llu ticks\n", timeslice);
|
2012-04-09 20:01:39 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2012-04-09 20:01:39 +02:00
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
#ifdef START_CHIEFTEST
|
|
|
|
|
|
|
|
struct testcase_t {
|
|
|
|
tid_t tid;
|
|
|
|
int retval;
|
|
|
|
char* userspace_argv[10];
|
|
|
|
entry_point_t kernelspace_ep;
|
|
|
|
char* testcase_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define USERSPACE_TC(execpath, name) {0, 0, {execpath, NULL}, NULL, name}
|
|
|
|
#define KERNELSPACE_TC(execpointer, name) {0, 0, {NULL}, execpointer, name}
|
|
|
|
|
|
|
|
struct testcase_t testcases[] = {
|
2012-12-27 11:29:29 -08:00
|
|
|
// USERSPACE_TC("/bin/jacobi", "Jacobi serial user space app"),
|
2012-09-16 16:48:55 +02:00
|
|
|
USERSPACE_TC("/bin/tests", "Tests user space app"),
|
2012-12-27 11:29:29 -08:00
|
|
|
//USERSPACE_TC("/bin/hello", "Hello userspace app"),
|
2012-09-16 16:48:55 +02:00
|
|
|
KERNELSPACE_TC(producer_consumer, "Producer consumer kernel space test"),
|
2012-09-17 14:51:10 +02:00
|
|
|
KERNELSPACE_TC(join_test, "Join kernel space test"),
|
|
|
|
#ifdef CONFIG_ROCKCREEK
|
2012-12-27 11:29:29 -08:00
|
|
|
//KERNELSPACE_TC(svm_test, "SVM Test kernel space test"),
|
|
|
|
// KERNELSPACE_TC(testcase_svm_bench, "SVM Bench kernel space test"),
|
2012-09-17 14:51:10 +02:00
|
|
|
KERNELSPACE_TC(mail_ping, "Mail Ping kernel space test"),
|
|
|
|
// KERNELSPACE_TC(jacobi, "Jacobi kernel space test"),
|
2012-12-27 11:29:29 -08:00
|
|
|
// KERNELSPACE_TC(netio_init, "NetIO kernel space test")
|
2012-09-17 14:51:10 +02:00
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static int chiefmastertest(void)
|
|
|
|
{
|
|
|
|
int tests = sizeof(testcases) / sizeof(struct testcase_t);
|
2012-12-27 11:29:29 -08:00
|
|
|
int i, j;
|
2012-09-16 16:48:55 +02:00
|
|
|
int result;
|
2012-12-27 11:29:29 -08:00
|
|
|
tid_t ret;
|
2012-09-16 16:48:55 +02:00
|
|
|
struct testcase_t* current;
|
|
|
|
|
2012-12-27 11:29:29 -08:00
|
|
|
int retval[tests];
|
|
|
|
int tmpval;
|
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
int *global_retval = NULL;
|
|
|
|
|
|
|
|
kprintf("Starting chief master test: %d test cases on %d cores.\n", tests, RCCE_NP);
|
|
|
|
#else
|
2012-09-17 14:51:10 +02:00
|
|
|
kprintf("Starting chief master test: %d test cases.\n", tests);
|
2012-12-27 11:29:29 -08:00
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
|
|
|
|
for (i = 0; i < tests; i++) {
|
|
|
|
current = &testcases[i];
|
|
|
|
|
2012-09-17 14:51:10 +02:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
2012-12-27 11:29:29 -08:00
|
|
|
/* TODO: This blocks forever. Why? */
|
|
|
|
//RCCE_barrier(&RCCE_COMM_WORLD);
|
2012-09-17 14:51:10 +02:00
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
kprintf("Starting testcase: %s\n", current->testcase_name);
|
|
|
|
|
|
|
|
if (current->kernelspace_ep == NULL &&
|
|
|
|
current->userspace_argv[0] != NULL) {
|
|
|
|
create_user_task(¤t->tid, current->userspace_argv[0],
|
|
|
|
current->userspace_argv);
|
|
|
|
} else if (current->kernelspace_ep != NULL &&
|
|
|
|
current->userspace_argv[0] == NULL) {
|
|
|
|
create_kernel_task(¤t->tid, current->kernelspace_ep,
|
|
|
|
NULL, NORMAL_PRIO);
|
|
|
|
} else {
|
|
|
|
kprintf("Invalid test case struct #%d!\n", i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = wait(&result);
|
|
|
|
} while(ret != current->tid);
|
|
|
|
|
2012-09-17 14:51:10 +02:00
|
|
|
kprintf("Testcase %s returned %d %s\n", current->testcase_name, result, result ? ":(" : ":)");
|
2012-09-16 16:48:55 +02:00
|
|
|
|
2012-12-27 11:29:29 -08:00
|
|
|
retval[i] = result;
|
2012-09-16 16:48:55 +02:00
|
|
|
}
|
|
|
|
|
2012-12-27 11:29:29 -08:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
if (RCCE_IAM == 0) { // Master
|
|
|
|
global_retval = kmalloc(tests * RCCE_NP);
|
|
|
|
memcpy(global_retval, retval, sizeof(retval));
|
2012-09-16 16:48:55 +02:00
|
|
|
|
2012-12-27 11:29:29 -08:00
|
|
|
for (i=1; i < RCCE_NP; i++)
|
|
|
|
iRCCE_recv((void*)&global_retval[tests * i], sizeof(*global_retval) * tests, i);
|
|
|
|
}
|
|
|
|
else { // worker cores
|
|
|
|
iRCCE_send((void*)retval, tests * sizeof(retval[0]), 0);
|
|
|
|
}
|
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
kprintf("======================================================\n");
|
|
|
|
kprintf("Master Chief test case results:\n");
|
|
|
|
for (i = 0; i < tests; i++) {
|
2012-12-27 22:10:59 +01:00
|
|
|
current = &testcases[i];
|
2012-12-27 11:29:29 -08:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
tmpval = 0;
|
|
|
|
for (j=0; j < RCCE_NP; j++)
|
|
|
|
tmpval |= global_retval[i + j*tests];
|
|
|
|
#else
|
|
|
|
tmpval = retval[i];
|
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
|
|
|
|
kprintf("%s: ", current->testcase_name);
|
2012-12-27 11:29:29 -08:00
|
|
|
if (tmpval) {
|
2012-09-16 16:48:55 +02:00
|
|
|
pushfg(COL_RED);
|
2012-12-27 11:29:29 -08:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
if (RCCE_IAM == 0) {
|
|
|
|
kprintf("Bad :( [on cores: ");
|
|
|
|
for (j=0; j < RCCE_NP; j++)
|
|
|
|
if (global_retval[i + j*tests])
|
|
|
|
kprintf("%d ", j);
|
|
|
|
kprintf("]");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
kprintf("Bad :(");
|
2012-09-16 16:48:55 +02:00
|
|
|
} else {
|
|
|
|
pushfg(COL_GREEN);
|
|
|
|
kprintf("Pass :)");
|
2012-12-27 11:29:29 -08:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
if (RCCE_IAM == 0) kprintf(" on all cores");
|
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
}
|
|
|
|
popfg();
|
|
|
|
kprintf("\n");
|
|
|
|
}
|
|
|
|
kprintf("======================================================\n");
|
|
|
|
|
2012-12-27 11:29:29 -08:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
|
|
|
kfree(global_retval, tests * RCCE_NP);
|
|
|
|
#endif
|
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // START_CHIEFTEST
|
|
|
|
|
2010-08-15 13:58:08 +00:00
|
|
|
int test_init(void)
|
|
|
|
{
|
2012-07-16 21:55:42 +02:00
|
|
|
#ifdef START_HELLO
|
|
|
|
char* hello_argv[] = {"/bin/hello", NULL};
|
|
|
|
#endif
|
|
|
|
#ifdef START_TESTS
|
|
|
|
char* tests_argv[] = {"/bin/tests", NULL};
|
|
|
|
#endif
|
|
|
|
#ifdef START_JACOBI
|
|
|
|
char* jacobi_argv[] = {"/bin/jacobi", NULL};
|
|
|
|
#endif
|
|
|
|
#ifdef START_MMNIF_TEST
|
2011-09-20 14:37:28 +02:00
|
|
|
char* server_argv[] = {"/bin/server", "6789", NULL};
|
2011-10-04 00:03:11 -07:00
|
|
|
char* client_argv[] = {"/bin/client", "192.168.0.1", "6789", NULL};
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
2010-08-15 13:58:08 +00:00
|
|
|
|
2012-09-16 16:48:55 +02:00
|
|
|
#ifdef START_CHIEFTEST
|
|
|
|
create_kernel_task(NULL, chiefmastertest, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
|
2012-07-16 21:55:42 +02:00
|
|
|
#ifdef START_ECHO
|
|
|
|
echo_init();
|
|
|
|
#endif
|
|
|
|
#ifdef START_NETIO
|
|
|
|
netio_init();
|
|
|
|
#endif
|
2012-09-16 16:48:55 +02:00
|
|
|
#if defined(START_CONSUMER_PRODUCER) || defined(START_CHIEFTEST)
|
2012-07-16 21:55:42 +02:00
|
|
|
sem_init(&producing, 1);
|
|
|
|
sem_init(&consuming, 0);
|
|
|
|
mailbox_int32_init(&mbox);
|
2012-09-16 16:48:55 +02:00
|
|
|
#endif
|
|
|
|
#ifdef START_CONSUMER_PRODUCER
|
|
|
|
create_kernel_task(NULL, producer_consumer, NULL, NORMAL_PRIO);
|
2012-07-16 21:55:42 +02:00
|
|
|
#endif
|
|
|
|
#ifdef START_MEASURE_CTX_SWITCH
|
|
|
|
create_kernel_task(NULL, measure_ctx_switch, (int)0, NORMAL_PRIO);
|
|
|
|
create_kernel_task(NULL, measure_ctx_switch, (int)1, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_FOO
|
2012-05-21 15:04:05 +02:00
|
|
|
create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO);
|
2012-07-16 21:55:42 +02:00
|
|
|
//create_kernel_task_on_core(NULL, foo, "Hello from foo2", NORMAL_PRIO, 1);
|
|
|
|
#endif
|
|
|
|
#ifdef START_JOIN_TEST
|
|
|
|
create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_MAIL_PING
|
|
|
|
create_kernel_task(NULL, mail_ping, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_MAIL_NOISE
|
|
|
|
create_kernel_task(NULL, mail_noise, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_SVM_TEST
|
|
|
|
create_kernel_task(NULL, svm_test, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_SVM_BENCH
|
|
|
|
create_kernel_task(NULL, svm_bench, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_PI
|
|
|
|
create_kernel_task(NULL, pi, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_KERNEL_LAPLACE
|
|
|
|
create_kernel_task(NULL, laplace, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_KERNEL_JACOBI
|
|
|
|
create_kernel_task(NULL, jacobi, NULL, NORMAL_PRIO);
|
|
|
|
#endif
|
|
|
|
#ifdef START_HELLO
|
|
|
|
create_user_task(NULL, "/bin/hello", hello_argv);
|
|
|
|
#endif
|
|
|
|
#ifdef START_TESTS
|
|
|
|
create_user_task(NULL, "/bin/tests", tests_argv);
|
|
|
|
#endif
|
|
|
|
#ifdef START_JACOBI
|
|
|
|
create_user_task(NULL, "/bin/jacobi", jacobi_argv);
|
|
|
|
//create_user_task_on_core(NULL, "/bin/jacobi", jacobi_argv, 1);
|
|
|
|
#endif
|
2013-10-22 21:30:30 +02:00
|
|
|
#if defined(START_MMNIF_TEST) && defined(CONFIG_LWIP) && LWIP_SOCKET
|
2012-07-16 14:14:53 -07:00
|
|
|
if (RCCE_IAM == 0) {
|
2012-07-15 05:55:53 -07:00
|
|
|
kprintf("Start /bin/server...\n");
|
|
|
|
create_user_task(NULL, "/bin/server", server_argv);
|
|
|
|
} else {
|
2011-10-04 00:03:11 -07:00
|
|
|
sleep(5);
|
2012-07-15 05:55:53 -07:00
|
|
|
kprintf("Start /bin/client...\n");
|
2011-10-04 00:03:11 -07:00
|
|
|
create_user_task(NULL, "/bin/client", client_argv);
|
2012-07-15 05:55:53 -07:00
|
|
|
}
|
2012-07-15 06:19:57 -07:00
|
|
|
#endif
|
2013-11-14 13:17:14 +01:00
|
|
|
#ifdef START_MEMORY
|
|
|
|
create_kernel_task(NULL, memory, NULL, NORMAL_PRIO);
|
2012-07-15 05:55:53 -07:00
|
|
|
#endif
|
2010-08-15 13:58:08 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|