Val _lib7_P_IO_read (Task* task, Val arg) { //=============== // // Mythryl type: (Int, Int) -> vector_of_one_byte_unts::Vector // fd nbytes // // Read the specified number of bytes from the specified file, // returning them in a vector. // // This fn gets bound as read' in: // // src/lib/std/src/psx/posix-io.pkg // src/lib/std/src/psx/posix-io-64.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); Val vec; int n; int fd = GET_TUPLE_SLOT_AS_INT( arg, 0 ); int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 1 ); if (nbytes == 0) return ZERO_LENGTH_STRING__GLOBAL; // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so allocate C space in which to do the read: // Mythryl_Heap_Value_Buffer vec_buf; // { char* c_vec = buffer_mythryl_heap_nonvalue( &vec_buf, nbytes ); // buffer_mythryl_heap_nonvalue is from src/c/main/runtime-state.c do { RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // n = read (fd, c_vec, nbytes); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); // } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. if (n < 0) { unbuffer_mythryl_heap_value( &vec_buf ); return RAISE_SYSERR__MAY_HEAPCLEAN(task, n, NULL); } if (n == 0) { unbuffer_mythryl_heap_value( &vec_buf ); return ZERO_LENGTH_STRING__GLOBAL; } // Allocate the vector. // Note that this might trigger a heapcleaning, moving things around: // vec = allocate_nonempty_wordslots_vector__may_heapclean( task, BYTES_TO_WORDS(n), NULL ); memcpy( PTR_CAST(char*, vec), c_vec, n ); unbuffer_mythryl_heap_value( &vec_buf ); } Val result = make_vector_header(task, STRING_TAGWORD, vec, n); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_IO_readbuf (Task* task, Val arg) { //================== // // Mythryl type: (Int, rw_vector_of_one_byte_unts::Rw_Vector, Int, Int) -> Int // fd data nbytes start // // Read nbytes of data from the specified file // into the given array starting at start. // Return the number of bytes read. // Assume bounds have been checked. // // This fn gets bound as readbuf' in: // // src/lib/std/src/posix-1003.1b/posix-io.pkg // src/lib/std/src/posix-1003.1b/posix-io-64.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_IO_readbuf"); int fd = GET_TUPLE_SLOT_AS_INT( arg, 0 ); // Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1 ); // We'll do this after the read(). int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 2 ); // int offset = GET_TUPLE_SLOT_AS_INT( arg, 3 ); // We'll do this after the read(). int n; Mythryl_Heap_Value_Buffer vec_buf; { char* c_vec // Get a pointer to 'nbytes' of free ram outside the Mythryl heap = // (i.e., ram guaranteed not to move around during a heapcleaning). buffer_mythryl_heap_nonvalue( &vec_buf, nbytes ); /* do { */ // Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_IO_readbuf", &arg ); // 'arg' is still live here! // n = read( fd, c_vec, nbytes ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_IO_readbuf" ); /* } while (n < 0 && errno == EINTR); */ // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // The heapcleaner may have moved everything around // during our read() call, so we wait until now to // track down the location of our buf vector: // Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1 ); char* start = HEAP_STRING_AS_C_STRING(buf) + GET_TUPLE_SLOT_AS_INT( arg, 3 ); // Copy the bytes read into given // string 'buf' on Mythryl heap: // memcpy( start, c_vec, n ); // Caller is responsible for guaranteeing that this will not overrun the vector and clobber the Mythryl heap. unbuffer_mythryl_heap_value( &vec_buf ); } RETURN_STATUS_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, n, NULL); }
Val _lib7_Sock_recvbuffrom (Task* task, Val arg) { //====================== // // Mythryl type: (Socket, rw_vector_of_one_byte_unts::Rw_Vector, Int, Int, Bool, Bool) -> (Int, Addr) // // The arguments are: // socket, // data buffer, // start position, // number of bytes, // OOB flag // peek flag. // // The result is: // number of bytes read // source address. // // This fn gets bound as recv_from_a in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); char address_buf[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int socket = GET_TUPLE_SLOT_AS_INT( arg, 0); // Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); // Mythryl buffer to read bytes into. // We'll fetch this after the call, since it may move around during the call. int offset = GET_TUPLE_SLOT_AS_INT( arg, 2); // Offset within buf to read bytes into. int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 3); // Number of bytes to read. int flag = 0; int n; if (GET_TUPLE_SLOT_AS_VAL(arg, 4) == HEAP_TRUE) flag |= MSG_OOB; if (GET_TUPLE_SLOT_AS_VAL(arg, 5) == HEAP_TRUE) flag |= MSG_PEEK; // We cannot reference anything on the Mythryl heap // between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so allocate a C-side read buffer: // Mythryl_Heap_Value_Buffer readbuf_buf; // { char* c_readbuf = buffer_mythryl_heap_nonvalue( &readbuf_buf, nbytes ); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, &arg ); // 'arg' is still live here! // do { // n = recvfrom( socket, c_readbuf, nbytes, flag, (struct sockaddr *)address_buf, &address_len ); } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (n < 0) { unbuffer_mythryl_heap_value( &readbuf_buf ); return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); } Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); // Mythryl buffer to read bytes into. char* bufstart = HEAP_STRING_AS_C_STRING(buf) + offset; memcpy( bufstart, c_readbuf, n); unbuffer_mythryl_heap_value( &readbuf_buf ); } Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, address_buf, address_len, NULL ); Val address = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, address_len); Val result = make_two_slot_record(task, TAGGED_INT_FROM_C_INT(n), address); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_Sock_recv (Task* task, Val arg) { //=============== // // Mythryl type: (Socket, Int, Bool, Bool) -> vector_of_one_byte_unts::Vector // // The arguments are: socket, number of bytes, OOB flag and peek flag. // The result is the vector of bytes received. // // This fn gets bound as recv_v' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); Val vec; ssize_t n; int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 1 ); Val oob = GET_TUPLE_SLOT_AS_VAL( arg, 2 ); Val peek = GET_TUPLE_SLOT_AS_VAL( arg, 3 ); int flag = 0; if (oob == HEAP_TRUE) flag |= MSG_OOB; if (peek == HEAP_TRUE) flag |= MSG_PEEK; // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so allocate a C-world buffer // to read the bytes into: // Mythryl_Heap_Value_Buffer read_buf; // { unsigned char* c_read = buffer_mythryl_heap_nonvalue( &read_buf, nbytes ); // log_if("recv.c/before: socket d=%d nbytes d=%d oob=%s peek=%s\n",socket,nbytes,(oob == HEAP_TRUE)?"TRUE":"FALSE",(peek == HEAP_TRUE)?"TRUE":"FALSE"); errno = 0; RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // do { // Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c // // Restored 2012-08-07 CrT n = recv (socket, c_read, nbytes, flag); // } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (n <= 0) { unbuffer_mythryl_heap_value( &read_buf ); if (n < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); if (n == 0) return ZERO_LENGTH_STRING__GLOBAL; } // Allocate result vector to hold the bytes read. // NB: This might cause a heapcleaning, moving things around: // vec = allocate_nonempty_wordslots_vector__may_heapclean( task, BYTES_TO_WORDS(n), NULL ); // Copy bytes read into result vector: // memcpy( PTR_CAST(char*, vec), c_read, n); // log_if( "recv.c/after: n d=%d errno d=%d (%s)\n", n, errno, errno ? strerror(errno) : ""); // hexdump_if( "recv.c/after: Received data: ", PTR_CAST(unsigned char*, vec), n ); unbuffer_mythryl_heap_value( &read_buf ); } Val result = make_vector_header( task, STRING_TAGWORD, vec, n ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }