1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2015.  ALL RIGHTS RESERVED.
3 *
4 * See file LICENSE for terms.
5 */
6 
7 #include "uct_test.h"
8 
9 #include <ucs/sys/sys.h>
10 
11 
12 class test_mem : public testing::TestWithParam<uct_alloc_method_t>,
13                  public uct_test_base {
14 public:
15     UCS_TEST_BASE_IMPL;
16 
init()17     virtual void init() {
18         ucs::skip_on_address_sanitizer();
19         uct_test_base::init();
20     }
21 
22 protected:
23 
check_mem(const uct_allocated_memory & mem,size_t min_length)24     void check_mem(const uct_allocated_memory &mem, size_t min_length) {
25         EXPECT_TRUE(mem.address != 0);
26         EXPECT_GE(mem.length, min_length);
27         if (mem.method == UCT_ALLOC_METHOD_MD) {
28             EXPECT_TRUE(mem.md != NULL);
29             EXPECT_TRUE(mem.memh != UCT_MEM_HANDLE_NULL);
30         } else {
31             EXPECT_TRUE((mem.method == GetParam()) ||
32                         (mem.method == UCT_ALLOC_METHOD_HEAP));
33         }
34     }
35 
36     static const size_t min_length = 1234557;
37 };
38 
39 
UCS_TEST_P(test_mem,nomd_alloc)40 UCS_TEST_P(test_mem, nomd_alloc) {
41     uct_alloc_method_t methods[2];
42     uct_allocated_memory mem;
43     ucs_status_t status;
44 
45     methods[0] = GetParam();
46     methods[1] = UCT_ALLOC_METHOD_HEAP;
47 
48     status = uct_mem_alloc(NULL, min_length, UCT_MD_MEM_ACCESS_ALL, methods,
49                            2, NULL, 0, "test", &mem);
50     ASSERT_UCS_OK(status);
51 
52     check_mem(mem, min_length);
53 
54     uct_mem_free(&mem);
55 }
56 
UCS_TEST_P(test_mem,md_alloc)57 UCS_TEST_P(test_mem, md_alloc) {
58     uct_alloc_method_t methods[3];
59     uct_allocated_memory mem;
60     std::vector<md_resource> md_resources;
61     uct_md_attr_t md_attr;
62     ucs_status_t status;
63     uct_md_h md;
64     uct_md_config_t *md_config;
65     int nonblock;
66 
67     methods[0] = UCT_ALLOC_METHOD_MD;
68     methods[1] = GetParam();
69     methods[2] = UCT_ALLOC_METHOD_HEAP;
70 
71     md_resources = enum_md_resources();
72     for (std::vector<md_resource>::iterator iter = md_resources.begin();
73          iter != md_resources.end(); ++iter) {
74 
75         status = uct_md_config_read(iter->cmpt, NULL, NULL, &md_config);
76         ASSERT_UCS_OK(status);
77 
78         status = uct_md_open(iter->cmpt, iter->rsc_desc.md_name, md_config, &md);
79         uct_config_release(md_config);
80         ASSERT_UCS_OK(status);
81 
82         status = uct_md_query(md, &md_attr);
83         ASSERT_UCS_OK(status);
84 
85         for (nonblock = 0; nonblock <= 1; ++nonblock) {
86             int flags = nonblock ? UCT_MD_MEM_FLAG_NONBLOCK : 0;
87             flags |= UCT_MD_MEM_ACCESS_ALL;
88             status = uct_mem_alloc(NULL, min_length, flags, methods, 3, &md, 1,
89                                    "test", &mem);
90             ASSERT_UCS_OK(status);
91 
92             if (md_attr.cap.flags & UCT_MD_FLAG_ALLOC) {
93                 EXPECT_EQ(UCT_ALLOC_METHOD_MD, mem.method);
94             } else {
95                 EXPECT_NE(UCT_ALLOC_METHOD_MD, mem.method);
96             }
97 
98             check_mem(mem, min_length);
99 
100             uct_mem_free(&mem);
101         }
102 
103         uct_md_close(md);
104     }
105 }
106 
UCS_TEST_P(test_mem,md_fixed)107 UCS_TEST_P(test_mem, md_fixed) {
108     std::vector<md_resource> md_resources;
109     uct_md_attr_t           md_attr;
110     uct_md_config_t         *md_config;
111     uct_md_h                md;
112     unsigned                j;
113 
114     const size_t            page_size   = ucs_get_page_size();
115     const size_t            n_tryes     = 101;
116     uct_alloc_method_t      meth;
117     void*                   p_addr      = ucs::mmap_fixed_address();
118     size_t                  n_success;
119 
120     uct_allocated_memory_t  uct_mem;
121     ucs_status_t            status;
122 
123     md_resources = enum_md_resources();
124     for (std::vector<md_resource>::iterator iter = md_resources.begin();
125          iter != md_resources.end(); ++iter) {
126 
127         status = uct_md_config_read(iter->cmpt, NULL, NULL, &md_config);
128         ASSERT_UCS_OK(status);
129 
130         status = uct_md_open(iter->cmpt, iter->rsc_desc.md_name, md_config, &md);
131         uct_config_release(md_config);
132         ASSERT_UCS_OK(status);
133 
134         status = uct_md_query(md, &md_attr);
135         ASSERT_UCS_OK(status);
136 
137         if ((md_attr.cap.flags & UCT_MD_FLAG_ALLOC) &&
138             (md_attr.cap.flags & UCT_MD_FLAG_FIXED)) {
139             n_success = 0;
140 
141             for (j = 0; j < n_tryes; ++j) {
142                 meth = UCT_ALLOC_METHOD_MD;
143 
144                 status = uct_mem_alloc(p_addr, 1,
145                                        UCT_MD_MEM_FLAG_FIXED|
146                                        UCT_MD_MEM_ACCESS_ALL,
147                                        &meth, 1, &md, 1, "test", &uct_mem);
148                 if (status == UCS_OK) {
149                     ++n_success;
150                     EXPECT_EQ(meth, uct_mem.method);
151                     EXPECT_EQ(p_addr, uct_mem.address);
152                     EXPECT_GE(uct_mem.length, (size_t)1);
153                     /* touch the page*/
154                     memset(uct_mem.address, 'c', uct_mem.length);
155                     EXPECT_EQ(*(char*)p_addr, 'c');
156                     status = uct_mem_free(&uct_mem);
157                 } else {
158                     EXPECT_EQ(status, UCS_ERR_NO_MEMORY);
159                 }
160 
161                 p_addr = (char*)p_addr + (2 * page_size);
162             }
163 
164             EXPECT_GT(n_success, (size_t)0);
165         }
166 
167         uct_md_close(md);
168     }
169 }
170 
171 
UCS_TEST_P(test_mem,mmap_fixed)172 UCS_TEST_P(test_mem, mmap_fixed) {
173     unsigned                i;
174 
175     const size_t            page_size   = ucs_get_page_size();
176     const size_t            n_tryes     = 101;
177     uct_alloc_method_t      meth;
178     void*                   p_addr      = ucs::mmap_fixed_address();
179     size_t                  n_success;
180 
181     uct_allocated_memory_t  uct_mem;
182     ucs_status_t            status;
183 
184     n_success = 0;
185 
186     for (i = 0; i < n_tryes; ++i) {
187         meth = (i % 2) ? UCT_ALLOC_METHOD_MMAP : UCT_ALLOC_METHOD_HUGE;
188 
189         status = uct_mem_alloc(p_addr, 1,
190                                UCT_MD_MEM_FLAG_FIXED|UCT_MD_MEM_ACCESS_ALL,
191                                &meth, 1, NULL, 0, "test", &uct_mem);
192         if (status == UCS_OK) {
193             ++n_success;
194             EXPECT_EQ(meth, uct_mem.method);
195             EXPECT_EQ(p_addr, uct_mem.address);
196             EXPECT_GE(uct_mem.length, (size_t)1);
197             /* touch the page*/
198             memset(uct_mem.address, 'c', uct_mem.length);
199             EXPECT_EQ(*(char*)p_addr, 'c');
200             status = uct_mem_free(&uct_mem);
201         } else {
202             EXPECT_EQ(status, UCS_ERR_NO_MEMORY);
203         }
204         p_addr = (char*)p_addr + (2 * page_size);
205     }
206 }
207 
208 INSTANTIATE_TEST_CASE_P(alloc_methods, test_mem,
209                         ::testing::Values(UCT_ALLOC_METHOD_THP,
210                                           UCT_ALLOC_METHOD_HEAP,
211                                           UCT_ALLOC_METHOD_MMAP,
212                                           UCT_ALLOC_METHOD_HUGE));
213