Merge branch 'master' into readwrite
This commit is contained in:
commit
1dd09910a8
22 changed files with 1916 additions and 30 deletions
|
@ -115,6 +115,16 @@ typedef struct {
|
|||
*/
|
||||
void gdt_install(void);
|
||||
|
||||
/** @brief Configures and returns a GDT descriptor with chosen attributes
|
||||
*
|
||||
* Just feed this function with address, limit and the flags
|
||||
* you have seen in idt.h
|
||||
*
|
||||
* @return a preconfigured gdt descriptor
|
||||
*/
|
||||
gdt_entry_t configure_gdt_entry(unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
154
arch/x86/include/asm/iRCCE.h
Normal file
154
arch/x86/include/asm/iRCCE.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-10-25] added support for non-blocking send/recv operations
|
||||
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
|
||||
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
// [2010-11-12] extracted non-blocking code into separate library
|
||||
// by Carsten Scholtes, University of Bayreuth
|
||||
//
|
||||
// [2010-12-09] added functions for a convenient handling of multiple
|
||||
// pending non-blocking requests
|
||||
// by Jacek Galowicz, Chair for Operating Systems
|
||||
// RWTH Aachen University
|
||||
//
|
||||
#ifndef IRCCE_H
|
||||
#define IRCCE_H
|
||||
|
||||
#include <asm/RCCE.h>
|
||||
|
||||
#define iRCCE_SUCCESS RCCE_SUCCESS
|
||||
#define iRCCE_PENDING -1
|
||||
#define iRCCE_RESERVED -2
|
||||
#define iRCCE_NOT_ENQUEUED -3
|
||||
|
||||
typedef struct _iRCCE_SEND_REQUEST {
|
||||
char *privbuf; // source buffer in local private memory (send buffer)
|
||||
t_vcharp combuf; // intermediate buffer in MPB
|
||||
size_t chunk; // size of MPB available for this message (bytes)
|
||||
RCCE_FLAG *ready; // flag indicating whether receiver is ready
|
||||
RCCE_FLAG *sent; // flag indicating whether message has been sent by source
|
||||
size_t size; // size of message (bytes)
|
||||
int dest; // UE that will receive the message
|
||||
|
||||
size_t wsize; // offset within send buffer when putting in "chunk" bytes
|
||||
size_t remainder; // bytes remaining to be sent
|
||||
size_t nbytes; // number of bytes to be sent in single RCCE_put call
|
||||
char *bufptr; // running pointer inside privbuf for current location
|
||||
|
||||
int label; // jump/goto label for the reentrance of the respective poll function
|
||||
int finished; // flag that indicates whether the request has already been finished
|
||||
|
||||
struct _iRCCE_SEND_REQUEST *next;
|
||||
} iRCCE_SEND_REQUEST;
|
||||
|
||||
|
||||
typedef struct _iRCCE_RECV_REQUEST {
|
||||
char *privbuf; // source buffer in local private memory (send buffer)
|
||||
t_vcharp combuf; // intermediate buffer in MPB
|
||||
size_t chunk; // size of MPB available for this message (bytes)
|
||||
RCCE_FLAG *ready; // flag indicating whether receiver is ready
|
||||
RCCE_FLAG *sent; // flag indicating whether message has been sent by source
|
||||
size_t size; // size of message (bytes)
|
||||
int source; // UE that will send the message
|
||||
|
||||
size_t wsize; // offset within send buffer when putting in "chunk" bytes
|
||||
size_t remainder; // bytes remaining to be sent
|
||||
size_t nbytes; // number of bytes to be sent in single RCCE_put call
|
||||
char *bufptr; // running pointer inside privbuf for current location
|
||||
|
||||
int label; // jump/goto label for the reentrance of the respective poll function
|
||||
int finished; // flag that indicates whether the request has already been finished
|
||||
int started; // flag that indicates whether message parts have already been received
|
||||
|
||||
struct _iRCCE_RECV_REQUEST *next;
|
||||
} iRCCE_RECV_REQUEST;
|
||||
|
||||
#define iRCCE_WAIT_LIST_RECV_TYPE 0
|
||||
#define iRCCE_WAIT_LIST_SEND_TYPE 1
|
||||
|
||||
typedef struct _iRCCE_WAIT_LISTELEM {
|
||||
int type;
|
||||
struct _iRCCE_WAIT_LISTELEM * next;
|
||||
void * req;
|
||||
} iRCCE_WAIT_LISTELEM;
|
||||
|
||||
typedef struct _iRCCE_WAIT_LIST {
|
||||
iRCCE_WAIT_LISTELEM * first;
|
||||
iRCCE_WAIT_LISTELEM * last;
|
||||
} iRCCE_WAIT_LIST;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// THE iRCCE API:
|
||||
//
|
||||
// Initialize function:
|
||||
int iRCCE_init(void);
|
||||
//
|
||||
// Non-blocking send/recv functions:
|
||||
int iRCCE_isend(char *, size_t, int, iRCCE_SEND_REQUEST *);
|
||||
int iRCCE_isend_test(iRCCE_SEND_REQUEST *, int *);
|
||||
int iRCCE_isend_wait(iRCCE_SEND_REQUEST *);
|
||||
int iRCCE_isend_push(void);
|
||||
int iRCCE_irecv(char *, size_t, int, iRCCE_RECV_REQUEST *);
|
||||
int iRCCE_irecv_test(iRCCE_RECV_REQUEST *, int *);
|
||||
int iRCCE_irecv_wait(iRCCE_RECV_REQUEST *);
|
||||
int iRCCE_irecv_push(void);
|
||||
//
|
||||
// Blocking but pipelined send/recv functions:
|
||||
int iRCCE_send(char *, size_t, int);
|
||||
int iRCCE_recv(char *, size_t, int);
|
||||
//
|
||||
// SCC-customized put/get and memcpy functions:
|
||||
int iRCCE_put(t_vcharp, t_vcharp, int, int);
|
||||
int iRCCE_get(t_vcharp, t_vcharp, int, int);
|
||||
void* iRCCE_memcpy_put(void*, const void*, size_t);
|
||||
void* iRCCE_memcpy_get(void*, const void*, size_t);
|
||||
//
|
||||
// Wait/test-all/any functions:
|
||||
void iRCCE_init_wait_list(iRCCE_WAIT_LIST*);
|
||||
void iRCCE_add_to_wait_list(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST *, iRCCE_RECV_REQUEST *);
|
||||
int iRCCE_test_all(iRCCE_WAIT_LIST*, int *);
|
||||
int iRCCE_wait_all(iRCCE_WAIT_LIST*);
|
||||
int iRCCE_test_any(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST **, iRCCE_RECV_REQUEST **);
|
||||
int iRCCE_wait_any(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST **, iRCCE_RECV_REQUEST **);
|
||||
//
|
||||
// Cancel functions for yet not started non-blocking requests:
|
||||
int iRCCE_isend_cancel(iRCCE_SEND_REQUEST *, int *);
|
||||
int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *, int *);
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Just for for convenience:
|
||||
#if 1
|
||||
#define RCCE_isend iRCCE_isend
|
||||
#define RCCE_isend_test iRCCE_isend_test
|
||||
#define RCCE_isend_wait iRCCE_isend_wait
|
||||
#define RCCE_isend_push iRCCE_isend_push
|
||||
#define RCCE_irecv iRCCE_irecv
|
||||
#define RCCE_irecv_test iRCCE_irecv_test
|
||||
#define RCCE_irecv_wait iRCCE_irecv_wait
|
||||
#define RCCE_irecv_push iRCCE_irecv_push
|
||||
#define RCCE_SEND_REQUEST iRCCE_SEND_REQUEST
|
||||
#define RCCE_RECV_REQUEST iRCCE_RECV_REQUEST
|
||||
#endif
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
39
arch/x86/include/asm/iRCCE_lib.h
Normal file
39
arch/x86/include/asm/iRCCE_lib.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-10-25] added support for non-blocking send/recv operations
|
||||
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
|
||||
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
// [2010-11-12] extracted non-blocking code into separate library
|
||||
// by Carsten Scholtes
|
||||
//
|
||||
#ifndef IRCCE_LIB_H
|
||||
#define IRCCE_LIB_H
|
||||
#include <asm/iRCCE.h>
|
||||
#include <asm/RCCE_lib.h>
|
||||
|
||||
extern iRCCE_SEND_REQUEST* iRCCE_isend_queue;
|
||||
extern iRCCE_RECV_REQUEST* iRCCE_irecv_queue[RCCE_MAXNP];
|
||||
#ifdef _OPENMP
|
||||
#pragma omp threadprivate (iRCCE_isend_queue, iRCCE_irecv_queue)
|
||||
#endif
|
||||
|
||||
int iRCCE_test_flag(RCCE_FLAG, RCCE_FLAG_STATUS, int *);
|
||||
|
||||
#endif
|
||||
|
|
@ -116,6 +116,16 @@ void idt_install(void);
|
|||
void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel,
|
||||
unsigned char flags);
|
||||
|
||||
/** @brief Configures and returns a IDT entry with chosen attributes
|
||||
*
|
||||
* Just feed this function with base, selector and the flags
|
||||
* you have seen in idt.h
|
||||
*
|
||||
* @return a preconfigured idt descriptor
|
||||
*/
|
||||
idt_entry_t configure_idt_entry(unsigned long base, unsigned short sel,
|
||||
unsigned char flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -157,19 +157,27 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg)
|
|||
static void gdt_set_gate(int num, unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran)
|
||||
{
|
||||
gdt[num] = configure_gdt_entry(base, limit, access, gran);
|
||||
}
|
||||
|
||||
gdt_entry_t configure_gdt_entry(unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran)
|
||||
{
|
||||
gdt_entry_t desc;
|
||||
/* Setup the descriptor base address */
|
||||
gdt[num].base_low = (base & 0xFFFF);
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||
desc.base_low = (base & 0xFFFF);
|
||||
desc.base_middle = (base >> 16) & 0xFF;
|
||||
desc.base_high = (base >> 24) & 0xFF;
|
||||
|
||||
/* Setup the descriptor limits */
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = ((limit >> 16) & 0x0F);
|
||||
desc.limit_low = (limit & 0xFFFF);
|
||||
desc.granularity = ((limit >> 16) & 0x0F);
|
||||
|
||||
/* Finally, set up the granularity and access flags */
|
||||
gdt[num].granularity |= (gran & 0xF0);
|
||||
gdt[num].access = access;
|
||||
desc.granularity |= (gran & 0xF0);
|
||||
desc.access = access;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -48,16 +48,25 @@ static idt_ptr_t idtp;
|
|||
void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel,
|
||||
unsigned char flags)
|
||||
{
|
||||
idt[num] = configure_idt_entry(base, sel, flags);
|
||||
}
|
||||
|
||||
idt_entry_t configure_idt_entry(unsigned long base, unsigned short sel,
|
||||
unsigned char flags)
|
||||
{
|
||||
idt_entry_t desc;
|
||||
|
||||
/* The interrupt routine's base address */
|
||||
idt[num].base_lo = (base & 0xFFFF);
|
||||
idt[num].base_hi = (base >> 16) & 0xFFFF;
|
||||
desc.base_lo = (base & 0xFFFF);
|
||||
desc.base_hi = (base >> 16) & 0xFFFF;
|
||||
|
||||
/* The segment or 'selector' that this IDT entry will use
|
||||
* is set here, along with any access flags */
|
||||
idt[num].sel = sel;
|
||||
idt[num].always0 = 0;
|
||||
idt[num].flags = flags;
|
||||
desc.sel = sel;
|
||||
desc.always0 = 0;
|
||||
desc.flags = flags;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
extern void isrsyscall(void);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := scc_init.c SCC_API.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c
|
||||
C_source := scc_init.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c
|
||||
ASM_source :=
|
||||
MODULE := arch_x86_scc
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
// #include <fcntl.h>
|
||||
|
||||
// En-/ or disable debug prints...
|
||||
#define DEBUG 1
|
||||
#define DEBUG 0
|
||||
|
||||
//......................................................................................
|
||||
// GLOBAL VARIABLES USED BY THE LIBRARY
|
||||
|
|
67
arch/x86/scc/iRCCE_admin.c
Normal file
67
arch/x86/scc/iRCCE_admin.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
//***************************************************************************************
|
||||
// Administrative routines.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-10-25] added support for non-blocking send/recv operations
|
||||
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
|
||||
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
// [2010-11-12] extracted non-blocking code into separate library
|
||||
// by Carsten Scholtes
|
||||
//
|
||||
// [2011-02-21] added support for multiple incoming queues
|
||||
// (one recv queue per remote rank)
|
||||
//
|
||||
|
||||
#include <metalsvm/stddef.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
// send request queue
|
||||
iRCCE_SEND_REQUEST* iRCCE_isend_queue;
|
||||
// recv request queue
|
||||
iRCCE_RECV_REQUEST* iRCCE_irecv_queue[RCCE_MAXNP];
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_init
|
||||
//--------------------------------------------------------------------------------------
|
||||
// initialize the library
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_init(void) {
|
||||
int i;
|
||||
|
||||
for(i=0; i<RCCE_MAXNP; i++) {
|
||||
iRCCE_irecv_queue[i] = NULL;
|
||||
}
|
||||
|
||||
iRCCE_isend_queue = NULL;
|
||||
|
||||
return (iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
85
arch/x86/scc/iRCCE_get.c
Normal file
85
arch/x86/scc/iRCCE_get.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
//***************************************************************************************
|
||||
// Get data from communication buffer.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-11-03] switched to SCC-optimized memcpy() functions in scc_memcpy.h:
|
||||
// - memcpy_to_mpb()
|
||||
// - memcpy_from_mpb()
|
||||
// by Stefan Lankes, Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
#ifdef COPPERRIDGE
|
||||
#include "scc_memcpy.h"
|
||||
#endif
|
||||
|
||||
void* iRCCE_memcpy_get(void *dest, const void *src, size_t count)
|
||||
{
|
||||
#ifdef COPPERRIDGE
|
||||
return memcpy_from_mpb(dest, src, count);
|
||||
#else
|
||||
return memcpy(dest, src, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_get
|
||||
//--------------------------------------------------------------------------------------
|
||||
// copy data from address "source" in the remote MPB to address "target" in either the
|
||||
// local MPB, or in the calling UE's private memory. We do not test to see if a move
|
||||
// into the calling UE's private memory stays within allocated memory *
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_get(
|
||||
t_vcharp target, // target buffer, MPB or private memory
|
||||
t_vcharp source, // source buffer, MPB
|
||||
int num_bytes, // number of bytes to copy (must be multiple of cache line size
|
||||
int ID // rank of source UE
|
||||
) {
|
||||
|
||||
// in non-GORY mode we only need to retain the MPB source shift; we
|
||||
// already know the source is in the MPB, not private memory
|
||||
source = RCCE_comm_buffer[ID]+(source-RCCE_comm_buffer[RCCE_IAM]);
|
||||
|
||||
// do the actual copy, making sure we copy fresh data
|
||||
#ifdef _OPENMP
|
||||
#pragma omp flush
|
||||
#endif
|
||||
RC_cache_invalidate();
|
||||
|
||||
iRCCE_memcpy_get((void *)target, (void *)source, num_bytes);
|
||||
|
||||
// flush data to make sure it is visible to all threads; cannot use a flush list
|
||||
// because it concerns malloced space
|
||||
#ifdef _OPENMP
|
||||
#pragma omp flush
|
||||
#endif
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
393
arch/x86/scc/iRCCE_irecv.c
Normal file
393
arch/x86/scc/iRCCE_irecv.c
Normal file
|
@ -0,0 +1,393 @@
|
|||
//***************************************************************************************
|
||||
// Synchronized receive routines.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-10-25] added support for non-blocking send/recv operations
|
||||
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
|
||||
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
// [2010-11-12] extracted non-blocking code into separate library
|
||||
// by Carsten Scholtes
|
||||
//
|
||||
// [2010-12-09] added cancel functions for non-blocking send/recv requests
|
||||
// by Carsten Clauss
|
||||
//
|
||||
// [2011-02-21] added support for multiple incoming queues
|
||||
// (one recv queue per remote rank)
|
||||
//
|
||||
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
static int iRCCE_push_recv_request(iRCCE_RECV_REQUEST *request) {
|
||||
|
||||
char padline[RCCE_LINE_SIZE]; // copy buffer, used if message not multiple of line size
|
||||
int test; // flag for calling iRCCE_test_flag()
|
||||
|
||||
if(request->finished) return(iRCCE_SUCCESS);
|
||||
|
||||
if(request->label == 1) goto label1;
|
||||
if(request->label == 2) goto label2;
|
||||
if(request->label == 3) goto label3;
|
||||
|
||||
// receive data in units of available chunk size of MPB
|
||||
for (; request->wsize < (request->size / request->chunk) * request->chunk; request->wsize += request->chunk) {
|
||||
request->bufptr = request->privbuf + request->wsize;
|
||||
request->nbytes = request->chunk;
|
||||
label1:
|
||||
iRCCE_test_flag(*(request->sent), RCCE_FLAG_SET, &test);
|
||||
if(!test) {
|
||||
request->label = 1;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
request->started = 1;
|
||||
|
||||
RCCE_flag_write(request->sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
// copy data from source's MPB space to private memory
|
||||
iRCCE_get((t_vcharp)request->bufptr, request->combuf, request->nbytes, request->source);
|
||||
|
||||
// tell the source I have moved data out of its comm buffer
|
||||
RCCE_flag_write(request->ready, RCCE_FLAG_SET, request->source);
|
||||
}
|
||||
|
||||
request->remainder = request->size % request->chunk;
|
||||
// if nothing is left over, we are done
|
||||
if (!request->remainder) {
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
// receive remainder of data--whole cache lines
|
||||
request->bufptr = request->privbuf + (request->size / request->chunk) * request->chunk;
|
||||
request->nbytes = request->remainder - request->remainder % RCCE_LINE_SIZE;
|
||||
if (request->nbytes) {
|
||||
label2:
|
||||
iRCCE_test_flag(*(request->sent), RCCE_FLAG_SET, &test);
|
||||
if(!test) {
|
||||
request->label = 2;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
request->started = 1;
|
||||
|
||||
RCCE_flag_write(request->sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
// copy data from source's MPB space to private memory
|
||||
iRCCE_get((t_vcharp)request->bufptr, request->combuf, request->nbytes, request->source);
|
||||
|
||||
// tell the source I have moved data out of its comm buffer
|
||||
RCCE_flag_write(request->ready, RCCE_FLAG_SET, request->source);
|
||||
}
|
||||
|
||||
request->remainder = request->size % request->chunk;
|
||||
request->remainder = request->remainder % RCCE_LINE_SIZE;
|
||||
if (!request->remainder) {
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
// remainder is less than cache line. This must be copied into appropriately sized
|
||||
// intermediate space before exact number of bytes get copied to the final destination
|
||||
request->bufptr = request->privbuf + (request->size / request->chunk) * request->chunk + request->nbytes;
|
||||
request->nbytes = RCCE_LINE_SIZE;
|
||||
label3:
|
||||
iRCCE_test_flag(*(request->sent), RCCE_FLAG_SET, &test);
|
||||
if(!test) {
|
||||
request->label = 3;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
request->started = 1;
|
||||
|
||||
RCCE_flag_write(request->sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
// copy data from source's MPB space to private memory
|
||||
iRCCE_get((t_vcharp)padline, request->combuf, request->nbytes, request->source);
|
||||
memcpy(request->bufptr,padline,request->remainder);
|
||||
|
||||
// tell the source I have moved data out of its comm buffer
|
||||
RCCE_flag_write(request->ready, RCCE_FLAG_SET, request->source);
|
||||
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
static void iRCCE_init_recv_request(
|
||||
char *privbuf, // source buffer in local private memory (send buffer)
|
||||
t_vcharp combuf, // intermediate buffer in MPB
|
||||
size_t chunk, // size of MPB available for this message (bytes)
|
||||
RCCE_FLAG *ready, // flag indicating whether receiver is ready
|
||||
RCCE_FLAG *sent, // flag indicating whether message has been sent by source
|
||||
size_t size, // size of message (bytes)
|
||||
int source, // UE that will send the message
|
||||
iRCCE_RECV_REQUEST *request
|
||||
) {
|
||||
|
||||
request->privbuf = privbuf;
|
||||
request->combuf = combuf;
|
||||
request->chunk = chunk;
|
||||
request->ready = ready;
|
||||
request->sent = sent;
|
||||
request->size = size;
|
||||
request->source = source;
|
||||
|
||||
request->wsize = 0;
|
||||
request->remainder = 0;
|
||||
request->nbytes = 0;
|
||||
request->bufptr = NULL;
|
||||
|
||||
request->label = 0;
|
||||
request->finished = 0;
|
||||
request->started = 0;
|
||||
|
||||
request->next = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_irecv
|
||||
//--------------------------------------------------------------------------------------
|
||||
// non-blocking recv function; returns an handle of type iRCCE_RECV_REQUEST
|
||||
//--------------------------------------------------------------------------------------
|
||||
static iRCCE_RECV_REQUEST blocking_irecv_request;
|
||||
int iRCCE_irecv(char *privbuf, size_t size, int source, iRCCE_RECV_REQUEST *request) {
|
||||
|
||||
if(request == NULL) request = &blocking_irecv_request;
|
||||
|
||||
if (source<0 || source >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
else {
|
||||
iRCCE_init_recv_request(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[RCCE_IAM], &RCCE_sent_flag[source],
|
||||
size, source, request);
|
||||
|
||||
if(iRCCE_irecv_queue[source] == NULL) {
|
||||
|
||||
if(iRCCE_push_recv_request(request) == iRCCE_SUCCESS) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
iRCCE_irecv_queue[source] = request;
|
||||
|
||||
if(request == &blocking_irecv_request) {
|
||||
iRCCE_irecv_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(iRCCE_irecv_queue[source]->next == NULL) {
|
||||
iRCCE_irecv_queue[source]->next = request;
|
||||
}
|
||||
else {
|
||||
iRCCE_RECV_REQUEST *run = iRCCE_irecv_queue[source];
|
||||
while(run->next != NULL) run = run->next;
|
||||
run->next = request;
|
||||
}
|
||||
|
||||
if(request == &blocking_irecv_request) {
|
||||
iRCCE_irecv_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_irecv_test
|
||||
//--------------------------------------------------------------------------------------
|
||||
// test function for completion of the requestes non-blocking recv operation
|
||||
// Just provide NULL instead of the testvar if you don't need it
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_irecv_test(iRCCE_RECV_REQUEST *request, int *test) {
|
||||
|
||||
int source;
|
||||
|
||||
if(request == NULL) {
|
||||
|
||||
if(iRCCE_irecv_push() == iRCCE_SUCCESS) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
source = request->source;
|
||||
|
||||
if(request->finished) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(iRCCE_irecv_queue[source] != request) {
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
|
||||
iRCCE_push_recv_request(request);
|
||||
|
||||
if(request->finished) {
|
||||
iRCCE_irecv_queue[source] = request->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_irecv_push
|
||||
//--------------------------------------------------------------------------------------
|
||||
// progress function for pending requests in the irecv queue
|
||||
//--------------------------------------------------------------------------------------
|
||||
static int iRCCE_irecv_push_source(int source) {
|
||||
|
||||
iRCCE_RECV_REQUEST *request = iRCCE_irecv_queue[source];
|
||||
|
||||
if(request == NULL) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(request->finished) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
iRCCE_push_recv_request(request);
|
||||
|
||||
if(request->finished) {
|
||||
iRCCE_irecv_queue[source] = request->next;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
|
||||
int iRCCE_irecv_push(void) {
|
||||
|
||||
int i, j;
|
||||
int retval = iRCCE_SUCCESS;
|
||||
|
||||
for(i=0; i<RCCE_NP; i++) {
|
||||
|
||||
j = iRCCE_irecv_push_source(i);
|
||||
|
||||
if(j != iRCCE_SUCCESS) {
|
||||
retval = j;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_irecv_wait
|
||||
//--------------------------------------------------------------------------------------
|
||||
// just wait for completion of the requested non-blocking send operation
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_irecv_wait(iRCCE_RECV_REQUEST *request) {
|
||||
|
||||
if(request != NULL) {
|
||||
while(!request->finished) {
|
||||
iRCCE_irecv_push();
|
||||
iRCCE_isend_push();
|
||||
}
|
||||
}
|
||||
else {
|
||||
do {
|
||||
iRCCE_isend_push();
|
||||
}
|
||||
while( iRCCE_irecv_push() != iRCCE_SUCCESS );
|
||||
}
|
||||
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_irecv_cancel
|
||||
//--------------------------------------------------------------------------------------
|
||||
// try to cancel a pending non-blocking recv request
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *request, int *test) {
|
||||
|
||||
int source;
|
||||
iRCCE_RECV_REQUEST *run;
|
||||
|
||||
if( (request == NULL) || (request->finished) ) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
source = request->source;
|
||||
|
||||
if(iRCCE_irecv_queue[source] == NULL) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
if(iRCCE_irecv_queue[source] == request) {
|
||||
|
||||
// have parts of the message already been received?
|
||||
if(request->started) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_PENDING;
|
||||
}
|
||||
else {
|
||||
// no, thus request can be canceld just in time:
|
||||
iRCCE_irecv_queue[source] = request->next;
|
||||
if (test) (*test) = 1;
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
for(run = iRCCE_irecv_queue[source]; run->next != NULL; run = run->next) {
|
||||
|
||||
// request found --> remove it from recv queue:
|
||||
if(run->next == request) {
|
||||
|
||||
run->next = run->next->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
#endif
|
355
arch/x86/scc/iRCCE_isend.c
Normal file
355
arch/x86/scc/iRCCE_isend.c
Normal file
|
@ -0,0 +1,355 @@
|
|||
//***************************************************************************************
|
||||
// Non-blocking send routines.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-10-25] added support for non-blocking send/recv operations
|
||||
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
|
||||
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
// [2010-11-12] extracted non-blocking code into separate library
|
||||
// by Carsten Scholtes
|
||||
//
|
||||
// [2010-12-09] added cancel functions for non-blocking send/recv requests
|
||||
// by Carsten Clauss
|
||||
//
|
||||
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
static int iRCCE_push_send_request(iRCCE_SEND_REQUEST *request) {
|
||||
|
||||
char padline[RCCE_LINE_SIZE]; // copy buffer, used if message not multiple of line size
|
||||
int test; // flag for calling iRCCE_test_flag()
|
||||
|
||||
if(request->finished) return(iRCCE_SUCCESS);
|
||||
|
||||
if(request->label == 1) goto label1;
|
||||
if(request->label == 2) goto label2;
|
||||
if(request->label == 3) goto label3;
|
||||
|
||||
// send data in units of available chunk size of comm buffer
|
||||
for (; request->wsize< (request->size / request->chunk) * request->chunk; request->wsize += request->chunk) {
|
||||
request->bufptr = request->privbuf + request->wsize;
|
||||
request->nbytes = request->chunk;
|
||||
// copy private data to own comm buffer
|
||||
iRCCE_put(request->combuf, (t_vcharp) request->bufptr, request->nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(request->sent, RCCE_FLAG_SET, request->dest);
|
||||
// wait for the destination to be ready to receive a message
|
||||
label1:
|
||||
iRCCE_test_flag(*(request->ready), RCCE_FLAG_SET, &test);
|
||||
if(!test) {
|
||||
request->label = 1;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
RCCE_flag_write(request->ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
|
||||
request->remainder = request->size % request->chunk;
|
||||
// if nothing is left over, we are done
|
||||
if (!request->remainder) {
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
// send remainder of data--whole cache lines
|
||||
request->bufptr = request->privbuf + (request->size / request->chunk) * request->chunk;
|
||||
request->nbytes = request->remainder - request->remainder % RCCE_LINE_SIZE;
|
||||
if (request->nbytes) {
|
||||
// copy private data to own comm buffer
|
||||
iRCCE_put(request->combuf, (t_vcharp)request->bufptr, request->nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(request->sent, RCCE_FLAG_SET, request->dest);
|
||||
// wait for the destination to be ready to receive a message
|
||||
label2:
|
||||
iRCCE_test_flag(*(request->ready), RCCE_FLAG_SET, &test);
|
||||
if(!test) {
|
||||
request->label = 2;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
RCCE_flag_write(request->ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
|
||||
request->remainder = request->size % request->chunk;
|
||||
request->remainder = request->remainder%RCCE_LINE_SIZE;
|
||||
// if nothing is left over, we are done
|
||||
if (!request->remainder)
|
||||
{
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
// remainder is less than a cache line. This must be copied into appropriately sized
|
||||
// intermediate space before it can be sent to the receiver
|
||||
request->bufptr = request->privbuf + (request->size / request->chunk) * request->chunk + request->nbytes;
|
||||
request->nbytes = RCCE_LINE_SIZE;
|
||||
// copy private data to own comm buffer
|
||||
memcpy(padline,request->bufptr,request->remainder);
|
||||
iRCCE_put(request->combuf, (t_vcharp)padline, request->nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(request->sent, RCCE_FLAG_SET, request->dest);
|
||||
// wait for the destination to be ready to receive a message
|
||||
label3:
|
||||
iRCCE_test_flag(*(request->ready), RCCE_FLAG_SET, &test);
|
||||
if(!test) {
|
||||
request->label = 3;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
RCCE_flag_write(request->ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
static void iRCCE_init_send_request(
|
||||
char *privbuf, // source buffer in local private memory (send buffer)
|
||||
t_vcharp combuf, // intermediate buffer in MPB
|
||||
size_t chunk, // size of MPB available for this message (bytes)
|
||||
RCCE_FLAG *ready, // flag indicating whether receiver is ready
|
||||
RCCE_FLAG *sent, // flag indicating whether message has been sent by source
|
||||
size_t size, // size of message (bytes)
|
||||
int dest, // UE that will receive the message
|
||||
iRCCE_SEND_REQUEST *request
|
||||
) {
|
||||
|
||||
request->privbuf = privbuf;
|
||||
request->combuf = combuf;
|
||||
request->chunk = chunk;
|
||||
request->ready = ready;
|
||||
request->sent = sent;
|
||||
request->size = size;
|
||||
request->dest = dest;
|
||||
|
||||
request->wsize = 0;
|
||||
request->remainder = 0;
|
||||
request->nbytes = 0;
|
||||
request->bufptr = NULL;
|
||||
|
||||
request->label = 0;
|
||||
|
||||
request->finished = 0;
|
||||
|
||||
request->next = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend
|
||||
//--------------------------------------------------------------------------------------
|
||||
// non-blocking send function; returns a handle of type iRCCE_SEND_REQUEST
|
||||
//--------------------------------------------------------------------------------------
|
||||
static iRCCE_SEND_REQUEST blocking_isend_request;
|
||||
int iRCCE_isend(char *privbuf, size_t size, int dest, iRCCE_SEND_REQUEST *request) {
|
||||
|
||||
if(request == NULL) request = &blocking_isend_request;
|
||||
|
||||
if (dest<0 || dest >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
else {
|
||||
iRCCE_init_send_request(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[dest], &RCCE_sent_flag[RCCE_IAM],
|
||||
size, dest, request);
|
||||
|
||||
if(iRCCE_isend_queue == NULL) {
|
||||
|
||||
if(iRCCE_push_send_request(request) == iRCCE_SUCCESS) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
iRCCE_isend_queue = request;
|
||||
|
||||
if(request == &blocking_isend_request) {
|
||||
iRCCE_isend_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(iRCCE_isend_queue->next == NULL) {
|
||||
iRCCE_isend_queue->next = request;
|
||||
}
|
||||
else {
|
||||
iRCCE_SEND_REQUEST *run = iRCCE_isend_queue;
|
||||
while(run->next != NULL) run = run->next;
|
||||
run->next = request;
|
||||
}
|
||||
|
||||
if(request == &blocking_isend_request) {
|
||||
iRCCE_isend_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend_test
|
||||
//--------------------------------------------------------------------------------------
|
||||
// test function for completion of the requestes non-blocking send operation
|
||||
// Just provide NULL instead of testvar if you don't need it
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_isend_test(iRCCE_SEND_REQUEST *request, int *test) {
|
||||
|
||||
if(request == NULL) {
|
||||
|
||||
iRCCE_isend_push();
|
||||
|
||||
if(iRCCE_isend_queue == NULL) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
if(request->finished) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(iRCCE_isend_queue != request) {
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
|
||||
iRCCE_push_send_request(request);
|
||||
|
||||
if(request->finished) {
|
||||
iRCCE_isend_queue = request->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend_push
|
||||
//--------------------------------------------------------------------------------------
|
||||
// progress function for pending requests in the isend queue
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_isend_push(void) {
|
||||
|
||||
iRCCE_SEND_REQUEST *request = iRCCE_isend_queue;
|
||||
|
||||
if(request == NULL) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(request->finished) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
iRCCE_push_send_request(request);
|
||||
|
||||
if(request->finished) {
|
||||
iRCCE_isend_queue = request->next;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend_wait
|
||||
//--------------------------------------------------------------------------------------
|
||||
// just wait for completion of the requestes non-blocking send operation
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_isend_wait(iRCCE_SEND_REQUEST *request) {
|
||||
|
||||
if(request != NULL) {
|
||||
|
||||
while(!request->finished) {
|
||||
|
||||
iRCCE_isend_push();
|
||||
iRCCE_irecv_push();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
while(iRCCE_isend_queue != NULL) {
|
||||
|
||||
iRCCE_isend_push();
|
||||
iRCCE_irecv_push();
|
||||
}
|
||||
}
|
||||
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend_cancel
|
||||
//--------------------------------------------------------------------------------------
|
||||
// try to cancel a pending non-blocking send request
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_isend_cancel(iRCCE_SEND_REQUEST *request, int *test) {
|
||||
|
||||
iRCCE_SEND_REQUEST *run;
|
||||
|
||||
if( (request == NULL) || (request->finished) ) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
if(iRCCE_isend_queue == NULL) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
if(iRCCE_isend_queue == request) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_PENDING;
|
||||
}
|
||||
|
||||
for(run = iRCCE_isend_queue; run->next != NULL; run = run->next) {
|
||||
|
||||
// request found --> remove it from send queue:
|
||||
if(run->next == request) {
|
||||
|
||||
run->next = run->next->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
#endif
|
87
arch/x86/scc/iRCCE_put.c
Normal file
87
arch/x86/scc/iRCCE_put.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
//***************************************************************************************
|
||||
// Put data into communication buffer.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-11-03] switched to SCC-optimized memcpy() functions in scc_memcpy.h:
|
||||
// - memcpy_to_mpb()
|
||||
// - memcpy_from_mpb()
|
||||
// by Stefan Lankes, Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
#ifdef COPPERRIDGE
|
||||
#include "scc_memcpy.h"
|
||||
#endif
|
||||
|
||||
void* iRCCE_memcpy_put(void *dest, const void *src, size_t count)
|
||||
{
|
||||
#ifdef COPPERRIDGE
|
||||
return memcpy_to_mpb(dest, src, count);
|
||||
#else
|
||||
return memcpy(dest, src, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_put
|
||||
//--------------------------------------------------------------------------------------
|
||||
// copy data from address "source" in the local MPB or the calling UE's private memory
|
||||
// to address "target" in the remote MPB. We do not test to see if a move from the
|
||||
// calling UE's private memory stays within allocated memory
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_put(
|
||||
t_vcharp target, // target buffer, MPB
|
||||
t_vcharp source, // source buffer, MPB or private memory
|
||||
int num_bytes,
|
||||
int ID
|
||||
) {
|
||||
|
||||
// in non-GORY mode we only need to retain the MPB target shift; we
|
||||
// already know the target is in the MPB, not private memory
|
||||
target = RCCE_comm_buffer[ID]+(target-RCCE_comm_buffer[RCCE_IAM]);
|
||||
|
||||
// make sure that any data that has been put in our MPB by another UE is visible
|
||||
#ifdef _OPENMP
|
||||
#pragma omp flush
|
||||
#endif
|
||||
|
||||
// do the actual copy
|
||||
RC_cache_invalidate();
|
||||
|
||||
iRCCE_memcpy_put((void *)target, (void *)source, num_bytes);
|
||||
|
||||
// flush data to make it visible to all threads; cannot use flush list because it
|
||||
// concerns malloced space
|
||||
#ifdef _OPENMP
|
||||
#pragma omp flush
|
||||
#endif
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
190
arch/x86/scc/iRCCE_recv.c
Normal file
190
arch/x86/scc/iRCCE_recv.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
//***************************************************************************************
|
||||
// Non-blocking receive routines.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-11-26] added a _pipelined_ version of blocking send/recv
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_recv_general
|
||||
//--------------------------------------------------------------------------------------
|
||||
// pipelined receive function
|
||||
//--------------------------------------------------------------------------------------
|
||||
static int iRCCE_recv_general(
|
||||
char *privbuf, // destination buffer in local private memory (receive buffer)
|
||||
t_vcharp combuf, // intermediate buffer in MPB
|
||||
size_t chunk, // size of MPB available for this message (bytes)
|
||||
RCCE_FLAG *ready, // flag indicating whether receiver is ready
|
||||
RCCE_FLAG *sent, // flag indicating whether message has been sent by source
|
||||
size_t size, // size of message (bytes)
|
||||
int source, // UE that sent the message
|
||||
int *test // if 1 upon entry, do nonblocking receive; if message available
|
||||
// set to 1, otherwise to 0
|
||||
) {
|
||||
|
||||
char padline[RCCE_LINE_SIZE]; // copy buffer, used if message not multiple of line size
|
||||
size_t wsize, // offset within receive buffer when pulling in "chunk" bytes
|
||||
remainder, // bytes remaining to be received
|
||||
nbytes; // number of bytes to be received in single iRCCE_get call
|
||||
int first_test; // only use first chunk to determine if message has been received yet
|
||||
char *bufptr; // running pointer inside privbuf for current location
|
||||
|
||||
first_test = 1;
|
||||
|
||||
#if 0
|
||||
// receive data in units of available chunk size of MPB
|
||||
for (wsize=0; wsize< (size/chunk)*chunk; wsize+=chunk) {
|
||||
bufptr = privbuf + wsize;
|
||||
nbytes = chunk;
|
||||
// if function is called in test mode, check if first chunk has been sent already.
|
||||
// If so, proceed as usual. If not, exit immediately
|
||||
if (*test && first_test) {
|
||||
first_test = 0;
|
||||
if (!(*test = RCCE_probe(*sent))) return(iRCCE_SUCCESS);
|
||||
}
|
||||
RCCE_wait_until(*sent, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
// copy data from local MPB space to private memory
|
||||
iRCCE_get((t_vcharp)bufptr, combuf, nbytes, source);
|
||||
|
||||
// tell the source I have moved data out of its comm buffer
|
||||
RCCE_flag_write(ready, RCCE_FLAG_SET, source);
|
||||
}
|
||||
#else
|
||||
{ // pipelined version of send/recv:
|
||||
|
||||
size_t subchunk1 = chunk / 2;
|
||||
size_t subchunk2 = chunk - subchunk1;
|
||||
|
||||
for (wsize=0; wsize < (size/chunk)*chunk; wsize+=chunk) {
|
||||
|
||||
if (*test && first_test) {
|
||||
first_test = 0;
|
||||
if (!(*test = RCCE_probe(*sent))) return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
bufptr = privbuf + wsize;
|
||||
nbytes = subchunk1;
|
||||
|
||||
RCCE_wait_until(*ready, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
iRCCE_get((t_vcharp)bufptr, combuf, nbytes, source);
|
||||
|
||||
RCCE_flag_write(ready, RCCE_FLAG_SET, source);
|
||||
|
||||
bufptr = privbuf + wsize + subchunk1;
|
||||
nbytes = subchunk2;
|
||||
|
||||
RCCE_wait_until(*sent, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
iRCCE_get((t_vcharp)bufptr, combuf + subchunk1, nbytes, source);
|
||||
|
||||
RCCE_flag_write(sent, RCCE_FLAG_SET, source);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
remainder = size%chunk;
|
||||
// if nothing is left over, we are done
|
||||
if (!remainder) return(iRCCE_SUCCESS);
|
||||
|
||||
// receive remainder of data--whole cache lines
|
||||
bufptr = privbuf + (size/chunk)*chunk;
|
||||
nbytes = remainder - remainder % RCCE_LINE_SIZE;
|
||||
if (nbytes) {
|
||||
// if function is called in test mode, check if first chunk has been sent already.
|
||||
// If so, proceed as usual. If not, exit immediately
|
||||
if (*test && first_test) {
|
||||
first_test = 0;
|
||||
if (!(*test = RCCE_probe(*sent))) return(iRCCE_SUCCESS);
|
||||
}
|
||||
RCCE_wait_until(*sent, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
// copy data from local MPB space to private memory
|
||||
iRCCE_get((t_vcharp)bufptr, combuf, nbytes, source);
|
||||
|
||||
// tell the source I have moved data out of its comm buffer
|
||||
RCCE_flag_write(ready, RCCE_FLAG_SET, source);
|
||||
}
|
||||
|
||||
remainder = remainder % RCCE_LINE_SIZE;
|
||||
if (!remainder) return(iRCCE_SUCCESS);
|
||||
|
||||
// remainder is less than cache line. This must be copied into appropriately sized
|
||||
// intermediate space before exact number of bytes get copied to the final destination
|
||||
bufptr = privbuf + (size/chunk)*chunk + nbytes;
|
||||
nbytes = RCCE_LINE_SIZE;
|
||||
|
||||
// if function is called in test mode, check if first chunk has been sent already.
|
||||
// If so, proceed as usual. If not, exit immediately
|
||||
if (*test && first_test) {
|
||||
first_test = 0;
|
||||
if (!(*test = RCCE_probe(*sent))) return(iRCCE_SUCCESS);
|
||||
}
|
||||
RCCE_wait_until(*sent, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
|
||||
// copy data from local MPB space to private memory
|
||||
iRCCE_get((t_vcharp)padline, combuf, nbytes, source);
|
||||
memcpy(bufptr,padline,remainder);
|
||||
|
||||
// tell the source I have moved data out of its comm buffer
|
||||
RCCE_flag_write(ready, RCCE_FLAG_SET, source);
|
||||
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_recv
|
||||
//--------------------------------------------------------------------------------------
|
||||
// pipelined recv function (blocking!)
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_recv(char *privbuf, size_t size, int source) {
|
||||
int ignore;
|
||||
|
||||
while(iRCCE_irecv_queue[source] != NULL) {
|
||||
// wait for completion of pending non-blocking requests
|
||||
iRCCE_irecv_push();
|
||||
iRCCE_isend_push();
|
||||
}
|
||||
|
||||
if (source<0 || source >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
else {
|
||||
ignore = 0;
|
||||
return(iRCCE_recv_general(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[RCCE_IAM], &RCCE_sent_flag[source],
|
||||
size, source, &ignore));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
165
arch/x86/scc/iRCCE_send.c
Normal file
165
arch/x86/scc/iRCCE_send.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
//***************************************************************************************
|
||||
// Synchronized receive routines.
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-11-26] added a _pipelined_ version of blocking send/recv
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_send_general
|
||||
//--------------------------------------------------------------------------------------
|
||||
// pipelined send function
|
||||
//--------------------------------------------------------------------------------------
|
||||
static int iRCCE_send_general(
|
||||
char *privbuf, // source buffer in local private memory (send buffer)
|
||||
t_vcharp combuf, // intermediate buffer in MPB
|
||||
size_t chunk, // size of MPB available for this message (bytes)
|
||||
RCCE_FLAG *ready, // flag indicating whether receiver is ready
|
||||
RCCE_FLAG *sent, // flag indicating whether message has been sent by source
|
||||
size_t size, // size of message (bytes)
|
||||
int dest // UE that will receive the message
|
||||
) {
|
||||
|
||||
char padline[RCCE_LINE_SIZE]; // copy buffer, used if message not multiple of line size
|
||||
size_t wsize, // offset within send buffer when putting in "chunk" bytes
|
||||
remainder, // bytes remaining to be sent
|
||||
nbytes; // number of bytes to be sent in single iRCCE_put call
|
||||
char *bufptr; // running pointer inside privbuf for current location
|
||||
|
||||
#if 0
|
||||
// send data in units of available chunk size of comm buffer
|
||||
for (wsize=0; wsize< (size/chunk)*chunk; wsize+=chunk) {
|
||||
bufptr = privbuf + wsize;
|
||||
nbytes = chunk;
|
||||
// copy private data to own comm buffer
|
||||
iRCCE_put(combuf, (t_vcharp) bufptr, nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_SET, dest);
|
||||
// wait for the destination to be ready to receive a message
|
||||
RCCE_wait_until(*ready, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
#else
|
||||
{ // pipelined version of send/recv:
|
||||
size_t subchunk1 = chunk / 2;
|
||||
size_t subchunk2 = chunk - subchunk1;
|
||||
|
||||
wsize = 0;
|
||||
|
||||
for (; wsize < (size/chunk)*chunk; wsize+=chunk) {
|
||||
|
||||
bufptr = privbuf + wsize;
|
||||
nbytes = subchunk1;
|
||||
|
||||
iRCCE_put(combuf, (t_vcharp) bufptr, nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(ready, RCCE_FLAG_SET, dest);
|
||||
|
||||
if(wsize>0)
|
||||
{
|
||||
RCCE_wait_until(*sent, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
|
||||
bufptr = privbuf + wsize + subchunk1;
|
||||
nbytes = subchunk2;
|
||||
|
||||
iRCCE_put(combuf + subchunk1, (t_vcharp) bufptr, nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_SET, dest);
|
||||
|
||||
RCCE_wait_until(*ready, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
|
||||
if(wsize>0) {
|
||||
RCCE_wait_until(*sent, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
remainder = size%chunk;
|
||||
// if nothing is left over, we are done
|
||||
if (!remainder) return(iRCCE_SUCCESS);
|
||||
|
||||
// send remainder of data--whole cache lines
|
||||
bufptr = privbuf + (size/chunk)*chunk;
|
||||
nbytes = remainder - remainder%RCCE_LINE_SIZE;
|
||||
if (nbytes) {
|
||||
// copy private data to own comm buffer
|
||||
iRCCE_put(combuf, (t_vcharp)bufptr, nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_SET, dest);
|
||||
// wait for the destination to be ready to receive a message
|
||||
RCCE_wait_until(*ready, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
}
|
||||
|
||||
remainder = remainder%RCCE_LINE_SIZE;
|
||||
if (!remainder) return(iRCCE_SUCCESS);
|
||||
|
||||
// remainder is less than a cache line. This must be copied into appropriately sized
|
||||
// intermediate space before it can be sent to the receiver
|
||||
bufptr = privbuf + (size/chunk)*chunk + nbytes;
|
||||
nbytes = RCCE_LINE_SIZE;
|
||||
|
||||
// copy private data to own comm buffer
|
||||
memcpy(padline,bufptr,remainder);
|
||||
iRCCE_put(combuf, (t_vcharp)padline, nbytes, RCCE_IAM);
|
||||
RCCE_flag_write(sent, RCCE_FLAG_SET, dest);
|
||||
|
||||
// wait for the destination to be ready to receive a message
|
||||
RCCE_wait_until(*ready, RCCE_FLAG_SET);
|
||||
RCCE_flag_write(ready, RCCE_FLAG_UNSET, RCCE_IAM);
|
||||
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_send
|
||||
//--------------------------------------------------------------------------------------
|
||||
// pipelined send function (blocking!)
|
||||
//--------------------------------------------------------------------------------------
|
||||
int iRCCE_send(char *privbuf, size_t size, int dest) {
|
||||
|
||||
while(iRCCE_isend_queue != NULL) {
|
||||
// wait for completion of pending non-blocking requests
|
||||
iRCCE_isend_push();
|
||||
iRCCE_irecv_push();
|
||||
}
|
||||
|
||||
if (dest<0 || dest >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
else
|
||||
return(iRCCE_send_general(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[dest], &RCCE_sent_flag[RCCE_IAM],
|
||||
size, dest));
|
||||
}
|
||||
|
||||
#endif
|
127
arch/x86/scc/iRCCE_synch.c
Normal file
127
arch/x86/scc/iRCCE_synch.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
///*************************************************************************************
|
||||
// Synchronization functions.
|
||||
// Single-bit and whole-cache-line flags are sufficiently different that we provide
|
||||
// separate implementations of the synchronization routines for each case
|
||||
//**************************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//**************************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2010-10-25] added support for non-blocking send/recv operations
|
||||
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
|
||||
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
|
||||
// by Carsten Clauss, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
// [2010-11-12] extracted non-blocking code into separate library
|
||||
// by Carsten Scholtes
|
||||
//
|
||||
// [2011-01-21] updated the datatype of RCCE_FLAG according to the
|
||||
// recent version of RCCE
|
||||
//
|
||||
// [2011-04-12] added marco test for rcce version
|
||||
//
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
|
||||
#ifdef SINGLEBITFLAGS
|
||||
|
||||
int iRCCE_test_flag(RCCE_FLAG flag, RCCE_FLAG_STATUS val, int *result) {
|
||||
|
||||
t_vcharp cflag;
|
||||
|
||||
#ifdef RCCE_VERSION
|
||||
// this is a newer version than V1.0.13
|
||||
t_vcharp flaga;
|
||||
#endif
|
||||
|
||||
cflag = flag.line_address;
|
||||
|
||||
#ifdef RCCE_VERSION
|
||||
// this is a newer version than V1.0.13
|
||||
flaga = flag.flag_addr;
|
||||
#endif
|
||||
|
||||
// always flush/invalidate to ensure we read the most recent value of *flag
|
||||
// keep reading it until it has the required value
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp flush
|
||||
#endif
|
||||
RC_cache_invalidate();
|
||||
|
||||
#ifdef RCCE_VERSION
|
||||
// this is a newer version than V1.0.13
|
||||
if(RCCE_bit_value(flaga, (flag.location)%RCCE_FLAGS_PER_BYTE) != val) {
|
||||
#else
|
||||
if(RCCE_bit_value(cflag, flag.location) != val) {
|
||||
#endif
|
||||
(*result) = 0;
|
||||
}
|
||||
else {
|
||||
(*result) = 1;
|
||||
}
|
||||
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// LOCKLESS SYNCHRONIZATION USING ONE WHOLE CACHE LINE PER FLAG //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
int iRCCE_test_flag(RCCE_FLAG flag, RCCE_FLAG_STATUS val, int *result) {
|
||||
|
||||
#ifdef RCCE_VERSION
|
||||
// this is a newer version than V1.0.13
|
||||
t_vcharp flaga = flag.flag_addr;
|
||||
#endif
|
||||
|
||||
// always flush/invalidate to ensure we read the most recent value of *flag
|
||||
// keep reading it until it has the required value. We only need to read the
|
||||
// first int of the MPB cache line containing the flag
|
||||
#ifdef _OPENMP
|
||||
#pragma omp flush
|
||||
#endif
|
||||
RC_cache_invalidate();
|
||||
|
||||
#ifdef RCCE_VERSION
|
||||
// this is a newer version than V1.0.13
|
||||
if((RCCE_FLAG_STATUS)(*flaga) != val) {
|
||||
#else
|
||||
if((*flag) != val) {
|
||||
#endif
|
||||
(*result) = 0;
|
||||
}
|
||||
else {
|
||||
(*result) = 1;
|
||||
}
|
||||
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -17,7 +17,8 @@
|
|||
#include <metalsvm/processor.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/RCCE_lib.h>
|
||||
#include <asm/RCCE.h>
|
||||
#include <asm/iRCCE.h>
|
||||
#include <asm/SCC_API.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
@ -35,6 +36,9 @@ bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO;
|
|||
static int scc_clear(void)
|
||||
{
|
||||
int tmp, x, y, z, offset;
|
||||
|
||||
// Initialize API
|
||||
InitAPI(0);
|
||||
|
||||
// Find out who I am...
|
||||
tmp=ReadConfigReg(CRB_OWN+MYTILEID);
|
||||
|
@ -57,6 +61,9 @@ static int scc_clear(void)
|
|||
// Clear test&set register write. Next read-access will read "1" (lock granted).
|
||||
SetConfigReg(CRB_ADDR(x,y)+((z)?LOCK1:LOCK0), 1);
|
||||
|
||||
// frees Message Passing Buffer
|
||||
MPBunalloc(&MPB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -64,31 +71,60 @@ int scc_init(void)
|
|||
{
|
||||
int num_ranks;
|
||||
int i, my_rank;
|
||||
uint64_t start, end, ticks, freq = 533;
|
||||
uint32_t cr4, msg = 0;
|
||||
|
||||
kputs("Initialize Rock Creek!\n");
|
||||
|
||||
/* Enable Messagepassing in CR4 */
|
||||
cr4 = read_cr4();
|
||||
cr4 = cr4 | _CR4_MPE;
|
||||
write_cr4(cr4);
|
||||
|
||||
kprintf("Initialize Rock Creek!\n");
|
||||
kprintf("address of the initrd: 0x%x\n", bootinfo->addr);
|
||||
kprintf("size of the initrd: %d\n", bootinfo->size);
|
||||
kprintf("rcce argc = %d\n", bootinfo->argc);
|
||||
for(i=0; i<bootinfo->argc; i++)
|
||||
kprintf("rcce argv[%d] = %s\n", i, bootinfo->argv[i]);
|
||||
|
||||
if (bootinfo->argc >= 3)
|
||||
freq = atoi(bootinfo->argv[2]);
|
||||
|
||||
kputs("Reset SCC!\n");
|
||||
scc_clear();
|
||||
kputs("Wait some time...\n");
|
||||
mb();
|
||||
start = rdtsc();
|
||||
do {
|
||||
mb();
|
||||
end = rdtsc();
|
||||
ticks = end > start ? end - start : start - end;
|
||||
} while(ticks*TIMER_FREQ < 300ULL*freq*1000000ULL);
|
||||
|
||||
if (RCCE_init(&bootinfo->argc, &bootinfo->argv) != RCCE_SUCCESS)
|
||||
return -ENODEV;
|
||||
if (iRCCE_init() != iRCCE_SUCCESS)
|
||||
return -ENODEV;
|
||||
|
||||
// enable additional outputs
|
||||
RCCE_debug_set(RCCE_DEBUG_ALL);
|
||||
|
||||
my_rank = RCCE_ue();
|
||||
num_ranks = RCCE_num_ues();
|
||||
kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks);
|
||||
|
||||
/* Enable Messagepassing in CR4 */
|
||||
uint32_t cr4 = read_cr4();
|
||||
cr4 = cr4 | _CR4_MPE;
|
||||
write_cr4(cr4);
|
||||
|
||||
i = ReadConfigReg(CRB_OWN+GLCFG0);
|
||||
kprintf("glcfg0 0x%x\n", i);
|
||||
|
||||
/* synchronize before starting MetalSVM: */
|
||||
//RCCE_barrier(&RCCE_COMM_WORLD);
|
||||
RCCE_barrier(&RCCE_COMM_WORLD);
|
||||
|
||||
kputs("RCCE test...\t");
|
||||
if (my_rank == 0)
|
||||
msg = 0x4711;
|
||||
if (RCCE_bcast((char*) &msg, sizeof(msg), 0, RCCE_COMM_WORLD) == RCCE_SUCCESS)
|
||||
kprintf("successfull! (0x%x)\n", msg);
|
||||
else
|
||||
kprintf("failed! (0x%x)\n", msg);
|
||||
|
||||
kputs("Now, the SCC is initialized!\n");
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ extern "C" {
|
|||
// RCCE specific flags
|
||||
#define SCC
|
||||
#define MS_BAREMETAL
|
||||
#define GORY
|
||||
//#define GORY
|
||||
//#define SHMADD
|
||||
//#define SHMADD_CACHEABLE
|
||||
/* default values for 16 GB system */
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/stddef.h>
|
||||
|
||||
#ifndef HAVE_ARCH_MEMCPY
|
||||
//#ifndef HAVE_ARCH_MEMCPY
|
||||
void *memcpy(void *dest, const void *src, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -23,7 +23,7 @@ void *memcpy(void *dest, const void *src, size_t count)
|
|||
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
#ifndef HAVE_ARCH_MEMSET
|
||||
void *memset(void *dest, int val, size_t count)
|
||||
|
|
|
@ -41,16 +41,19 @@ scc_bootinfo.asm: bootinfo.sh
|
|||
scc_bootinfo.bin: scc_bootinfo.asm
|
||||
$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
|
||||
SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin initrd.img
|
||||
bin2obj: bin2obj.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin initrd.img bin2obj
|
||||
cp ../metalsvm.elf .
|
||||
$(CROSS_OBJCOPY) -j .mboot -j .text -j .data -j .rodata -j .bss -O binary metalsvm.elf metalsvm.bin
|
||||
chmod a-x *.bin
|
||||
. ./prepare.sh
|
||||
/home/lankes/tools/bin2obj -m load.map -o metalsvm.obj
|
||||
./bin2obj -m load.map -o metalsvm.obj
|
||||
sccMerge -noimage -m 8 -n 12 -force ./metalsvm.mt
|
||||
|
||||
clean:
|
||||
$(RM) -rf *.o *~ make_initrd initrd.img *.bin *.obj *.hex *.elf obj
|
||||
$(RM) -rf *.o *~ bin2obj make_initrd initrd.img *.bin *.obj *.hex *.elf obj
|
||||
|
||||
depend:
|
||||
$(CC) -MM $(CFLAGS) *.c > Makefile.dep
|
||||
|
|
147
tools/bin2obj.c
Normal file
147
tools/bin2obj.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
const char BIN2OBJIDSTRING[] = "$Id: bin2obj.c 8016 2007-11-01 14:24:42Z tlehnig $";
|
||||
|
||||
|
||||
long long convertToHex(char *fn, unsigned long origin, FILE *outfile) {
|
||||
FILE *datafile;
|
||||
unsigned char data1, data2, data3, data4;
|
||||
int res = 0;
|
||||
long long count = 0;
|
||||
|
||||
datafile = fopen(fn, "r");
|
||||
if (!datafile) {
|
||||
printf("Datafile >%s< could not be opened, not writing data for this file\n", fn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Converting file >%s< to .32.obj format at origin 0x%08lx (0x%08lx) ... ",
|
||||
fn, origin >> 2, origin);
|
||||
fprintf(outfile, "/origin %08lx\n", origin >> 2);
|
||||
|
||||
do {
|
||||
data1 = 0;
|
||||
data2 = 0;
|
||||
data3 = 0;
|
||||
data4 = 0;
|
||||
|
||||
res = fscanf(datafile, "%c%c%c%c", &data1, &data2, &data3, &data4);
|
||||
if (res > 0) {
|
||||
count += res;
|
||||
|
||||
fprintf(outfile, "%02x%02x%02x%02x", data4, data3, data2, data1);
|
||||
|
||||
if ((count % 16) == 0)
|
||||
fprintf(outfile, "\n");
|
||||
else
|
||||
fprintf(outfile, " ");
|
||||
}
|
||||
|
||||
} while (res > 0);
|
||||
|
||||
if ((count % 16) != 0) fprintf(outfile, "\n");
|
||||
|
||||
printf("done with %lli Bytes.\n", count);
|
||||
|
||||
fclose(datafile);
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void print_help() {
|
||||
printf("Usage: bin2obj [FLAGS] [OPTIONS]\n");
|
||||
printf("\nFLAGS: -h, -v\n");
|
||||
printf("-h Print this help\n");
|
||||
printf("-v Print Version ID\n");
|
||||
printf("\nOPTIONS: -m, -o\n");
|
||||
printf("-m <mapfile> Defines mapfile to use for bin2obj\n");
|
||||
printf("-o <outfile> Defines output file to use for bin2obj\n");
|
||||
printf("\nbin2obj converts the binary files defined in the mapfile to a hex based textfile\n");
|
||||
printf("used by MCEMU\n");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
FILE *mapfile = NULL, *outfile = NULL;
|
||||
unsigned long origin;
|
||||
char datafn[255];
|
||||
char outfn[255] = "output.obj";
|
||||
char mapfn[255] = "load.map";
|
||||
int res = 0;
|
||||
unsigned long long count = 0;
|
||||
long long thiscount = 0;
|
||||
int retval = 0;
|
||||
|
||||
int c, doOptLoop = 1;
|
||||
|
||||
while (doOptLoop) {
|
||||
c = getopt(argc, argv, "m:o:hv");
|
||||
|
||||
if (c == -1) {
|
||||
doOptLoop = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_help();
|
||||
return 0;
|
||||
break;
|
||||
case 'v':
|
||||
printf("%s %s\n", argv[0], BIN2OBJIDSTRING);
|
||||
return 0;
|
||||
break;
|
||||
case 'm':
|
||||
printf("Mapfile: >%s<\n", optarg);
|
||||
strncpy(mapfn, optarg, 255);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Outfile: >%s<\n", optarg);
|
||||
strncpy(outfn, optarg, 255);
|
||||
break;
|
||||
default:
|
||||
print_help();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mapfile = fopen(mapfn, "r");
|
||||
if (!mapfile) {
|
||||
printf("Mapfile >%s< not found, exiting.\n", mapfn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
outfile = fopen(outfn, "w");
|
||||
if (!outfile) {
|
||||
printf("Outputfile >%s< could not be created, exiting\n", outfn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// res = fscanf(mapfile, "%lx %s\n", &origin, datafn);
|
||||
|
||||
while ((res = fscanf(mapfile, "%lx %s\n", &origin, datafn)) == 2) {
|
||||
//printf("ReadMapFile origin: 0x%08lx, filename: >%s<\n", origin, datafn);
|
||||
|
||||
thiscount = convertToHex(datafn, origin, outfile);
|
||||
if (thiscount < 0) {
|
||||
retval = -1;
|
||||
}
|
||||
else count += thiscount;
|
||||
|
||||
}
|
||||
|
||||
fprintf(outfile, "/eof\n");
|
||||
fclose(mapfile);
|
||||
fclose (outfile);
|
||||
|
||||
printf("Total conversion: %lli Bytes\n", count);
|
||||
|
||||
return retval;
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
# pid mch-route mch-dest-id mch-offset-base testcase
|
||||
0x00 0x00 6 0x00 metalsvm.obj
|
||||
0x01 0x00 6 0x01 metalsvm.obj
|
||||
|
|
Loading…
Add table
Reference in a new issue