Add qlmpi and swap to mckernel (This is rebase commit for merging to development)

This commit is contained in:
Yutaka Ishikawa
2017-07-23 21:19:15 +09:00
committed by Ken Sato
parent 74f15783d2
commit 236a072311
61 changed files with 6638 additions and 24 deletions

91
executer/include/md5.h Normal file
View File

@@ -0,0 +1,91 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

473
executer/include/pmi.h Normal file
View File

@@ -0,0 +1,473 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2001 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#ifndef PMI_H_INCLUDED
#define PMI_H_INCLUDED
#ifdef USE_PMI2_API
#error This header file defines the PMI v1 API, but PMI2 was selected
#endif
/* prototypes for the PMI interface in MPICH */
#if defined(__cplusplus)
extern "C" {
#endif
/*D
PMI_CONSTANTS - PMI definitions
Error Codes:
+ PMI_SUCCESS - operation completed successfully
. PMI_FAIL - operation failed
. PMI_ERR_NOMEM - input buffer not large enough
. PMI_ERR_INIT - PMI not initialized
. PMI_ERR_INVALID_ARG - invalid argument
. PMI_ERR_INVALID_KEY - invalid key argument
. PMI_ERR_INVALID_KEY_LENGTH - invalid key length argument
. PMI_ERR_INVALID_VAL - invalid val argument
. PMI_ERR_INVALID_VAL_LENGTH - invalid val length argument
. PMI_ERR_INVALID_LENGTH - invalid length argument
. PMI_ERR_INVALID_NUM_ARGS - invalid number of arguments
. PMI_ERR_INVALID_ARGS - invalid args argument
. PMI_ERR_INVALID_NUM_PARSED - invalid num_parsed length argument
. PMI_ERR_INVALID_KEYVALP - invalid keyvalp argument
- PMI_ERR_INVALID_SIZE - invalid size argument
Booleans:
+ PMI_TRUE - true
- PMI_FALSE - false
D*/
#define PMI_SUCCESS 0
#define PMI_FAIL -1
#define PMI_ERR_INIT 1
#define PMI_ERR_NOMEM 2
#define PMI_ERR_INVALID_ARG 3
#define PMI_ERR_INVALID_KEY 4
#define PMI_ERR_INVALID_KEY_LENGTH 5
#define PMI_ERR_INVALID_VAL 6
#define PMI_ERR_INVALID_VAL_LENGTH 7
#define PMI_ERR_INVALID_LENGTH 8
#define PMI_ERR_INVALID_NUM_ARGS 9
#define PMI_ERR_INVALID_ARGS 10
#define PMI_ERR_INVALID_NUM_PARSED 11
#define PMI_ERR_INVALID_KEYVALP 12
#define PMI_ERR_INVALID_SIZE 13
/* PMI Group functions */
/*@
PMI_Init - initialize the Process Manager Interface
Output Parameter:
. spawned - spawned flag
Return values:
+ PMI_SUCCESS - initialization completed successfully
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - initialization failed
Notes:
Initialize PMI for this process group. The value of spawned indicates whether
this process was created by 'PMI_Spawn_multiple'. 'spawned' will be 'PMI_TRUE' if
this process group has a parent and 'PMI_FALSE' if it does not.
@*/
int PMI_Init( int *spawned );
/*@
PMI_Initialized - check if PMI has been initialized
Output Parameter:
. initialized - boolean value
Return values:
+ PMI_SUCCESS - initialized successfully set
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to set the variable
Notes:
On successful output, initialized will either be 'PMI_TRUE' or 'PMI_FALSE'.
+ PMI_TRUE - initialize has been called.
- PMI_FALSE - initialize has not been called or previously failed.
@*/
int PMI_Initialized( int *initialized );
/*@
PMI_Finalize - finalize the Process Manager Interface
Return values:
+ PMI_SUCCESS - finalization completed successfully
- PMI_FAIL - finalization failed
Notes:
Finalize PMI for this process group.
@*/
int PMI_Finalize( void );
/*@
PMI_Get_size - obtain the size of the process group
Output Parameters:
. size - pointer to an integer that receives the size of the process group
Return values:
+ PMI_SUCCESS - size successfully obtained
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to return the size
Notes:
This function returns the size of the process group to which the local process
belongs.
@*/
int PMI_Get_size( int *size );
/*@
PMI_Get_rank - obtain the rank of the local process in the process group
Output Parameters:
. rank - pointer to an integer that receives the rank in the process group
Return values:
+ PMI_SUCCESS - rank successfully obtained
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to return the rank
Notes:
This function returns the rank of the local process in its process group.
@*/
int PMI_Get_rank( int *rank );
/*@
PMI_Get_universe_size - obtain the universe size
Output Parameters:
. size - pointer to an integer that receives the size
Return values:
+ PMI_SUCCESS - size successfully obtained
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to return the size
@*/
int PMI_Get_universe_size( int *size );
/*@
PMI_Get_appnum - obtain the application number
Output parameters:
. appnum - pointer to an integer that receives the appnum
Return values:
+ PMI_SUCCESS - appnum successfully obtained
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to return the size
@*/
int PMI_Get_appnum( int *appnum );
/*@
PMI_Publish_name - publish a name
Input parameters:
. service_name - string representing the service being published
. port - string representing the port on which to contact the service
Return values:
+ PMI_SUCCESS - port for service successfully published
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to publish service
@*/
int PMI_Publish_name( const char service_name[], const char port[] );
/*@
PMI_Unpublish_name - unpublish a name
Input parameters:
. service_name - string representing the service being unpublished
Return values:
+ PMI_SUCCESS - port for service successfully published
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to unpublish service
@*/
int PMI_Unpublish_name( const char service_name[] );
/*@
PMI_Lookup_name - lookup a service by name
Input parameters:
. service_name - string representing the service being published
Output parameters:
. port - string representing the port on which to contact the service
Return values:
+ PMI_SUCCESS - port for service successfully obtained
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to lookup service
@*/
int PMI_Lookup_name( const char service_name[], char port[] );
/*@
PMI_Barrier - barrier across the process group
Return values:
+ PMI_SUCCESS - barrier successfully finished
- PMI_FAIL - barrier failed
Notes:
This function is a collective call across all processes in the process group
the local process belongs to. It will not return until all the processes
have called 'PMI_Barrier()'.
@*/
int PMI_Barrier( void );
/*@
PMI_Abort - abort the process group associated with this process
Input Parameters:
+ exit_code - exit code to be returned by this process
- error_msg - error message to be printed
Return values:
. none - this function should not return
@*/
int PMI_Abort(int exit_code, const char error_msg[]);
/* PMI Keymap functions */
/*@
PMI_KVS_Get_my_name - obtain the name of the keyval space the local process group has access to
Input Parameters:
. length - length of the kvsname character array
Output Parameters:
. kvsname - a string that receives the keyval space name
Return values:
+ PMI_SUCCESS - kvsname successfully obtained
. PMI_ERR_INVALID_ARG - invalid argument
. PMI_ERR_INVALID_LENGTH - invalid length argument
- PMI_FAIL - unable to return the kvsname
Notes:
This function returns the name of the keyval space that this process and all
other processes in the process group have access to. The output parameter,
kvsname, must be at least as long as the value returned by
'PMI_KVS_Get_name_length_max()'.
@*/
int PMI_KVS_Get_my_name( char kvsname[], int length );
/*@
PMI_KVS_Get_name_length_max - obtain the length necessary to store a kvsname
Output Parameter:
. length - maximum length required to hold a keyval space name
Return values:
+ PMI_SUCCESS - length successfully set
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to set the length
Notes:
This function returns the string length required to store a keyval space name.
A routine is used rather than setting a maximum value in 'pmi.h' to allow
different implementations of PMI to be used with the same executable. These
different implementations may allow different maximum lengths; by using a
routine here, we can interface with a variety of implementations of PMI.
@*/
int PMI_KVS_Get_name_length_max( int *length );
/*@
PMI_KVS_Get_key_length_max - obtain the length necessary to store a key
Output Parameter:
. length - maximum length required to hold a key string.
Return values:
+ PMI_SUCCESS - length successfully set
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to set the length
Notes:
This function returns the string length required to store a key.
@*/
int PMI_KVS_Get_key_length_max( int *length );
/*@
PMI_KVS_Get_value_length_max - obtain the length necessary to store a value
Output Parameter:
. length - maximum length required to hold a keyval space value
Return values:
+ PMI_SUCCESS - length successfully set
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - unable to set the length
Notes:
This function returns the string length required to store a value from a
keyval space.
@*/
int PMI_KVS_Get_value_length_max( int *length );
/*@
PMI_KVS_Put - put a key/value pair in a keyval space
Input Parameters:
+ kvsname - keyval space name
. key - key
- value - value
Return values:
+ PMI_SUCCESS - keyval pair successfully put in keyval space
. PMI_ERR_INVALID_KVS - invalid kvsname argument
. PMI_ERR_INVALID_KEY - invalid key argument
. PMI_ERR_INVALID_VAL - invalid val argument
- PMI_FAIL - put failed
Notes:
This function puts the key/value pair in the specified keyval space. The
value is not visible to other processes until 'PMI_KVS_Commit()' is called.
The function may complete locally. After 'PMI_KVS_Commit()' is called, the
value may be retrieved by calling 'PMI_KVS_Get()'. All keys put to a keyval
space must be unique to the keyval space. You may not put more than once
with the same key.
@*/
int PMI_KVS_Put( const char kvsname[], const char key[], const char value[]);
/*@
PMI_KVS_Commit - commit all previous puts to the keyval space
Input Parameters:
. kvsname - keyval space name
Return values:
+ PMI_SUCCESS - commit succeeded
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - commit failed
Notes:
This function commits all previous puts since the last 'PMI_KVS_Commit()' into
the specified keyval space. It is a process local operation.
@*/
int PMI_KVS_Commit( const char kvsname[] );
/*@
PMI_KVS_Get - get a key/value pair from a keyval space
Input Parameters:
+ kvsname - keyval space name
. key - key
- length - length of value character array
Output Parameters:
. value - value
Return values:
+ PMI_SUCCESS - get succeeded
. PMI_ERR_INVALID_KVS - invalid kvsname argument
. PMI_ERR_INVALID_KEY - invalid key argument
. PMI_ERR_INVALID_VAL - invalid val argument
. PMI_ERR_INVALID_LENGTH - invalid length argument
- PMI_FAIL - get failed
Notes:
This function gets the value of the specified key in the keyval space.
@*/
int PMI_KVS_Get( const char kvsname[], const char key[], char value[], int length);
/* PMI Process Creation functions */
/*S
PMI_keyval_t - keyval structure used by PMI_Spawn_mulitiple
Fields:
+ key - name of the key
- val - value of the key
S*/
typedef struct PMI_keyval_t
{
const char * key;
char * val;
} PMI_keyval_t;
/*@
PMI_Spawn_multiple - spawn a new set of processes
Input Parameters:
+ count - count of commands
. cmds - array of command strings
. argvs - array of argv arrays for each command string
. maxprocs - array of maximum processes to spawn for each command string
. info_keyval_sizes - array giving the number of elements in each of the
'info_keyval_vectors'
. info_keyval_vectors - array of keyval vector arrays
. preput_keyval_size - Number of elements in 'preput_keyval_vector'
- preput_keyval_vector - array of keyvals to be pre-put in the spawned keyval space
Output Parameter:
. errors - array of errors for each command
Return values:
+ PMI_SUCCESS - spawn successful
. PMI_ERR_INVALID_ARG - invalid argument
- PMI_FAIL - spawn failed
Notes:
This function spawns a set of processes into a new process group. The 'count'
field refers to the size of the array parameters - 'cmd', 'argvs', 'maxprocs',
'info_keyval_sizes' and 'info_keyval_vectors'. The 'preput_keyval_size' refers
to the size of the 'preput_keyval_vector' array. The 'preput_keyval_vector'
contains keyval pairs that will be put in the keyval space of the newly
created process group before the processes are started. The 'maxprocs' array
specifies the desired number of processes to create for each 'cmd' string.
The actual number of processes may be less than the numbers specified in
maxprocs. The acceptable number of processes spawned may be controlled by
``soft'' keyvals in the info arrays. The ``soft'' option is specified by
mpiexec in the MPI-2 standard. Environment variables may be passed to the
spawned processes through PMI implementation specific 'info_keyval' parameters.
@*/
int PMI_Spawn_multiple(int count,
const char * cmds[],
const char ** argvs[],
const int maxprocs[],
const int info_keyval_sizesp[],
const PMI_keyval_t * info_keyval_vectors[],
int preput_keyval_size,
const PMI_keyval_t preput_keyval_vector[],
int errors[]);
#if defined(__cplusplus)
}
#endif
#endif

