/* * 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> #include <metalsvm/vma.h> #include <metalsvm/page.h> #ifdef CONFIG_ROCKCREEK #include <asm/icc.h> #include <asm/RCCE.h> #include <asm/RCCE_lib.h> #include <asm/iRCCE.h> #include <asm/iRCCE_lib.h> #include <asm/svm.h> #include <asm/SCC_API.h> #include <lwip/sockets.h> #include "client.h" #include "server.h" #include "shell.h" #endif static sem_t consuming, producing; static mailbox_int32_t mbox; static int val = 0; static int consumer(void* arg) { int i, m = 0; for(i=0; i<5; i++) { sem_wait(&consuming, 0); kprintf("Consumer got %d\n", val); val = 0; sem_post(&producing); } for(i=0; i<5; i++) { mailbox_int32_fetch(&mbox, &m, 0); kprintf("Got mail %d\n", m); } return 0; } static int producer(void* arg) { int i; int mail[5] = {1, 2, 3, 4, 5}; for(i=0; i<5; i++) { sem_wait(&producing, 0); 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; } static int foo(void* arg) { int i; if (!arg) return 0; for(i=0; i<5; i++) { kprintf("Message from core %d: %s\n", smp_id(), (char*) arg); sleep(1); } return 42; } #ifdef CONFIG_ROCKCREEK int mail_ping(void* arg) { int i; for(i=0; i<20; i++) { if (BUILTIN_EXPECT(icc_mail_ping(), 0)) return -1; udelay(500000); } return 0; } #define N 1024 volatile static int* A[N]; volatile static int* B[N]; volatile static int* C[N]; static int svm_test(void *arg) { uint64_t start, end; uint32_t i, j, k; int my_ue, num_ues; RCCE_barrier(&RCCE_COMM_WORLD); my_ue = RCCE_ue(); num_ues = RCCE_num_ues(); #if 0 if (!my_ue) { // allocate and initialize SVM region A[0] = (int*) kmalloc(3*N*N*sizeof(int)); 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++) B[i][j] = i+j; } kputs("Start sequentiell calculation...\n"); start = rdtsc(); start = rdtsc(); // start calculation for(i=0; i<N; i++) for(j=0; j<N; j++) for(k=0; k<N; k++) C[i][j] += A[i][k] * B[k][j]; end = rdtsc(); kprintf("Calculation time (seq): %llu\n", end-start); kfree(A[0], 3*N*N*sizeof(int)); } RCCE_barrier(&RCCE_COMM_WORLD); #endif // allocate and initialize SVM region A[0] = (int*) svmmalloc(3*N*N*sizeof(int)); if (!my_ue) 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); } if (!my_ue) { for(i=0; i<N; i++) { A[i][i] = 1; for(j=0; j<N; j++) B[i][j] = i+j; } } svm_flush(); kputs("Start parallel calculation...\n"); start = rdtsc(); start = rdtsc(); // Now, we need only read access on A and B change_page_permissions((size_t) A[0], (size_t) (A[0]+2*N*N), VMA_CACHEABLE|VMA_READ); RCCE_barrier(&RCCE_COMM_WORLD); // start calculation for(i=my_ue*(N/num_ues); i<(my_ue+1)*(N/num_ues); i++) for(j=0; j<N; j++) for(k=0; k<N; k++) C[i][j] += A[i][k] * B[k][j]; svm_flush(); RCCE_barrier(&RCCE_COMM_WORLD); end = rdtsc(); kputs("Check results...\n"); if (!my_ue) { uint32_t err = 0; for(i=0; (i<N) && (err < 10); i++) { for(j=0; (j<N) && (err < 10); j++) { if (C[i][j] != i+j) { err++; kprintf("Wrong value at C[%u][%u] = %u, B[%u][%u] = %u\n", i, j, C[i][j], i, j, B[i][j]); } } } } RCCE_barrier(&RCCE_COMM_WORLD); kprintf("Calculation time (par): %llu\n", end-start); svmfree((void*) A[0], 3*N*sizeof(int)); svm_statistics(); return 0; } #endif static int join_test(void* arg) { tid_t id, ret; int result = -1234; create_kernel_task(&id, foo, "Hello from foo2"); kprintf("Wait for child %u\n", id); do { ret = wait(&result); } while(ret != id); kprintf("Child %u finished: result = %d\n", id, result); return 0; } #if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) #define SHELLDEBUGPRINTF(x,...) kprintf(x,##__VA_ARGS__); static int srv_cnt = 0; static Server srv; void srv_on_read(ServerEventArgs* e) { // kprintf("%i:",srv_cnt); // hex_dump(e->dwLen,e->pBuffer); // srv_cnt++; /* printf("%i:",cnt); puts(e->pBuffer); puts("\n"); cnt++; */ } void srv_on_disc(ServerEventArgs*e ) { kprintf("connection lost!!!\n"); } void srv_on_conn(ServerEventArgs* e) { int i = 0, err = 0; int tmp1,tmp2; char buff[1024]; SHELLDEBUGPRINTF("someone finally connected\n"); tmp1 = get_clock_tick(); for (i = 0; i < 1024*4; i++) { err = srv_sendBuffer(&srv,e->ClientID,buff,sizeof(buff)); if ( err < 0) { SHELLDEBUGPRINTF("err: %d", err); } if (!(i%10)) { SHELLDEBUGPRINTF("\r-%d-",i); } } tmp2 = get_clock_tick(); // SHELLDEBUGPRINTF("send with %f kb/s",((float)i*sizeof(buff))/(tmp2-tmp1)); SHELLDEBUGPRINTF("send %d bytes in %d ticks",i*sizeof(buff),(tmp2-tmp1)); } void* server_task(void* e) { SHELLDEBUGPRINTF("created server\n"); server_init(&srv,5555,2); srv._OnRead = srv_on_read; srv._OnDisconnect = srv_on_disc; srv._OnConnect = srv_on_conn; while(1) sleep(2); return NULL; } static int cli_cnt = 0; void cli_on_read(ClientEventArgs* e) { kprintf("\r-%d-",cli_cnt); cli_cnt++; // printf("%i:",cnt); // hex_dump(e->dwLen,e->pBuffer); // cnt++; /* puts(e->pBuffer); puts("\n"); cnt++; */ } void cli_on_disc(ClientEventArgs*e ) { kprintf("connection lost!!!\n"); } void* client_task(void* e) { int err = -2; Client cli; char netbuffer[256]; kprintf("created client"); cli_init(&cli); cli._OnRead = cli_on_read; cli._OnDisconnect = cli_on_disc; sleep(2); SHELLDEBUGPRINTF("Client is ready...\n"); while (err) { sleep(1); err = cli_ConnectTo(&cli,"192.168.0.1",5555,0); SHELLDEBUGPRINTF("retry connect err = %d socket: %d\n",err,cli.sSocket); } SHELLDEBUGPRINTF("connected\n"); sleep(1); err = cli_sendBuffer(&cli,"Hallo Welt",sizeof("Hallo Welt")); SHELLDEBUGPRINTF("send message err = %d\n",err); while(1) sleep(2); return NULL; } #endif int test_init(void) { char* argv[] = {"/bin/tests", NULL}; char* server_argv[] = {"/bin/server", "6789", NULL}; char* client_argv[] = {"/bin/client", "127.0.0.1", "6789", NULL}; sem_init(&producing, 1); sem_init(&consuming, 0); mailbox_int32_init(&mbox); #if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) // shell_init(RCCE_ue()); // // sleep(10); // SHELLDEBUGPRINTF("hello World! I AM CORE NO. %d =) \n",RCCE_ue()); // if (!RCCE_ue()) // create_kernel_task(NULL,server_task,NULL); // else // create_kernel_task(NULL,client_task,NULL); #endif //create_kernel_task(NULL, foo, "Hello from foo1"); //create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); //create_kernel_task(NULL, mail_ping, NULL); create_kernel_task(NULL, svm_test, NULL); //create_user_task(NULL, "/bin/hello", argv); //create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/server", server_argv); //sleep(5); //create_user_task(NULL, "/bin/client", client_argv); return 0; }