diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h index 0ce1e64f..31fdb2ef 100644 --- a/arch/x86/include/asm/icc.h +++ b/arch/x86/include/asm/icc.h @@ -45,11 +45,14 @@ typedef struct { uint32_t length; } icc_header_t; -#define ICC_TYPE_IP (1 << 0) -#define ICC_TYPE_SVM (1 << 1) +#define ICC_TYPE_IP (1 << 0) +#define ICC_TYPE_SVM (1 << 1) +#define ICC_TYPE_PINGREQUEST (1 << 2) +#define ICC_TYPE_PINGRESPONSE (1 << 3) int icc_init(void); -void check_icc(void); +int icc_ping(); +void icc_check(void); #endif diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index adcd26fb..58a89be5 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_ROCKCREEK #include #include @@ -29,6 +30,9 @@ static int num_ues, my_ue; /* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ #define _CR4_MPE 0x00000800 +/* maximal number of SCC's cores */ +#define MAX_SCC_CORES (NUM_ROWS*NUM_COLS*NUM_CORES) + /* * This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c). * @@ -131,8 +135,102 @@ int icc_init(void) return 0; } -void check_icc(void) +int icc_ping(int ue) { + icc_header_t ping_header = {ICC_TYPE_PINGREQUEST, 0, sizeof(uint64_t)}; + uint64_t tsc; + uint32_t flags; + iRCCE_SEND_REQUEST send_request; + + if (BUILTIN_EXPECT(ue == my_ue, 0)) + return -EINVAL; + if (BUILTIN_EXPECT((ue < 0) || (ue >= num_ues), 0)) + return -EINVAL; + + tsc = rdtsc(); + + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + + iRCCE_isend((char*) &ping_header, sizeof(icc_header_t), ue, NULL); + iRCCE_isend((char*) &tsc, sizeof(uint64_t), ue, &send_request); + + // waiting for the completion + while(iRCCE_isend_test(&send_request, NULL) != iRCCE_SUCCESS) + icc_check(); // oh, we have time to check incoming requests + + irq_nested_enable(flags); + + return 0; +} + +static void interpret_header(icc_header_t* header, int recv_ue) +{ + //kprintf("Got ICC message %d from %d\n", header->type, recv_ue); + + switch(header->type) + { + case ICC_TYPE_PINGREQUEST: { + icc_header_t response = {ICC_TYPE_PINGRESPONSE, 0, sizeof(uint64_t)}; + iRCCE_RECV_REQUEST recv_req; + uint64_t tsc; + + iRCCE_isend((char*) &response, sizeof(icc_header_t), recv_ue, NULL); + if (iRCCE_irecv((char*) &tsc, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS) + iRCCE_irecv_wait(&recv_req); + + iRCCE_isend((char*) &tsc, sizeof(uint64_t), recv_ue, NULL); + iRCCE_isend_push(); + } + break; + case ICC_TYPE_PINGRESPONSE: { + uint64_t start, end; + iRCCE_RECV_REQUEST recv_req; + + if (iRCCE_irecv((char*) &start, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS) + iRCCE_irecv_wait(&recv_req); + end = rdtsc(); + kprintf("Receive ping response. Ticks: %d\n", end-start); + } + break; + default: + kprintf("Receive unknown ICC message (%d)\n", header->type); + } +} + +/* + * By entering this function, interrupts are already disables + * => No race by using the static variables + */ +void icc_check(void) +{ + static icc_header_t header[MAX_SCC_CORES]; + static iRCCE_RECV_REQUEST request[MAX_SCC_CORES]; + static int8_t pending[MAX_SCC_CORES] = {[0 ... MAX_SCC_CORES-1] = 0}; + int i, ret; + + // pushes the progress of non-blocking communication requests + iRCCE_isend_push(); + iRCCE_irecv_push(); + + for(i=0; i #include #include +#ifdef CONFIG_ROCKCREEK +#include +#endif static sem_t consuming, producing; static mailbox_int32_t mbox; @@ -83,6 +86,20 @@ static int STDCALL foo(void* arg) return 42; } +#ifdef CONFIG_ROCKCREEK +static int STDCALL ping(void* arg) +{ + int i; + + for(i=0; i<20; i++) { + icc_ping(1); + sleep(1); + } + + return 0; +} +#endif + static int STDCALL join_test(void* arg) { tid_t id, ret; @@ -112,6 +129,7 @@ int test_init(void) //create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); + //create_kernel_task(NULL, ping, NULL); //create_user_task(NULL, "/bin/hello", argv); create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv);