1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2015. ALL RIGHTS RESERVED.
3 *
4 * See file LICENSE for terms.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 # include "config.h"
9 #endif
10
11 #include "dt_iov.h"
12
13 #include <ucs/debug/assert.h>
14 #include <ucs/sys/math.h>
15
16 #include <string.h>
17 #include <unistd.h>
18
19
ucp_dt_iov_gather(void * dest,const ucp_dt_iov_t * iov,size_t length,size_t * iov_offset,size_t * iovcnt_offset)20 void ucp_dt_iov_gather(void *dest, const ucp_dt_iov_t *iov, size_t length,
21 size_t *iov_offset, size_t *iovcnt_offset)
22 {
23 size_t item_len, item_reminder, item_len_to_copy;
24 size_t length_it = 0;
25
26 ucs_assert(length > 0);
27 while (length_it < length) {
28 item_len = iov[*iovcnt_offset].length;
29 item_reminder = item_len - *iov_offset;
30
31 item_len_to_copy = item_reminder -
32 ucs_max((ssize_t)((length_it + item_reminder) - length), 0);
33 memcpy(UCS_PTR_BYTE_OFFSET(dest, length_it),
34 UCS_PTR_BYTE_OFFSET(iov[*iovcnt_offset].buffer, *iov_offset),
35 item_len_to_copy);
36 length_it += item_len_to_copy;
37
38 ucs_assert(length_it <= length);
39 if (length_it < length) {
40 *iov_offset = 0;
41 ++(*iovcnt_offset);
42 } else {
43 *iov_offset += item_len_to_copy;
44 }
45 }
46 }
47
ucp_dt_iov_scatter(ucp_dt_iov_t * iov,size_t iovcnt,const void * src,size_t length,size_t * iov_offset,size_t * iovcnt_offset)48 size_t ucp_dt_iov_scatter(ucp_dt_iov_t *iov, size_t iovcnt, const void *src,
49 size_t length, size_t *iov_offset, size_t *iovcnt_offset)
50 {
51 size_t item_len, item_len_to_copy;
52 size_t length_it = 0;
53
54 while ((length_it < length) && (*iovcnt_offset < iovcnt)) {
55 item_len = iov[*iovcnt_offset].length;
56 item_len_to_copy = ucs_min(ucs_max((ssize_t)(item_len - *iov_offset), 0),
57 length - length_it);
58 ucs_assert(*iov_offset <= item_len);
59
60 memcpy(UCS_PTR_BYTE_OFFSET(iov[*iovcnt_offset].buffer, *iov_offset),
61 UCS_PTR_BYTE_OFFSET(src, length_it),
62 item_len_to_copy);
63 length_it += item_len_to_copy;
64
65 ucs_assert(length_it <= length);
66 if (length_it < length) {
67 *iov_offset = 0;
68 ++(*iovcnt_offset);
69 } else {
70 *iov_offset += item_len_to_copy;
71 }
72 }
73 return length_it;
74 }
75
ucp_dt_iov_seek(ucp_dt_iov_t * iov,size_t iovcnt,ptrdiff_t distance,size_t * iov_offset,size_t * iovcnt_offset)76 void ucp_dt_iov_seek(ucp_dt_iov_t *iov, size_t iovcnt, ptrdiff_t distance,
77 size_t *iov_offset, size_t *iovcnt_offset)
78 {
79 ssize_t new_iov_offset; /* signed, since it can be negative */
80 size_t length_it;
81
82 new_iov_offset = ((ssize_t)*iov_offset) + distance;
83
84 if (new_iov_offset < 0) {
85 /* seek backwards */
86 do {
87 ucs_assert(*iovcnt_offset > 0);
88 --(*iovcnt_offset);
89 new_iov_offset += iov[*iovcnt_offset].length;
90 } while (new_iov_offset < 0);
91 } else {
92 /* seek forward */
93 while (new_iov_offset >= (length_it = iov[*iovcnt_offset].length)) {
94 new_iov_offset -= length_it;
95 ++(*iovcnt_offset);
96 ucs_assert(*iovcnt_offset < iovcnt);
97 }
98 }
99
100 *iov_offset = new_iov_offset;
101 }
102
ucp_dt_iov_count_nonempty(const ucp_dt_iov_t * iov,size_t iovcnt)103 size_t ucp_dt_iov_count_nonempty(const ucp_dt_iov_t *iov, size_t iovcnt)
104 {
105 size_t iov_it, count;
106
107 count = 0;
108 for (iov_it = 0; iov_it < iovcnt; ++iov_it) {
109 count += iov[iov_it].length != 0;
110 }
111 return count;
112 }
113