vppinfra: numa vector placement support
[vpp.git] / src / vppinfra / unix-misc.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2005 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #include <vppinfra/error.h>
39 #include <vppinfra/os.h>
40 #include <vppinfra/unix.h>
41
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <sys/uio.h>            /* writev */
45 #include <fcntl.h>
46 #include <stdio.h>              /* for sprintf */
47
48 __thread uword __os_thread_index = 0;
49 __thread uword __os_numa_index = 0;
50
51 clib_error_t *
52 clib_file_n_bytes (char *file, uword * result)
53 {
54   struct stat s;
55
56   if (stat (file, &s) < 0)
57     return clib_error_return_unix (0, "stat `%s'", file);
58
59   if (S_ISREG (s.st_mode))
60     *result = s.st_size;
61   else
62     *result = 0;
63
64   return /* no error */ 0;
65 }
66
67 clib_error_t *
68 clib_file_read_contents (char *file, u8 * result, uword n_bytes)
69 {
70   int fd = -1;
71   uword n_done, n_left;
72   clib_error_t *error = 0;
73   u8 *v = result;
74
75   if ((fd = open (file, 0)) < 0)
76     return clib_error_return_unix (0, "open `%s'", file);
77
78   n_left = n_bytes;
79   n_done = 0;
80   while (n_left > 0)
81     {
82       int n_read;
83       if ((n_read = read (fd, v + n_done, n_left)) < 0)
84         {
85           error = clib_error_return_unix (0, "open `%s'", file);
86           goto done;
87         }
88
89       /* End of file. */
90       if (n_read == 0)
91         break;
92
93       n_left -= n_read;
94       n_done += n_read;
95     }
96
97   if (n_left > 0)
98     {
99       error =
100         clib_error_return (0,
101                            " `%s' expected to read %wd bytes; read only %wd",
102                            file, n_bytes, n_bytes - n_left);
103       goto done;
104     }
105
106 done:
107   close (fd);
108   return error;
109 }
110
111 clib_error_t *
112 clib_file_contents (char *file, u8 ** result)
113 {
114   uword n_bytes;
115   clib_error_t *error = 0;
116   u8 *v;
117
118   if ((error = clib_file_n_bytes (file, &n_bytes)))
119     return error;
120
121   v = 0;
122   vec_resize (v, n_bytes);
123
124   error = clib_file_read_contents (file, v, n_bytes);
125
126   if (error)
127     vec_free (v);
128   else
129     *result = v;
130
131   return error;
132 }
133
134 clib_error_t *
135 unix_proc_file_contents (char *file, u8 ** result)
136 {
137   u8 *rv = 0;
138   uword pos;
139   int bytes, fd;
140
141   /* Unfortunately, stat(/proc/XXX) returns zero... */
142   fd = open (file, O_RDONLY);
143
144   if (fd < 0)
145     return clib_error_return_unix (0, "open `%s'", file);
146
147   vec_validate (rv, 4095);
148   pos = 0;
149   while (1)
150     {
151       bytes = read (fd, rv + pos, 4096);
152       if (bytes < 0)
153         {
154           close (fd);
155           vec_free (rv);
156           return clib_error_return_unix (0, "read '%s'", file);
157         }
158
159       if (bytes == 0)
160         {
161           _vec_len (rv) = pos;
162           break;
163         }
164       pos += bytes;
165       vec_validate (rv, pos + 4095);
166     }
167   *result = rv;
168   close (fd);
169   return 0;
170 }
171
172 void os_panic (void) __attribute__ ((weak));
173
174 void
175 os_panic (void)
176 {
177   abort ();
178 }
179
180 void os_exit (int) __attribute__ ((weak));
181
182 void
183 os_exit (int code)
184 {
185   exit (code);
186 }
187
188 void os_puts (u8 * string, uword string_length, uword is_error)
189   __attribute__ ((weak));
190
191 void
192 os_puts (u8 * string, uword string_length, uword is_error)
193 {
194   int cpu = os_get_thread_index ();
195   int nthreads = os_get_nthreads ();
196   char buf[64];
197   int fd = is_error ? 2 : 1;
198   struct iovec iovs[2];
199   int n_iovs = 0;
200
201   if (nthreads > 1)
202     {
203       snprintf (buf, sizeof (buf), "%d: ", cpu);
204
205       iovs[n_iovs].iov_base = buf;
206       iovs[n_iovs].iov_len = strlen (buf);
207       n_iovs++;
208     }
209
210   iovs[n_iovs].iov_base = string;
211   iovs[n_iovs].iov_len = string_length;
212   n_iovs++;
213
214   if (writev (fd, iovs, n_iovs) < 0)
215     ;
216 }
217
218 void os_out_of_memory (void) __attribute__ ((weak));
219 void
220 os_out_of_memory (void)
221 {
222   os_panic ();
223 }
224
225 uword os_get_nthreads (void) __attribute__ ((weak));
226 uword
227 os_get_nthreads (void)
228 {
229   return 1;
230 }
231
232 /*
233  * fd.io coding-style-patch-verification: ON
234  *
235  * Local Variables:
236  * eval: (c-set-style "gnu")
237  * End:
238  */