58
executer/include/qlmpi.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef __HEADER_QLMPI_H
#define __HEADER_QLMPI_H
/* UerProgram executed */
#define QL_EXEC_END 'E'
/* qlmpiexec_finalize */
#define QL_RET_FINAL 'F'
/* UserProgram resume */
#define QL_RET_RESUME 'R'
/* Connect from ql_mpiexec_start/Finalize*/
#define QL_COM_CONN 'N'
/* Abnormal end */
#define QL_AB_END 'A'
/* Client kind */
/* mpiexec moniter Program */
#define QL_MONITOR 1
/* mcexec */
#define QL_MCEXEC_PRO 2
/* ql_mcexec_start ql_mpiexec_finalize */
#define QL_MPEXEC 3
#define QL_SOCK "ql_sock"
#define QL_MAX_PATH 4096
#define QL_PARAM_PATH "./"
#define QL_PARAM_EXTE ".param"
#define QL_SWAP_PATH "/tmp"
#define QL_SOCKT_PATH "/run/user"
#define QL_NAME "QL_NAME"
#define QL_SWAP_ENV "QL_SWAP_PATH"
#define QL_PARAM_ENV "QL_PARAM_PATH"
#define QL_SOCK_ENV "QL_SOCKET_PATH"
#define QL_BUF_MAX 256
struct client_fd {
int fd; //FD
int client; //Client Kind
char *name; //QL_NAME
int status; //execute status
};
int ql_recv(int fd,char ** buf);
int ql_send(int fd,int command,char *buf);
#define QL_COMMAND '0'
#define QL_ARG '1'
#define QL_ENV '2'
//#define QL_DEBUG
#endif

View File

@@ -0,0 +1,10 @@
#ifndef __HEADER_QLMPILIB_H
#define __HEADER_QLMPILIB_H
int ql_client(int *argc, char ***argv);
#define QL_CONTINUE 1
#define QL_EXIT 0
#endif

