// The initial ref count in the return qbytes buffer is 1. // The caller is responsible for calling qbytes_release on it when done. qbytes_t* bulk_get_bytes(int64_t src_locale, qbytes_t* src_addr) { qbytes_t tmp; qbytes_t* ret; int64_t src_len; void* src_data; qioerr err; // Zero-initialize tmp. memset(&tmp, 0, sizeof(qbytes_t)); // First, get the length and local pointer to the bytes. chpl_gen_comm_get( &tmp, src_locale, src_addr, sizeof(qbytes_t), CHPL_TYPE_int64_t, -1, "<internal>"); src_len = tmp.len; src_data = tmp.data; // The initial ref count is 1. err = qbytes_create_calloc(&ret, src_len); if( err ) return NULL; // TODO -- note -- technically, this should be gasnet_get_bulk, // since we don't want to require src/dst to have a particular alignment. // Next, get the data itself. if( src_data ) { chpl_gen_comm_get( ret->data, src_locale, src_data, sizeof(uint8_t)*src_len, CHPL_TYPE_uint8_t, -1, "<internal>"); } // Great! All done. return ret; }
qioerr qbuffer_flatten(qbuffer_t* buf, qbuffer_iter_t start, qbuffer_iter_t end, qbytes_t** bytes_out) { int64_t num_bytes = qbuffer_iter_num_bytes(start, end); ssize_t num_parts = qbuffer_iter_num_parts(start, end); struct iovec* iov = NULL; size_t iovcnt; size_t i,j; qbytes_t* ret; MAYBE_STACK_SPACE(struct iovec, iov_onstack); qioerr err; if( num_bytes < 0 || num_parts < 0 || start.offset < buf->offset_start || end.offset > buf->offset_end ) { *bytes_out = 0; QIO_RETURN_CONSTANT_ERROR(EINVAL, "range outside of buffer"); } err = qbytes_create_calloc(&ret, num_bytes); if( err ) { *bytes_out = 0; return err; } MAYBE_STACK_ALLOC(struct iovec, num_parts, iov, iov_onstack); if( ! iov ) { // The buffer was successfully allocated, so we have to release it here. qbytes_release(ret); *bytes_out = 0; return QIO_ENOMEM; } err = qbuffer_to_iov(buf, start, end, num_parts, iov, NULL, &iovcnt); if( err ) { MAYBE_STACK_FREE(iov, iov_onstack); // The buffer was successfully allocated, so we have to release it here. qbytes_release(ret); *bytes_out = 0; return err; } j = 0; for( i = 0; i < iovcnt; i++ ) { qio_memcpy(PTR_ADDBYTES(ret->data, j), iov[i].iov_base, iov[i].iov_len); j += iov[i].iov_len; } MAYBE_STACK_FREE(iov, iov_onstack); *bytes_out = ret; return 0; }
err_t qbuffer_flatten(qbuffer_t* buf, qbuffer_iter_t start, qbuffer_iter_t end, qbytes_t** bytes_out) { int64_t num_bytes = qbuffer_iter_num_bytes(start, end); ssize_t num_parts = qbuffer_iter_num_parts(start, end); struct iovec* iov = NULL; size_t iovcnt; size_t i,j; qbytes_t* ret; MAYBE_STACK_SPACE(struct iovec, iov_onstack); err_t err; if( num_bytes < 0 || num_parts < 0 || start.offset < buf->offset_start || end.offset > buf->offset_end ) return EINVAL; err = qbytes_create_calloc(&ret, num_bytes); if( err ) return err; MAYBE_STACK_ALLOC(struct iovec, num_parts, iov, iov_onstack); if( ! iov ) { qbytes_release(ret); return ENOMEM; } err = qbuffer_to_iov(buf, start, end, num_parts, iov, NULL, &iovcnt); if( err ) { MAYBE_STACK_FREE(iov, iov_onstack); qbytes_release(ret); return err; } j = 0; for( i = 0; i < iovcnt; i++ ) { memcpy(PTR_ADDBYTES(ret->data, j), iov[i].iov_base, iov[i].iov_len); j += iov[i].iov_len; } MAYBE_STACK_FREE(iov, iov_onstack); *bytes_out = ret; return 0; }
qbytes_t* bulk_get_bytes(int64_t src_locale, qbytes_t* src_addr) { qbytes_t* ret; int64_t src_len; err_t err; // First, get the length of the bytes. chpl_gen_comm_get( &src_len, src_locale, & src_addr->len, sizeof(int64_t), CHPL_TYPE_int64_t, 1, -1, "<internal>"); // chpl_comm_get err = qbytes_create_calloc(&ret, src_len); if( err ) return NULL; // TODO -- note -- technically, this should be gasnet_get_bulk, // since we don't want to require src/dst to have a particular alignment. // Next, get the data itself. chpl_gen_comm_get( ret->data, src_locale, & src_addr->data, sizeof(uint8_t), CHPL_TYPE_uint8_t, src_len, -1, "<internal>"); // Great! All done. return ret; }