123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*
- * mpipack.c
- *
- * Packing stuff into buffers for cross-PE communication
- */
-
- /*
- * This code may be used and modified, and redistributed in binary
- * or source form, subject to the "CCL Public License", which should
- * accompany it. This license is a variant on the BSD license, and thus
- * permits use of code derived from this in either open and commercial
- * projects: but it does require that updates to this code be made
- * available back to the originators of the package.
- * Before merging other code in with this or linking this code
- * with other packages or libraries please check that the license terms
- * of the other material are compatible with those of this.
- */
- /* Signature: 2d67b138 18-Apr-2002 */
- #ifndef header_mpipack_h
- #define header_mpipack_h
- /* Code to pack a Lisp cons-structure into a linear buffer and retrieve it. */
- /* These are the calls to do it; think of them as
- * void pack_object(Lisp_Object a);
- * and Lisp_Object unpack_object();
- */
- #define pack_object(a) (mpi_pack_buffer = 0, \
- mpi_pack_position = 0, \
- mpi_pack_size = 0, \
- pack_cell(a) )
- /* Once a message has been packed, it may be sent using mpi_pack_buffer and
- * mpi_pack_position as the "buf" and "count" fields, and MPI_PACKED as the
- * Datatype.
- */
- /* mpi_pack_buffer should be set to the recieve buffer before calling this. */
- #define unpack_object() (mpi_pack_position = 0, unpack_cell())
- /* There must be a buffer to put them in.
- * It will grow by MPI_BUFFER_BLOCK bytes at a time, as needed.
- */
- static char* mpi_pack_buffer = 0;
- static int mpi_pack_size = 0;
- #define MPI_BUFFER_BLOCK 1024
- /* position marker for MPI_(Un)Pack */
- static int mpi_pack_position = 0;
- /* THE REST OF THIS FILE IS PRIVATE */
- /* Function to check the size of the buffer, and grow it if necessary.
- * check_buffer(n) will make sure that there are n free bytes in the buffer.
- */
- static void default_check_buffer(int n)
- {
- if (mpi_pack_size - mpi_pack_position < n){
- mpi_pack_size += MPI_BUFFER_BLOCK;
- mpi_pack_buffer = (char*)realloc( mpi_pack_buffer, mpi_pack_size);
- if (mpi_pack_buffer == 0) aerror0("Not enough memory for MPI buffer.");
- }
- }
- static char* mpi_buffer_bottom;
- static int mpi_pack_offset;
- static int mpi_real_size;
- static void scatter_check_buffer(int n)
- {
- if (mpi_real_size - ( (mpi_pack_buffer - mpi_buffer_bottom) +
- mpi_pack_position ) < n) {
- mpi_real_size += MPI_BUFFER_BLOCK;
- mpi_pack_size += MPI_BUFFER_BLOCK;
- mpi_buffer_bottom = (char*)realloc( mpi_buffer_bottom, mpi_real_size);
- if (mpi_buffer_bottom == 0) aerror0("Not enough memory for MPI buffer.");
- mpi_pack_buffer = mpi_buffer_bottom + mpi_pack_offset;
- }
- }
- typedef void buffptr(int);
- static buffptr *check_buffer = default_check_buffer;
- /* MPI insists on using pointers everywhere, so here are things to point at. */
- static char mpi_packing_symbols[] = {' ', '(', ')', '.', ','};
- static Lisp_Object mpi_pack_number;
- static char mpi_pack_char;
- /* The MPI function calls for packing */
- /* Think of this as void pack_32bit(Lisp_Object),but it actually returns int */
- /* The name is to remind one that the size is fixed for now. It would be
- * better to conditionally define a type of either MPI_LONG or MPI_LONG_LONG
- * depending on the size of Lisp objects. This may happen eventually.
- */
- #define pack_32bit(n) (check_buffer(4), \
- MPI_Pack(&(n), 1, MPI_UNSIGNED_LONG, \
- mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, MPI_COMM_WORLD) )
- /* The functions to flatten the list structures, according to a simple grammar*/
- static void pack_list(Lisp_Object a);
- static void pack_cell(Lisp_Object a);
- static void pack_atom(Lisp_Object a)
- {
- if (is_fixnum(a)) pack_32bit(a);
- else if (is_bfloat(a)) {
- Header* h = &flthdr(a);
- if (type_of_header(*h) == TYPE_DOUBLE_FLOAT){
- pack_32bit(*h);
- check_buffer(sizeof(double));
- MPI_Pack( &(((Double_Float*)h)->f), 1, MPI_DOUBLE,
- mpi_pack_buffer, mpi_pack_size,
- &mpi_pack_position, MPI_COMM_WORLD);
- }
- else err_printf("Unsupported float type %x\n",type_of_header(*h));
- }
- else if (is_numbers(a)) {
- Header* h = &numhdr(a);
- int size = length_of_header(*h) - sizeof(Header);
- if (type_of_header(*h) == TYPE_BIGNUM){
- pack_32bit(*h);
- /* Bignums are arrays of 32-bit things; we'll have to pack them
- as such to avoid byte-ordering problems. */
- check_buffer(size);
- MPI_Pack(h+1, size >> 2, MPI_UNSIGNED_LONG,
- mpi_pack_buffer, mpi_pack_size, &mpi_pack_position,
- MPI_COMM_WORLD);
- }
- else err_printf("Unsupported number type %x\n",type_of_header(*h));
- }
- else if (is_vector(a)) {
- Header* h = &vechdr(a);
- switch(type_of_header(*h)){
- case TYPE_STRING:
- pack_32bit(*h);
- {
- int size = length_of_header(*h) - sizeof(Header);
- check_buffer(size);
- MPI_Pack(h+1, size, MPI_CHAR,
- mpi_pack_buffer, mpi_pack_size,
- &mpi_pack_position, MPI_COMM_WORLD);
- }
- break;
- case TYPE_SIMPLE_VEC: case TYPE_ARRAY: case TYPE_STRUCTURE:
- pack_32bit(*h);
- {
- int i;
- for (i = 0; i < (length_of_header(*h)>>2) - 1; ++i)
- pack_cell(elt(a,i));
- }
- break;
- default:
- err_printf("Unsupported vector type %x\n",type_of_header(*h));
- }
- }
- else if (is_symbol(a)) {
- Symbol_Head* h = (Symbol_Head*)( (char*)a-TAG_SYMBOL);
- Header My_Head = TYPE_SYMBOL;
- pack_32bit(My_Head);
- pack_atom(h->pname); /* This is a string. */
- }
- else err_printf("Unsupported type %d\n",a & TAG_BITS);
- }
- /* again, think of void pack_xxxx(void); (but actually returning int) */
- #define pack_space() ( check_buffer(1), \
- MPI_Pack(mpi_packing_symbols, 1, MPI_CHAR, \
- mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, MPI_COMM_WORLD) )
- #define pack_open() ( check_buffer(1), \
- MPI_Pack(mpi_packing_symbols+1, 1, MPI_CHAR, \
- mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, MPI_COMM_WORLD) )
- #define pack_close() ( check_buffer(1), \
- MPI_Pack(mpi_packing_symbols+2, 1, MPI_CHAR, \
- mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, MPI_COMM_WORLD) )
- #define pack_dot() ( check_buffer(1), \
- MPI_Pack(mpi_packing_symbols+3, 1, MPI_CHAR, \
- mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, MPI_COMM_WORLD) )
- #define pack_comma() ( check_buffer(1), \
- MPI_Pack(mpi_packing_symbols+4, 1, MPI_CHAR, \
- mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, MPI_COMM_WORLD) )
-
- static void pack_cell(Lisp_Object a)
- {
- /* In Common mode, consp needs nil defined. I don't want to
- * clutter the stack with unnecessary variables, so I don't
- * define it in CSL mode.
- */
- #ifdef COMMON
- Lisp_Object nil = C_nil;
- #endif
- if (consp(a)) pack_open(), pack_cell(qcar(a)), pack_list(qcdr(a));
- else pack_space(), pack_atom(a);
- }
- static void pack_list(Lisp_Object a)
- {
- #ifdef COMMON
- Lisp_Object nil = C_nil;
- #endif
- if (consp(a)) pack_comma(), pack_cell(qcar(a)), pack_list(qcdr(a));
- else if (a == C_nil) pack_close();
- else pack_dot(), pack_atom(a);
- }
- /* Now unpacking... */
- /* The MPI calls */
- /* Think of these as char unpack_char(); Lisp_Object unpack_32bit(); */
- #define unpack_char() (MPI_Unpack(mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, &mpi_pack_char, 1, \
- MPI_CHAR, MPI_COMM_WORLD), \
- mpi_pack_char)
- #define unpack_32bit() (MPI_Unpack(mpi_pack_buffer, mpi_pack_size, \
- &mpi_pack_position, &mpi_pack_number, 1, \
- MPI_UNSIGNED_LONG, MPI_COMM_WORLD), \
- mpi_pack_number)
- /* The functions to parse the linear buffer */
- static Lisp_Object unpack_list(void);
- static Lisp_Object unpack_cell(void);
- static Lisp_Object unpack_atom()
- {
- Lisp_Object a = unpack_32bit();
- if (is_fixnum(a)) return a;
-
- switch (type_of_header(a)){
- int size;
- case TYPE_DOUBLE_FLOAT:
- size = length_of_header(a);
- a = getvector(TAG_BOXFLOAT,TYPE_DOUBLE_FLOAT,size);
- MPI_Unpack(mpi_pack_buffer, mpi_pack_size, &mpi_pack_position,
- /* How ugly is this? */
- &(((Double_Float*)((char*)a - TAG_BOXFLOAT))->f),
- 1, MPI_DOUBLE, MPI_COMM_WORLD);
- return a;
- case TYPE_BIGNUM:
- size = length_of_header(a);
- a = getvector(TAG_NUMBERS,type_of_header(a),size);
- MPI_Unpack(mpi_pack_buffer,mpi_pack_size,&mpi_pack_position,
- (char*)a - TAG_NUMBERS + CELL,
- (size - sizeof(Header))>>2, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- return a;
-
- case TYPE_STRING:
- size = length_of_header(a);
- a = getvector(TAG_VECTOR,TYPE_STRING,size);
- MPI_Unpack(mpi_pack_buffer, mpi_pack_size, &mpi_pack_position,
- (char*)a - TAG_VECTOR + CELL,
- size - sizeof(Header), MPI_CHAR, MPI_COMM_WORLD);
- return a;
-
- case TYPE_SIMPLE_VEC: case TYPE_ARRAY: case TYPE_STRUCTURE:
- size = length_of_header(a);
- push(getvector(TAG_VECTOR,type_of_header(a),size));
- {
- int i;
- for (i=0; i<(size>>2)-1; ++i) elt(*stack,i) = unpack_cell();
- if (!(i&1)) elt(*stack,i) = C_nil;
- }
- return my_pop();
- case TYPE_SYMBOL:
- {
- Lisp_Object nil = C_nil;
- a = unpack_atom(); /* Name in a string */
- return iintern(a, length_of_header(vechdr(a))-CELL, CP, 0);
- }
- default:
- err_printf("Unknown header type %d", type_of_header(a));
- }
- }
- static Lisp_Object unpack_cell(void)
- {
- switch (unpack_char()){
- case ' ': return unpack_atom();
- case '(': return unpack_list();
- default : {err_printf("Syntax error in message.\n"); return C_nil;}
- }
- }
- static Lisp_Object unpack_list(void)
- {
- push(unpack_cell());
- switch (unpack_char()){
- case ')': return cons(my_pop(),C_nil);
- case '.': {Lisp_Object tail = unpack_atom(); return cons(my_pop(), tail);}
- case ',': {Lisp_Object tail = unpack_list(); return cons(my_pop(), tail);}
- default : {err_printf("Syntax error in message.\n"); return (my_pop());}
- }
- }
- #endif
- /* end of mpipack.c */
|