View File

@@ -890,9 +890,11 @@ static struct vm_operations_struct rus_vmops = {
static int rus_mmap(struct file *file, struct vm_area_struct *vma)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_MIXEDMAP;
// vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_MIXEDMAP;
vma->vm_flags |= VM_RESERVED | VM_MIXEDMAP;
#else
vma->vm_flags |= VM_DONTDUMP | VM_DONTEXPAND | VM_MIXEDMAP;
// vma->vm_flags |= VM_DONTDUMP | VM_DONTEXPAND | VM_MIXEDMAP;
vma->vm_flags |= VM_DONTDUMP | VM_MIXEDMAP;
#endif
vma->vm_ops = &rus_vmops;
return 0;
@@ -1713,6 +1715,75 @@ out:
return error;
}
#ifdef MCCTRL_KSYM_walk_page_range
static void
(*mcctrl_walk_page_range)(unsigned long addr, unsigned long end, struct mm_walk *walk)
#if MCCTRL_KSYM_walk_page_range
= (void *)MCCTRL_KSYM_walk_page_range;
#else
= &walk_page_range;
#endif
#endif
static int mywalk(pte_t *pte, unsigned long addr, unsigned long next, struct mm_walk *walk)
{
unsigned long pfn;
struct page *page;
if (pte == NULL) {
kprintf("mywalk: ptr(%p)\n", pte);
return 0;
}
pfn = pte_pfn(*pte);
page = pfn_to_page(pfn);
if (page == NULL) {
kprintf("mywalk: pte(%p) page is null\n", pte);
return 0;
}
if (PageLocked(page)) {
kprintf("mywalk: MLOCK (%p)\n", (void*) addr);
}
if (addr > 0x700000 && addr < 0x705000) {
kprintf("mywalk: %p(%lx)\n", (void*) addr, page->flags);
}
return 0;
}
static long pager_req_mlock_list(ihk_os_t os, unsigned long start,
unsigned long end, void *addr, int nent)
{
struct addrpair {
unsigned long start;
unsigned long end;
unsigned long flag;
} *addrpair = (struct addrpair *) addr;
int cnt = 0;
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
kprintf("pager_req_mlock_list: addr(%p)\n", addr);
vma = find_vma(current->mm, 0x7010a0);
for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
if (vma->vm_start < start || vma->vm_start > end) continue;
kprintf("\t%p: %p -- %p\t%lx\n", vma,
(void*)vma->vm_start, (void*)vma->vm_end,
vma->vm_flags & VM_LOCKED);
if (vma->vm_flags & VM_LOCKED) {
kprintf("\t locked\n");
if (++cnt >= nent) { /* last entry is a marker */
addrpair->start = (unsigned long) -1;
goto full;
}
addrpair->start = vma->vm_start;
addrpair->end = vma->vm_end;
addrpair->flag = vma->vm_flags;
addrpair++;
}
}
full:
return cnt;
}
static long pager_call(ihk_os_t os, struct syscall_request *req)
{
long ret;
@@ -1726,6 +1797,7 @@ static long pager_call(ihk_os_t os, struct syscall_request *req)
#define PAGER_REQ_MAP 0x0005
#define PAGER_REQ_PFN 0x0006
#define PAGER_REQ_UNMAP 0x0007
#define PAGER_REQ_MLOCK_LIST 0x0008
case PAGER_REQ_CREATE:
ret = pager_req_create(os, req->args[1], req->args[2]);
break;
@@ -1754,7 +1826,11 @@ static long pager_call(ihk_os_t os, struct syscall_request *req)
case PAGER_REQ_UNMAP:
ret = pager_req_unmap(os, req->args[1]);
break;
case PAGER_REQ_MLOCK_LIST:
ret = pager_req_mlock_list(os, (unsigned long) req->args[1],
(unsigned long) req->args[2],
(void*) req->args[3], (int) req->args[4]);
break;
default:
ret = -ENOSYS;
printk("pager_call(%#lx):unknown req %ld\n", req->args[0], ret);

View File

@@ -1,22 +1,33 @@
CC=@CC@
MCC=mpicc
BINDIR=@BINDIR@
SBINDIR=@SBINDIR@
prefix=@prefix@
exec_prefix=@exec_prefix@
LIBDIR=@libdir@
MCKERNEL_INCDIR=@MCKERNEL_INCDIR@
MCKERNEL_LIBDIR=@MCKERNEL_LIBDIR@
KDIR ?= @KDIR@
CFLAGS=-Wall -O -I. -I$(VPATH)/arch/${ARCH}
LDFLAGS=@LDFLAGS@
VPATH=@abs_srcdir@
TARGET=mcexec libsched_yield
@uncomment_if_ENABLE_MEMDUMP@TARGET+=eclair
LIBS=@LIBS@
ARCH=@ARCH@
IHKDIR ?= $(VPATH)/../../../ihk/linux/include/
MCEXEC_LIBS=-lmcexec -lrt -lnuma -pthread
ENABLE_QLMPI=@ENABLE_QLMPI@
ifeq ($(ENABLE_QLMPI),yes)
MCEXEC_LIBS += -lmpi
TARGET+= libqlmpi.so ql_server ql_mpiexec_start ql_mpiexec_finalize ql_talker libqlfort.so
endif
all: $(TARGET)
mcexec: mcexec.c libmcexec.a
$(CC) -I${KDIR} $(CFLAGS) $(EXTRA_CFLAGS) -DLIBDIR=\"$(LIBDIR)\" -fPIE -pie -L. -lmcexec -lrt -lnuma -pthread -o $@ $^ $(EXTRA_OBJS)
$(CC) -I${KDIR} $(CFLAGS) $(EXTRA_CFLAGS) $(LDFLAGS) -DLIBDIR=\"$(LIBDIR)\" -fPIE -pie -L. $(MCEXEC_LIBS) -o $@ $^ $(EXTRA_OBJS)
eclair: eclair.c
$(CC) $(CFLAGS) -I${IHKDIR} -o $@ $^ $(LIBS)
@@ -27,6 +38,27 @@ libsched_yield: libsched_yield.c
libmcexec.a::
(cd arch/${ARCH}; make)
libqlmpi.so: qlmpilib.c
$(MCC) $(CFLAGS) $(LDFLAGS) -shared -fPIC -o $@ $<
libqlfort.so: libqlfort.c
$(MCC) $(CFLAGS) $(LDFLAGS) -shared -fPIC -o $@ $< -ldl
ql_server: ql_server.c
$(CC) $(CFLAGS) -o $@ $^
ql_mpiexec_start: ql_mpiexec_start.o md5.o
$(CC) $^ $(CFLAGS) -pthread -o $@
ql_mpiexec_finalize.o: ql_mpiexec_start.c
$(CC) $(CFLAGS) -DQL_MPIEXEC_FINALIZE -c -o $@ $<
ql_mpiexec_finalize: ql_mpiexec_finalize.o md5.o
$(CC) $^ $(CFLAGS) -pthread -o $@
ql_talker: ql_talker.o
$(CC) $^ $(CFLAGS) -o $@
clean::
(cd arch/${ARCH}; make clean)
$(RM) $(TARGET) *.o
@@ -39,5 +71,13 @@ install::
install -m 755 mcexec $(BINDIR)
mkdir -p -m 755 $(MCKERNEL_LIBDIR)
install -m 755 libsched_yield.so.1.0.0 $(MCKERNEL_LIBDIR)
ifeq ($(ENABLE_QLMPI),yes)
install -m 644 ../include/qlmpilib.h $(MCKERNEL_INCDIR)
install -m 755 libqlmpi.so $(MCKERNEL_LIBDIR)
install -m 755 libqlfort.so $(MCKERNEL_LIBDIR)
install -m 755 ql_server $(SBINDIR)
install -m 755 ql_mpiexec_start $(BINDIR)
install -m 755 ql_mpiexec_finalize $(BINDIR)
install -m 755 ql_talker $(SBINDIR)
endif
@uncomment_if_ENABLE_MEMDUMP@install -m 755 eclair $(BINDIR)

101
executer/user/libqlfort.c Normal file
View File

@@ -0,0 +1,101 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
static int *mck_ql_argc;
static char ***mck_ql_argv;
static int (*intel_iargc)();
static int (*intel_getarg)(int *, char *, int, int);
static int (*gfortran_iargc)();
static int (*gfortran_getarg)(int *, char *, int);
static void (*mpi_init)(int *);
static int dl_init_flag;
static inline void
init()
{
if (dl_init_flag)
return;
mck_ql_argc = dlsym(RTLD_NEXT, "mck_ql_argc");
mck_ql_argv = dlsym(RTLD_NEXT, "mck_ql_argv");
intel_iargc = dlsym(RTLD_NEXT, "for_iargc");
intel_getarg = dlsym(RTLD_NEXT, "for_getarg");
gfortran_iargc = dlsym(RTLD_NEXT, "_gfortran_iargc");
gfortran_getarg = dlsym(RTLD_NEXT, "_gfortran_getarg_i4");
mpi_init = dlsym(RTLD_NEXT, "mpi_init_");
dl_init_flag = 1;
}
// for GNU Fortran
int
_gfortran_iargc()
{
init();
if (mck_ql_argc && mck_ql_argv && *mck_ql_argv)
return *mck_ql_argc - 1;
if (gfortran_iargc)
return gfortran_iargc();
return 0;
}
void
_gfortran_getarg_i4(int *n, char *arg, int arg_len)
{
int l;
init();
if (mck_ql_argc && mck_ql_argv && *mck_ql_argv) {
memset(arg, ' ', arg_len);
if (*n < 0 || *n > *mck_ql_argc)
return;
l = strlen((*mck_ql_argv)[*n]);
if (l > arg_len)
l = arg_len;
strncpy(arg, (*mck_ql_argv)[*n], l);
return;
}
if (gfortran_getarg) {
gfortran_getarg(n, arg, arg_len);
return;
}
return;
}
// for Intel Fortran
int
for_iargc()
{
init();
if (mck_ql_argc && mck_ql_argv && *mck_ql_argv)
return *mck_ql_argc - 1;
if (intel_iargc)
return intel_iargc();
return 0;
}
void
for_getarg(int *n, char *arg, int dmy1, int arg_len)
{
int l;
init();
if (mck_ql_argc && mck_ql_argv && *mck_ql_argv) {
memset(arg, ' ', arg_len);
if (*n < 0 || *n > *mck_ql_argc)
return;
l = strlen((*mck_ql_argv)[*n]);
if (l > arg_len)
l = arg_len;
strncpy(arg, (*mck_ql_argv)[*n], l);
return;
}
if (intel_getarg) {
intel_getarg(n, arg, dmy1, arg_len);
return;
}
return;
}

View File

@@ -73,7 +73,12 @@
#include "../../config.h"
#include <numa.h>
#include <numaif.h>
#include <spawn.h>
#include <sys/personality.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "../include/pmi.h"
#include "../include/qlmpi.h"
//#define DEBUG
@@ -1568,6 +1573,37 @@ opendev()
return fd;
}
static void ld_preload_init()
{
char envbuf[PATH_MAX];
char *old_ld_preload;
if (disable_sched_yield) {
sprintf(envbuf, "%s/libsched_yield.so.1.0.0", MCKERNEL_LIBDIR);
__dprintf("%s: %s\n", __FUNCTION__, sched_yield_lib_path);
if (setenv("LD_PRELOAD", envbuf, 1) < 0) {
printf("%s: warning: failed to set LD_PRELOAD for sched_yield\n",
__FUNCTION__);
}
}
/* Set LD_PRELOAD to McKernel specific value */
else if (getenv(ld_preload_envname)) {
if (setenv("LD_PRELOAD", getenv(ld_preload_envname), 1) < 0) {
printf("%s: warning: failed to set LD_PRELOAD environment variable\n",
__FUNCTION__);
}
unsetenv(ld_preload_envname);
}
#ifdef ENABLE_QLMPI
sprintf(envbuf, "%s/libqlfort.so", MCKERNEL_LIBDIR);
if ((old_ld_preload = getenv("LD_PRELOAD"))) {
sprintf(strchr(envbuf, '\0'), " %s", old_ld_preload);
}
setenv("LD_PRELOAD", envbuf, 1);
#endif
}
int main(int argc, char **argv)
{
int ret = 0;
@@ -1683,24 +1719,7 @@ int main(int argc, char **argv)
if (opendev() == -1)
exit(EXIT_FAILURE);
if (disable_sched_yield) {
char sched_yield_lib_path[PATH_MAX];
sprintf(sched_yield_lib_path, "%s/libsched_yield.so.1.0.0",
MCKERNEL_LIBDIR);
__dprintf("%s: %s\n", __FUNCTION__, sched_yield_lib_path);
if (setenv("LD_PRELOAD", sched_yield_lib_path, 1) < 0) {
printf("%s: warning: failed to set LD_PRELOAD for sched_yield\n",
__FUNCTION__);
}
}
/* Set LD_PRELOAD to McKernel specific value */
else if (getenv(ld_preload_envname)) {
if (setenv("LD_PRELOAD", getenv(ld_preload_envname), 1) < 0) {
printf("%s: warning: failed to set LD_PRELOAD environment variable\n",
__FUNCTION__);
}
unsetenv(ld_preload_envname);
}
ld_preload_init();
/* Collect environment variables */
envs_len = flatten_strings(-1, NULL, environ, &envs);
@@ -3416,6 +3435,194 @@ return_execve2:
}
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
break;
case 801: {// swapout
#ifdef ENABLE_QLMPI
int rc;
int spawned;
int rank;
int ql_fd = -1;
int len;
struct sockaddr_un unix_addr;
char msg_buf[QL_BUF_MAX];
char *ql_name;
rc = PMI_Init(&spawned);
if (rc != 0) {
fprintf(stderr, "swapout(): ERROR: failed to init PMI\n");
ret = -1;
goto return_swapout;
}
rc = PMI_Get_rank(&rank);
if (rc != 0) {
fprintf(stderr, "swapout(): ERROR: failed to get Rank\n");
ret = -1;
goto return_swapout;
}
// swap synchronization
rc = PMI_Barrier();
if (rank == 0) {
// tell ql_server what calculation is done.
ql_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (ql_fd < 0) {
fprintf(stderr, "swapout(): ERROR: failed to open socket\n");
ret = -1;
goto return_swapout;
}
unix_addr.sun_family = AF_UNIX;
strcpy(unix_addr.sun_path, getenv("QL_SOCKET_FILE"));
len = sizeof(unix_addr.sun_family) + strlen(unix_addr.sun_path) + 1;
rc = connect(ql_fd, (struct sockaddr*)&unix_addr, len);
if (rc < 0) {
fprintf(stderr, "swapout(): ERROR: failed to connect ql_server\n");
ret = -1;
goto return_swapout;
}
ql_name = getenv(QL_NAME);
sprintf(msg_buf, "%c %04x %s",
QL_EXEC_END, (unsigned int)strlen(ql_name), ql_name);
rc = send(ql_fd, msg_buf, strlen(msg_buf) + 1, 0);
if (rc < 0) {
fprintf(stderr, "swapout(): ERROR: failed to send QL_EXEC_END\n");
ret = -1;
goto return_swapout;
}
// wait resume-req from ql_server.
#ifdef QL_DEBUG
fprintf(stdout, "INFO: waiting resume-req ...\n");
#endif
rc = recv(ql_fd, msg_buf, strlen(msg_buf) + 1, 0);
if (rc < 0) {
fprintf(stderr, "swapout(): ERROR: failed to recieve\n");
ret = -1;
goto return_swapout;
}
// parse message
if (msg_buf[0] == QL_RET_RESUME) {
#ifdef QL_DEBUG
fprintf(stdout, "INFO: recieved resume-req\n");
#endif
}
else {
fprintf(stderr, "swapout(): ERROR: recieved unexpected requsest from ql_server\n");
ret = -1;
goto return_swapout;
}
// resume-req synchronization
rc = PMI_Barrier();
}
else {
// resume-req synchronization
rc = PMI_Barrier();
}
ret = 0;
return_swapout:
if (ql_fd >= 0) {
close(ql_fd);
}
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
#else
printf("mcexec has not been compiled with ENABLE_QLMPI\n");
ret = -1;
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
#endif // ENABLE_QLMPI
break;
}
case 802: /* debugging purpose */
printf("linux mlock(%p, %ld)\n",
(void *)w.sr.args[0], w.sr.args[1]);
printf("str(%p)=%s", (void*)w.sr.args[0], (char*)w.sr.args[0]);
ret = mlock((void *)w.sr.args[0], w.sr.args[1]);
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
break;
#ifndef ARG_MAX
#define ARG_MAX 256
#endif
case 811: { // linux_spawn
int rc, i;
pid_t pid;
size_t slen;
char *exec_path = NULL;
char* argv[ARG_MAX];
char** spawn_args = (char**)w.sr.args[1];
if (!w.sr.args[0] || ! spawn_args) {
fprintf(stderr, "linux_spawn(): ERROR: invalid argument \n");
ret = -1;
goto return_linux_spawn;
}
// copy exec_path
slen = strlen((char*)w.sr.args[0]) + 1;
if (slen <= 0 || slen >= PATH_MAX) {
fprintf(stderr, "linux_spawn(): ERROR: invalid exec_path \n");
ret = -1;
goto return_linux_spawn;
}
exec_path = malloc(slen);
if (!exec_path) {
fprintf(stderr, "linux_spawn(): ERROR: failed to allocating exec_path\n");
ret = -1;
goto return_linux_spawn;
}
memset(exec_path, '\0', slen);
rc = do_strncpy_from_user(fd, exec_path, (void *)w.sr.args[0], slen);
if (rc < 0) {
fprintf(stderr, "linux_spawn(): ERROR: failed to strncpy from user\n");
ret = -1;
goto return_linux_spawn;
}
// copy args to argv[]
for (i = 0; spawn_args[i] != NULL; i++) {
slen = strlen(spawn_args[i]) + 1;
argv[i] = malloc(slen);
if (!argv[i]) {
fprintf(stderr, "linux_spawn(): ERROR: failed to allocating argv[%d]\n", i);
ret = -1;
goto return_linux_spawn;
}
memset(argv[i], '\0', slen);
rc = do_strncpy_from_user(fd, argv[i], spawn_args[i], slen);
if (rc < 0) {
fprintf(stderr, "linux_spawn(): ERROR: failed to strncpy from user\n");
ret = -1;
goto return_linux_spawn;
}
}
rc = posix_spawn(&pid, exec_path, NULL, NULL, argv, NULL);
if (rc != 0) {
fprintf(stderr, "linux_spawn(): ERROR: posix_spawn returned %d\n", rc);
ret = -1;
goto return_linux_spawn;
}
ret = 0;
return_linux_spawn:
// free allocated memory
if (exec_path) {
free(exec_path);
}
for (i = 0; argv[i] != NULL; i++) {
free(argv[i]);
}
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
break;
}
default:
ret = do_generic_syscall(&w);

381
executer/user/md5.c Normal file
View File

@@ -0,0 +1,381 @@
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#include "../include/md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}

File diff suppressed because it is too large Load Diff

597
executer/user/ql_server.c Normal file
View File

@@ -0,0 +1,597 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/un.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <alloca.h>
#include <unistd.h>
#include <fcntl.h>
#include "../include/qlmpi.h"
#define NALLOC 10
#define NOLOG
#ifndef NOLOG
#define LOGFILE "ql_server.log"
int log_open(char *f_name);
int log_close();
void log_printf(const char *format, ...);
void log_dump(struct client_fd *fd_list,int fd_size);
FILE * log_fp;
#endif
int listen_fd = -1;
char file_path[1024];
int check_ql_server( char * path,char * file ,char *filep){
struct stat st;
int rc;
sprintf(filep,"%s/%s",path,file);
rc = stat(filep,&st);
if (rc == 0) {
fprintf(stderr,"socket file exests. %s\n",filep);
return rc;
}
else {
rc = stat(path,&st);
if ( rc == 0) {
fprintf(stderr,"dir(file) exests. %s %d\n",path,rc);
return 1;
}
else {
mode_t m = st.st_mode;
if (S_ISDIR(m)) {
fprintf(stderr,"dir exests. %s %d\n",path,rc);
return rc; /* dir exist */
}
else {
if (mkdir(path, (S_IRUSR | S_IWUSR | S_IRWXU |
S_IRGRP | S_IWGRP | S_IRWXG |
S_IROTH | S_IWOTH | S_IRWXO)) == 0) {
fprintf(stderr,"dir create. %s %d\n",path,rc);
return 1;
}
fprintf(stderr,"mkdir error. %s %d\n",path,rc);
return 0; /* mkdir error */
}
}
}
}
void terminate(int rc){
if (listen_fd >= 0) {
shutdown(listen_fd, 2);
close(listen_fd);
unlink(file_path);
}
#ifndef NOLOG
log_close();
#endif
exit(rc);
}
int s_fd_list(char * p_name,int client_type ,
struct client_fd *fd_list,int fd_size){
int i;
for (i = 0; fd_size > i; i++) {
if ((fd_list[i].client == client_type) &&
(!strcmp(fd_list[i].name,p_name)) &&
(fd_list[i].fd != -1)) {
break;
}
}
return i;
}
int main( int argc, char *argv[]){
int i,j, fd, rc = 0, len, maxfd;
int fd_size ;
struct client_fd *fd_list;
fd_set rset, allset;
struct sockaddr_un unix_addr;
char *buf;
int s_indx;
#ifndef NOLOG
int e_no; /*errno copy*/
#endif
char * null_buff = "";
if (argc < 3 ) {
fprintf(stderr," few args \n");
exit(-1);
}
for (i = 0; i < 4096; i++)
close(i);
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);
if (!check_ql_server(argv[1], argv[2] ,file_path)) {
fprintf(stderr,"ql_server already exists.\n");
exit(-1);
}
signal(SIGINT, terminate);
signal(SIGTERM, terminate);
listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (listen_fd < 0) {
fprintf(stderr,"listen error.\n");
terminate(rc);
}
#ifndef NOLOG
log_open(argv[1]);
#endif
unix_addr.sun_family = AF_UNIX;
strcpy(unix_addr.sun_path, file_path);
#ifndef NOLOG
log_printf("file_path =%s \n",file_path);
#endif
len = sizeof(unix_addr.sun_family) + strlen(unix_addr.sun_path) + 1;
rc = bind(listen_fd, (struct sockaddr *)&unix_addr, len);
if (rc < 0) {
#ifndef NOLOG
log_printf("bind error \n",file_path);
#endif
terminate(rc);
}
// become a daemon
if (fork())
exit(0);
if (fork())
exit(0);
setsid();
rc = listen(listen_fd, 5);
if (rc < 0) {
#ifndef NOLOG
log_printf("listen error \n");
#endif
terminate(rc);
}
FD_ZERO(&allset);
FD_SET(listen_fd, &allset);
maxfd = listen_fd;
fd_size = NALLOC;
fd_list = malloc(sizeof(struct client_fd)*fd_size);
for (i = 0; i < fd_size; i++) {
fd_list[i].fd = -1;
}
#ifndef NOLOG
log_printf("loop_start \n");
#endif
for (;;) {
memcpy(&rset, &allset, sizeof(rset));
rc = select(maxfd + 1, &rset, NULL, NULL, NULL);
if (rc == -1) {
#ifndef NOLOG
e_no = errno;
log_printf("server:select error.\n");
log_printf("select error string by strerror: %s\n",
strerror(e_no));
log_printf("select error code: %d\n", e_no);
#endif
terminate(rc);
}
#ifndef NOLOG
log_printf("server:select.\n");
#endif
if (FD_ISSET(listen_fd, &rset)) {
len = sizeof(unix_addr);
fd = accept(listen_fd, (struct sockaddr *)&unix_addr,
(socklen_t*)&len);
if (fd < 0) {
#ifndef NOLOG
log_printf("server:accept error.\n");
#endif
terminate(fd);
}
#ifndef NOLOG
log_printf("server:accept (%d).\n", fd);
#endif
for (i = 0; fd_size > i; i++) {
if (fd_list[i].fd == -1) {
fd_list[i].fd = fd;
break;
}
}
if (i >= fd_size) {
fd_list = realloc(fd_list,
sizeof(int)*(fd_size+NALLOC));
for (i = fd_size; i < (fd_size + NALLOC); i++) {
fd_list[i].fd = -1;
}
fd_list[fd_size].fd = fd;
fd_size += NALLOC;
}
FD_SET(fd, &allset);
if (fd > maxfd) {
maxfd = fd;
}
}
for (i = 0; i < fd_size; i++) {
if (fd_list[i].fd == -1)
continue;
fd = fd_list[i].fd;
if (!FD_ISSET(fd, &rset))
continue;
rc = ql_recv(fd, &buf);
#ifndef NOLOG
log_printf("ql_recv (%d) index = %d fd = %d \n", rc,i,fd);
#endif
if(rc < 0){
#ifndef NOLOG
log_printf("server:recv (%d) error.\n", fd);
#endif
terminate(rc);
}
if (rc == 0) {
#ifndef NOLOG
log_printf("server:closed (%d).\n", fd);
#endif
fd_list[i].fd = -1;
if (strcmp(fd_list[i].name,null_buff)) {
free(fd_list[i].name);
fd_list[i].name = null_buff;
}
FD_CLR(fd, &allset);
maxfd = -1;
for (j = 0; fd_size > j ; j++) {
if (fd > maxfd) {
maxfd = fd;
}
}
close(fd);
#ifndef NOLOG
log_printf("index = %d\n",i);
log_dump(fd_list,fd_size);
#endif
if (maxfd == -1) {
terminate(rc);
}
continue;
}
if (rc == QL_EXEC_END){ /* swapout from mcexec */
fd_list[i].client = QL_MCEXEC_PRO;
fd_list[i].name = buf;
fd_list[i].status = QL_EXEC_END;
#ifndef NOLOG
log_printf("index = %d\n",i);
log_dump(fd_list,fd_size);
#endif
/* send E command to ql_talker */
if ((s_indx = s_fd_list(fd_list[i].name,
QL_MPEXEC,fd_list,
fd_size)) < fd_size) {
#ifndef NOLOG
log_printf("E command to talker %d \n",s_indx);
#endif
rc = ql_send(fd_list[s_indx].fd,
QL_EXEC_END,NULL);
/* fd close for ql_talker */
FD_CLR(fd_list[s_indx].fd, &allset);
maxfd = -1;
close(fd_list[s_indx].fd);
free(fd_list[s_indx].name);
fd_list[s_indx].fd = -1;
fd_list[s_indx].name = null_buff;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
if (maxfd == -1) terminate(0);
}
else{
/* ql_talker not found */
#ifndef NOLOG
log_printf("ql_talker not found\n",i);
#endif
/* send I command to mcexec and param_file put A command*/
}
#ifndef NOLOG
log_printf("index = %d\n",i);
log_dump(fd_list,fd_size);
#endif
}
else if (rc == QL_RET_RESUME) {
/* recv R command from ql_talker */
fd_list[i].client = QL_MPEXEC;
fd_list[i].name = buf;
fd_list[i].status = QL_RET_RESUME;
#ifndef NOLOG
log_printf("index = %d,fd_size=%d\n",
i,fd_size);
log_dump(fd_list,fd_size);
#endif
/* send R command to mcexec */
if (((s_indx = s_fd_list(fd_list[i].name,
QL_MCEXEC_PRO ,
fd_list,fd_size)) < fd_size) &&
fd_list[s_indx].status == QL_EXEC_END) {
#ifndef NOLOG
log_printf("R command to mcexec %d \n",s_indx);
log_dump(fd_list,fd_size);
#endif
rc = ql_send(fd_list[s_indx].fd,
QL_RET_RESUME,NULL);
fd_list[s_indx].status = QL_RET_RESUME;
FD_CLR(fd_list[s_indx].fd, &allset);
close(fd_list[s_indx].fd);
free(fd_list[s_indx].name);
fd_list[s_indx].fd = -1;
fd_list[s_indx].name = null_buff;
maxfd = -1;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
if (maxfd == -1) terminate(0);
}
else{
/* mcexec not found */
/* send A command to ql_talker */
#ifndef NOLOG
log_printf("send A command index = %d,fd_size=%d\n",
i,fd_size);
log_dump(fd_list,fd_size);
#endif
rc = ql_send(fd_list[i].fd,
QL_AB_END,NULL);
/* fd close for ql_talker */
FD_CLR(fd_list[i].fd, &allset);
close(fd_list[i].fd);
free(fd_list[i].name);
fd_list[i].fd = -1;
// fd_list[i].name = NULL;
fd_list[i].name = null_buff;
maxfd = -1;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
if (maxfd == -1) terminate(0);
}
#ifndef NOLOG
log_printf("index = %d,s_indx=%d\n",
i,s_indx);
log_dump(fd_list,fd_size);
#endif
}
else if (rc == QL_COM_CONN) {
/* connect from ql_mpiexec_* */
fd_list[i].client = QL_MPEXEC;
fd_list[i].name = buf;
fd_list[i].status = QL_COM_CONN;
#ifndef NOLOG
log_printf("N command index = %d,fd_size=%d\n",
i,fd_size);
log_dump(fd_list,fd_size);
#endif
if ((s_indx = s_fd_list(fd_list[i].name,
QL_MCEXEC_PRO,fd_list,
fd_size)) < fd_size) {
rc = ql_send(fd_list[i].fd,
QL_EXEC_END,NULL);
/* fd close for ql_talker */
FD_CLR(fd_list[i].fd, &allset);
maxfd = -1;
close(fd_list[i].fd);
free(fd_list[i].name);
fd_list[i].fd = -1;
fd_list[i].name = null_buff;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
// if (maxfd == -1) terminate(0);
}
#ifndef NOLOG
log_dump(fd_list,fd_size);
#endif
}
else if(rc == QL_RET_FINAL) {
/* F command from Monitor Process */
fd_list[i].client = QL_MONITOR;
fd_list[i].name = buf;
fd_list[i].status = QL_RET_FINAL;
#ifndef NOLOG
log_printf("F command index = %d,fd_size=%d\n",
i,fd_size);
log_dump(fd_list,fd_size);
#endif
/* search ql_mpiexec_start process */
if ((s_indx = s_fd_list(fd_list[i].name,
QL_MPEXEC,fd_list,
fd_size)) < fd_size) {
/* send A command */
rc = ql_send(fd_list[s_indx].fd,
QL_AB_END,NULL);
/* table clear */
FD_CLR(fd_list[s_indx].fd, &allset);
maxfd = -1;
close(fd_list[s_indx].fd);
free(fd_list[s_indx].name);
fd_list[s_indx].fd = -1;
fd_list[s_indx].name = null_buff;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
}
/* search mcexec process */
if ((s_indx = s_fd_list(fd_list[i].name,
QL_MCEXEC_PRO,fd_list,
fd_size)) < fd_size) {
/* table clear */
FD_CLR(fd_list[s_indx].fd, &allset);
maxfd = -1;
close(fd_list[s_indx].fd);
free(fd_list[s_indx].name);
fd_list[s_indx].fd = -1;
fd_list[s_indx].name = null_buff;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
}
FD_CLR(fd_list[i].fd, &allset);
close(fd_list[i].fd);
free(fd_list[i].name);
fd_list[i].fd = -1;
fd_list[i].name = null_buff;
maxfd = -1;
for (j = 0; fd_size > j ; j++) {
if (fd_list[j].fd > maxfd) {
maxfd = fd_list[j].fd;
}
}
#ifndef NOLOG
log_printf("F command end index = %d,fd_size=%d\n",
i,fd_size);
log_dump(fd_list,fd_size);
#endif
if (maxfd == -1)
terminate(0);
}
else {
#ifndef NOLOG
log_printf("server:unknwon commond %d (%d).\n",
rc, fd);
#endif
}
#ifndef NOLOG
log_printf("server:recv (%d) .\n", fd);
#endif
}
}
terminate(0);
}
#ifndef NOLOG
int log_open(char *f_path){
char f_name[1024];
sprintf(f_name,"%s/%s",f_path,LOGFILE);
if ((log_fp = fopen(f_name,"w")) == NULL) {
log_fp = stderr;
}
return 0;
}
int log_close(){
if (log_fp != stdout) {
fclose(log_fp);
}
return 0;
}
void log_printf(const char *format, ...){
va_list arglist;
char log[1024];
va_start(arglist, format);
vsprintf(log, format, arglist);
fprintf(log_fp, "%s\n", log);
va_end(arglist);
fflush(log_fp);
}
void log_dump(struct client_fd *fd_list,int fd_size){
int i;
for (i = 0; fd_size > i; i++) {
if (fd_list[i].fd != -1) {
log_printf("|%4d|%4d|%c|%s|\n",fd_list[i].fd,
fd_list[i].client,(char)fd_list[i].status,
fd_list[i].name);
}
else{
log_printf("|%4d|0000| | |\n",fd_list[i].fd);
}
}
log_printf("-----------------------\n");
}
#endif
int ql_recv(int fd,char ** buf){
char l_buf[QL_BUF_MAX];
char comm;
int size = 0;
int rc;
int ret;
rc = recv(fd, l_buf, QL_BUF_MAX, 0);
#ifndef NOLOG
log_printf("rc = %d,l_buf=%s\n",rc,l_buf);
#endif
if (rc <= 0) {
return rc;
}
sscanf(l_buf, "%c %x", &comm, &size);
ret = (int)(comm);
#ifndef NOLOG
log_printf("COMM=%c size = %x rc= %d\n", ret, size, rc);
#endif
if (size > 0) {
*buf = malloc(size+1);
memcpy(*buf, &l_buf[7], size);
buf[size] = 0x00;
#ifndef NOLOG
log_printf("COMM=%c size = %x *buf= %s\n",ret,size,*buf);
#endif
}
#ifndef NOLOG
log_printf("ret = %d\n", ret);
#endif
return ret;
}
int ql_send(int fd,int command,char *buf){
char *lbuf;
int size;
int rc;
if (buf != NULL) {
size = strlen(buf);
lbuf = alloca(size+7+1);
sprintf(lbuf,"%c %04x %s",command,size,buf);
}
else{
size = 0;
lbuf = alloca(6+1);
sprintf(lbuf,"%c 0000",command);
}
#ifndef NOLOG
log_printf("send lbuf=%s",lbuf);
#endif
rc=send(fd,lbuf,strlen(lbuf),0);
return rc;
}

