Whamcloud - gitweb
b=15516
[fs/lustre-release.git] / libcfs / libcfs / user-prim.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2004 Cluster File Systems, Inc.
5  * Author: Nikita Danilov <nikita@clusterfs.com>
6  *
7  * This file is part of Lustre, http://www.lustre.org.
8  *
9  * Lustre is free software; you can redistribute it and/or modify it under the
10  * terms of version 2 of the GNU General Public License as published by the
11  * Free Software Foundation.
12  *
13  * Lustre is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with Lustre; if not, write to the Free Software Foundation, Inc., 675 Mass
20  * Ave, Cambridge, MA 02139, USA.
21  *
22  * Implementation of portable APIs for user-level.
23  *
24  */
25
26 /* Implementations of portable APIs for liblustre */
27
28 /*
29  * liblustre is single-threaded, so most "synchronization" APIs are trivial.
30  */
31
32 #ifndef __KERNEL__
33
34 #include <libcfs/libcfs.h>
35
36 #include <sys/mman.h>
37 #ifndef  __CYGWIN__
38 #include <stdint.h>
39 #ifdef HAVE_ASM_PAGE_H
40 #include <asm/page.h>
41 #endif
42 #ifdef HAVE_SYS_USER_H
43 #include <sys/user.h>
44 #endif
45 #else
46 #include <sys/types.h>
47 #endif
48 #include <stdlib.h>
49 #include <string.h>
50 #include <signal.h>
51 #include <errno.h>
52 #include <sys/stat.h>
53 #ifdef  HAVE_SYS_VFS_H
54 #include <sys/vfs.h>
55 #endif
56
57 /*
58  * Sleep channel. No-op implementation.
59  */
60
61 void cfs_waitq_init(struct cfs_waitq *waitq)
62 {
63         LASSERT(waitq != NULL);
64         (void)waitq;
65 }
66
67 void cfs_waitlink_init(struct cfs_waitlink *link)
68 {
69         LASSERT(link != NULL);
70         (void)link;
71 }
72
73 void cfs_waitq_add(struct cfs_waitq *waitq, struct cfs_waitlink *link)
74 {
75         LASSERT(waitq != NULL);
76         LASSERT(link != NULL);
77         (void)waitq;
78         (void)link;
79 }
80
81 void cfs_waitq_add_exclusive(struct cfs_waitq *waitq, struct cfs_waitlink *link)
82 {
83         LASSERT(waitq != NULL);
84         LASSERT(link != NULL);
85         (void)waitq;
86         (void)link;
87 }
88
89 void cfs_waitq_forward(struct cfs_waitlink *link, struct cfs_waitq *waitq)
90 {
91         LASSERT(waitq != NULL);
92         LASSERT(link != NULL);
93         (void)waitq;
94         (void)link;
95 }
96
97 void cfs_waitq_del(struct cfs_waitq *waitq, struct cfs_waitlink *link)
98 {
99         LASSERT(waitq != NULL);
100         LASSERT(link != NULL);
101         (void)waitq;
102         (void)link;
103 }
104
105 int cfs_waitq_active(struct cfs_waitq *waitq)
106 {
107         LASSERT(waitq != NULL);
108         (void)waitq;
109         return 0;
110 }
111
112 void cfs_waitq_signal(struct cfs_waitq *waitq)
113 {
114         LASSERT(waitq != NULL);
115         (void)waitq;
116 }
117
118 void cfs_waitq_signal_nr(struct cfs_waitq *waitq, int nr)
119 {
120         LASSERT(waitq != NULL);
121         (void)waitq;
122 }
123
124 void cfs_waitq_broadcast(struct cfs_waitq *waitq)
125 {
126         LASSERT(waitq != NULL);
127         (void)waitq;
128 }
129
130 void cfs_waitq_wait(struct cfs_waitlink *link, int state)
131 {
132         LASSERT(link != NULL);
133         (void)link;
134 }
135
136 int64_t cfs_waitq_timedwait(struct cfs_waitlink *link, int state, int64_t timeout)
137 {
138         LASSERT(link != NULL);
139         (void)link;
140         return 0;
141 }
142
143 #ifdef HAVE_LIBPTHREAD
144
145 /*
146  * Threads
147  */
148
149 struct lustre_thread_arg {
150         cfs_thread_t f; 
151         void *arg;
152 };
153 static void *cfs_thread_helper(void *data)
154 {
155         struct lustre_thread_arg *targ = data;
156         cfs_thread_t f  = targ->f;
157         void *arg = targ->arg;
158
159         free(targ);
160         
161         (void)f(arg);
162         return NULL;
163 }
164 int cfs_create_thread(cfs_thread_t func, void *arg)
165 {
166         pthread_t tid;
167         pthread_attr_t tattr;
168         int rc;
169         struct lustre_thread_arg *targ_p = malloc(sizeof(struct lustre_thread_arg));
170
171         if ( targ_p == NULL )
172                 return -ENOMEM;
173         
174         targ_p->f = func;
175         targ_p->arg = arg;
176
177         pthread_attr_init(&tattr); 
178         pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
179         rc = pthread_create(&tid, &tattr, cfs_thread_helper, targ_p);
180         pthread_attr_destroy(&tattr);
181         return -rc;
182 }
183 #endif
184
185 uid_t cfs_curproc_uid(void)
186 {
187         return getuid();
188 }
189
190 int cfs_parse_int_tunable(int *value, char *name)
191 {
192         char    *env = getenv(name);
193         char    *end;
194
195         if (env == NULL)
196                 return 0;
197
198         *value = strtoull(env, &end, 0);
199         if (*end == 0)
200                 return 0;
201
202         CERROR("Can't parse tunable %s=%s\n", name, env);
203         return -EINVAL;
204 }
205
206 /*
207  * Allocator
208  */
209
210 cfs_page_t *cfs_alloc_page(unsigned int flags)
211 {
212         cfs_page_t *pg = malloc(sizeof(*pg));
213
214         if (!pg)
215                 return NULL;
216         pg->addr = malloc(CFS_PAGE_SIZE);
217
218         if (!pg->addr) {
219                 free(pg);
220                 return NULL;
221         }
222         return pg;
223 }
224
225 void cfs_free_page(cfs_page_t *pg)
226 {
227         free(pg->addr);
228         free(pg);
229 }
230
231 void *cfs_page_address(cfs_page_t *pg)
232 {
233         return pg->addr;
234 }
235
236 void *cfs_kmap(cfs_page_t *pg)
237 {
238         return pg->addr;
239 }
240
241 void cfs_kunmap(cfs_page_t *pg)
242 {
243 }
244
245 /*
246  * SLAB allocator
247  */
248
249 cfs_mem_cache_t *
250 cfs_mem_cache_create(const char *name, size_t objsize, size_t off, unsigned long flags)
251 {
252         cfs_mem_cache_t *c;
253
254         c = malloc(sizeof(*c));
255         if (!c)
256                 return NULL;
257         c->size = objsize;
258         CDEBUG(D_MALLOC, "alloc slab cache %s at %p, objsize %d\n",
259                name, c, (int)objsize);
260         return c;
261 }
262
263 int cfs_mem_cache_destroy(cfs_mem_cache_t *c)
264 {
265         CDEBUG(D_MALLOC, "destroy slab cache %p, objsize %u\n", c, c->size);
266         free(c);
267         return 0;
268 }
269
270 void *cfs_mem_cache_alloc(cfs_mem_cache_t *c, int gfp)
271 {
272         return cfs_alloc(c->size, gfp);
273 }
274
275 void cfs_mem_cache_free(cfs_mem_cache_t *c, void *addr)
276 {
277         cfs_free(addr);
278 }
279
280 void cfs_enter_debugger(void)
281 {
282         /*
283          * nothing for now.
284          */
285 }
286
287 void cfs_daemonize(char *str)
288 {
289         return;
290 }
291
292 int cfs_daemonize_ctxt(char *str)
293 {
294         return 0;
295 }
296
297 cfs_sigset_t cfs_block_allsigs(void)
298 {
299         cfs_sigset_t   all;
300         cfs_sigset_t   old;
301         int            rc;
302
303         sigfillset(&all);
304         rc = sigprocmask(SIG_SETMASK, &all, &old);
305         LASSERT(rc == 0);
306
307         return old;
308 }
309
310 cfs_sigset_t cfs_block_sigs(cfs_sigset_t blocks)
311 {
312         cfs_sigset_t   old;
313         int   rc;
314         
315         rc = sigprocmask(SIG_SETMASK, &blocks, &old);
316         LASSERT (rc == 0);
317
318         return old;
319 }
320
321 void cfs_restore_sigs(cfs_sigset_t old)
322 {
323         int   rc = sigprocmask(SIG_SETMASK, &old, NULL);
324
325         LASSERT (rc == 0);
326 }
327
328 int cfs_signal_pending(void)
329 {
330         cfs_sigset_t    empty;
331         cfs_sigset_t    set;
332         int  rc;
333
334         rc = sigpending(&set);
335         LASSERT (rc == 0);
336
337         sigemptyset(&empty);
338
339         return !memcmp(&empty, &set, sizeof(set));
340 }
341
342 void cfs_clear_sigpending(void)
343 {
344         return;
345 }
346
347 #ifdef __linux__
348
349 /*
350  * In glibc (NOT in Linux, so check above is not right), implement
351  * stack-back-tracing through backtrace() function.
352  */
353 #include <execinfo.h>
354
355 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
356 {
357         backtrace(trace->frame, sizeof_array(trace->frame));
358 }
359
360 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
361 {
362         if (0 <= frame_no && frame_no < sizeof_array(trace->frame))
363                 return trace->frame[frame_no];
364         else
365                 return NULL;
366 }
367
368 #else
369
370 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
371 {}
372 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
373 {
374         return NULL;
375 }
376
377 /* __linux__ */
378 #endif
379
380 void lbug_with_loc(char *file, const char *func, const int line)
381 {
382         /* No libcfs_catastrophe in userspace! */
383         libcfs_debug_msg(NULL, 0, D_EMERG, file, func, line, "LBUG\n");
384         abort();
385 }
386
387 /* !__KERNEL__ */
388 #endif
389
390 /*
391  * Local variables:
392  * c-indentation-style: "K&R"
393  * c-basic-offset: 8
394  * tab-width: 8
395  * fill-column: 80
396  * scroll-step: 1
397  * End:
398  */