101
executer/user/ql_talker.c Normal file
View File

@@ -0,0 +1,101 @@
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include "../include/qlmpi.h"
int fd = -1;
#define BUF_MAX 256
void terminate(int rc)
{
if(fd >= 0){
shutdown(fd, 2);
close(fd);
}
exit(rc);
}
int main(int argc, char* argv[])
{
int rc=-1, len;
struct sockaddr_un unix_addr;
char buf[BUF_MAX];
signal(SIGINT, terminate);
signal(SIGTERM, terminate);
if (argc < 5) {
#ifdef QL_DEBUG
printf("too few arguments\n");
#endif
return rc;
}
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
#ifdef QL_DEBUG
printf("client:socket error.\n");
#endif
terminate(rc);
}
#ifdef QL_DEBUG
printf("client:socket.\n");
#endif
unix_addr.sun_family = AF_UNIX;
strcpy(unix_addr.sun_path, argv[4]);
#ifdef QL_DEBUG
printf("socket_path %s\n",argv[4]);
#endif
len = sizeof(unix_addr.sun_family)+strlen(unix_addr.sun_path) + 1;
rc = connect(fd, (struct sockaddr*)&unix_addr, len);
if (rc < 0) {
#ifdef QL_DEBUG
printf("client:connect error.\n");
printf("%s %s\n", unix_addr.sun_path, strerror(errno));
#endif
terminate(rc);
}
if (argv[1][0]) {
sprintf(buf,"%s %04x %s",argv[1],
(unsigned int)strlen(argv[3]),argv[3]);
rc = send(fd, buf, strlen(buf) + 1, 0);
if (rc < 0) {
#ifdef QL_DEBUG
printf("send error.\n");
#endif
terminate(rc);
}
}
if (strcmp(argv[2],"-n")) {
#ifdef QL_DEBUG
printf("waiting reply message from ql_server ...\n");
#endif
rc = recv(fd, buf, 256, 0);
#ifdef QL_DEBUG
printf("%s\n",buf);
#endif
if (rc < 0) {
#ifdef QL_DEBUG
printf("recv error\n");
#endif
terminate(rc);
}
if (buf[0] == argv[2][0]){
terminate(0);
}
if (buf[0] == QL_AB_END){
/* abnormal end */
terminate(-2);
}
}
terminate(0);
return rc; /*not reached */
}

320
executer/user/qlmpilib.c Normal file
View File

@@ -0,0 +1,320 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <errno.h>
#include "mpi.h"
#include "../include/qlmpilib.h"
#include "../include/qlmpi.h"
#include "../include/pmi.h"
#define BUF_SIZE (32*1024)
#define NALLOC 10
#define QL_SUCCESS 0
#define QL_NORMAL 2
//#define QL_DEBUG
static char ql_name[33];
static char swap_file[1024];
static char param_file[1024];
static int ql_mode_flg = 0; /* 0 is normal */
static int rank = -1;
static char buffer[BUF_SIZE];
static int ql_initialized;
int mck_ql_argc = NALLOC;
char **mck_ql_argv;
char **mck_ql_env;
static void freev(char **v)
{
char **a;
for (a = v; *a; a++)
free(*a);
free(v);
}
static void esc_get(char *in, char *out)
{
char *p;
char *q;
int c;
for (p = in, q = out; *p; p++) {
if (*p == '%' && p[1] && p[2]) {
int i;
for (i = 0, c = 0; i < 2; i++) {
p++;
c <<= 4;
if (*p >= '0' && *p <= '9')
c += *p - '0';
else if (*p >= 'A' && *p <= 'F')
c += *p - 'A' + 10;
else if (*p >= 'a' && *p <= 'f')
c += *p - 'a' + 10;
}
*(q++) = c;
}
else
*(q++) = *p;
}
*q = '\0';
}
static int swapout(char *fname, void *buf, size_t sz, int flag)
{
int cc;
cc = syscall(801, fname, buf, sz, flag);
return cc;
}
static int ql_get_option() {
char *env_str;
env_str = getenv(QL_NAME);
if (env_str == NULL) {
return 0;
}
else{
strcpy(ql_name,env_str);
return 1;
}
}
int ql_init() {
char tmp_path[1024];
char *env_str;
if (ql_initialized) {
return QL_CONTINUE;
}
ql_mode_flg = ql_get_option();
#ifdef QL_DEBUG
printf("flg = %d \n",ql_mode_flg);
#endif
if (ql_mode_flg) {
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
/* get param_file path */
env_str = getenv(QL_PARAM_ENV);
if (env_str == NULL) {
sprintf(tmp_path,"%s/",getenv("HOME"));
}
else{
sprintf(tmp_path,"%s/",env_str);
}
sprintf(param_file,"%s%s%s",tmp_path,ql_name,QL_PARAM_EXTE);
#ifdef QL_DEBUG
printf("param_file = %s\n",param_file);
#endif
/* get swap_file path*/
env_str = getenv(QL_SWAP_ENV);
if (env_str == NULL) {
strcpy(tmp_path,QL_SWAP_PATH);
}
else{
strcpy(tmp_path,env_str);
}
sprintf(swap_file,"%s/%s%d",tmp_path,ql_name,rank);
#ifdef QL_DEBUG
printf("swap_file = %s rank=%d\n",swap_file,rank);
#endif
ql_initialized = 1;
return QL_SUCCESS;
}
ql_initialized = 1;
return QL_NORMAL;
}
int ql_client(int *argc,char ***argv)
{
int rc;
int ret = QL_EXIT;
char buf[4096];
FILE *fp;
char **envs;
char **args;
char **a;
char **e;
if (ql_mode_flg == 0) return(QL_EXIT);
syscall(803);
rc = PMI_Barrier();
rc = swapout(swap_file, buffer, BUF_SIZE, 0);
#ifdef QL_DEBUG
printf(" swapout rc=%d\n",rc);
#endif
if (rc == -1) {
/* terminate due to swap error */
syscall(804);
return QL_EXIT;
}
/* param file */
if ((fp = fopen(param_file,"r")) == NULL) {
/* param file open error */
#ifdef QL_DEBUG
printf("param_file open error\n");
#endif
syscall(804);
return QL_EXIT;
}
a = args = NULL;
e = envs = NULL;
while ((fgets(buf, 4096, fp)) != NULL) {
int cmd = buf[0];
char *t;
int n;
// remove return code
buf[strlen(buf) - 1] = '\0';
if (cmd == QL_COMMAND) {
t = strchr(buf, '=');
if (!t ||
(t[1] != QL_RET_RESUME && t[1] != QL_RET_FINAL)) {
fprintf(stderr, "invalid file format\n");
exit(1);
}
t++;
if (*t == QL_RET_RESUME) {
ret = QL_CONTINUE;
#ifdef QL_DEBUG
printf("COM = %c ret = %d\n", *t, ret);
#endif
}
else {
ret = QL_EXIT;
#ifdef QL_DEBUG
printf(" ret = %d",ret);
#endif
}
t = strchr(t, ' ');
if (t) {
n = atoi(t + 1);
args = malloc(sizeof(char *) * (n + 1));
a = args;
t = strchr(t + 1, ' ');
if (t) {
n = atoi(t + 1);
envs = malloc(sizeof(char *) * (n + 1));
e = envs;
}
}
}
else if (cmd == QL_ARG) {
if (!args)
continue;
t = strchr(buf, ' ');
if (!t)
continue;
n = atoi(t + 1);
t = strchr(t + 1, ' ');
if (!t)
continue;
t++;
*a = malloc(n + 1);
esc_get(t, *a);
a++;
}
else if (cmd == QL_ENV) {
if (!envs)
continue;
t = strchr(buf, ' ');
if (!t)
continue;
n = atoi(t + 1);
t = strchr(t + 1, ' ');
if (!t)
continue;
t++;
*e = malloc(n + 1);
esc_get(t, *e);
e++;
}
else {
}
}
fclose(fp);
if (args) {
*a = NULL;
if (mck_ql_argv)
freev(mck_ql_argv);
mck_ql_argv = args;
if (argv)
*argv = args;
for (mck_ql_argc = 0; mck_ql_argv[mck_ql_argc]; mck_ql_argc++);
if (argc)
*argc = mck_ql_argc;
}
if (envs) {
*e = NULL;
if (mck_ql_env)
freev(mck_ql_env);
mck_ql_env = envs;
environ = envs;
}
syscall(804);
#ifdef QL_DEBUG
printf(" return rtn = %d\n",ret);
#endif
return ret;
}
int MPI_Init(int *argc,char ***argv){
int rc = 0;
rc = PMPI_Init(argc,argv);
if (rc == MPI_SUCCESS)
ql_init();
return rc;
}
void
mpi_init_(int *ierr)
{
extern void pmpi_init_(int *ierr) __attribute__ ((__weak__));
if (!pmpi_init_) {
*ierr = MPI_ERR_OTHER;
return;
}
pmpi_init_(ierr);
if (*ierr == MPI_SUCCESS)
ql_init();
return;
}
void ql_client_(int *ierr)
{
int argc;
char **argv;
*ierr = ql_client(&argc, &argv);
}