Whamcloud - gitweb
e9652f0c7c222d02870893976c4a60fe39b365a6
[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  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  *
32  * Copyright (c) 2011, Whamcloud, Inc.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  *
38  * libcfs/libcfs/user-prim.c
39  *
40  * Implementations of portable APIs for liblustre
41  *
42  * Author: Nikita Danilov <nikita@clusterfs.com>
43  */
44
45 /*
46  * liblustre is single-threaded, so most "synchronization" APIs are trivial.
47  */
48
49 #ifndef __KERNEL__
50
51 #include <libcfs/libcfs.h>
52
53 /*
54  * Wait queue. No-op implementation.
55  */
56
57 void cfs_waitq_init(struct cfs_waitq *waitq)
58 {
59         LASSERT(waitq != NULL);
60         (void)waitq;
61 }
62
63 void cfs_waitlink_init(struct cfs_waitlink *link)
64 {
65         LASSERT(link != NULL);
66         (void)link;
67 }
68
69 void cfs_waitq_add(struct cfs_waitq *waitq, struct cfs_waitlink *link)
70 {
71         LASSERT(waitq != NULL);
72         LASSERT(link != NULL);
73         (void)waitq;
74         (void)link;
75 }
76
77 void cfs_waitq_add_exclusive(struct cfs_waitq *waitq, struct cfs_waitlink *link)
78 {
79         LASSERT(waitq != NULL);
80         LASSERT(link != NULL);
81         (void)waitq;
82         (void)link;
83 }
84
85 void cfs_waitq_add_exclusive_head(struct cfs_waitq *waitq, struct cfs_waitlink *link)
86 {
87         cfs_waitq_add_exclusive(waitq, link);
88 }
89
90 void cfs_waitq_del(struct cfs_waitq *waitq, struct cfs_waitlink *link)
91 {
92         LASSERT(waitq != NULL);
93         LASSERT(link != NULL);
94         (void)waitq;
95         (void)link;
96 }
97
98 int cfs_waitq_active(struct cfs_waitq *waitq)
99 {
100         LASSERT(waitq != NULL);
101         (void)waitq;
102         return 0;
103 }
104
105 void cfs_waitq_signal(struct cfs_waitq *waitq)
106 {
107         LASSERT(waitq != NULL);
108         (void)waitq;
109 }
110
111 void cfs_waitq_signal_nr(struct cfs_waitq *waitq, int nr)
112 {
113         LASSERT(waitq != NULL);
114         (void)waitq;
115 }
116
117 void cfs_waitq_broadcast(struct cfs_waitq *waitq)
118 {
119         LASSERT(waitq != NULL);
120         (void)waitq;
121 }
122
123 void cfs_waitq_wait(struct cfs_waitlink *link, cfs_task_state_t state)
124 {
125         LASSERT(link != NULL);
126         (void)link;
127
128         /* well, wait for something to happen */
129         cfs_call_wait_handler(0);
130 }
131
132 int64_t cfs_waitq_timedwait(struct cfs_waitlink *link, cfs_task_state_t state,
133                             int64_t timeout)
134 {
135         LASSERT(link != NULL);
136         (void)link;
137         cfs_call_wait_handler(timeout);
138         return 0;
139 }
140
141 void cfs_schedule_timeout_and_set_state(cfs_task_state_t state, int64_t timeout)
142 {
143         cfs_waitlink_t    l;
144         /* sleep(timeout) here instead? */
145         cfs_waitq_timedwait(&l, state, timeout);
146 }
147
148 void
149 cfs_pause(cfs_duration_t d)
150 {
151         struct timespec s;
152
153         cfs_duration_nsec(d, &s);
154         nanosleep(&s, NULL);
155 }
156
157 int cfs_need_resched(void)
158 {
159         return 0;
160 }
161
162 void cfs_cond_resched(void)
163 {
164 }
165
166 /*
167  * Timer
168  */
169
170 void cfs_init_timer(cfs_timer_t *t)
171 {
172         CFS_INIT_LIST_HEAD(&t->tl_list);
173 }
174
175 void cfs_timer_init(cfs_timer_t *l, cfs_timer_func_t *func, void *arg)
176 {
177         CFS_INIT_LIST_HEAD(&l->tl_list);
178         l->function = func;
179         l->data = (ulong_ptr_t)arg;
180         return;
181 }
182
183 int cfs_timer_is_armed(cfs_timer_t *l)
184 {
185         if (cfs_time_before(cfs_time_current(), l->expires))
186                 return 1;
187         else
188                 return 0;
189 }
190
191 void cfs_timer_arm(cfs_timer_t *l, cfs_time_t deadline)
192 {
193         l->expires = deadline;
194 }
195
196 void cfs_timer_disarm(cfs_timer_t *l)
197 {
198 }
199 cfs_time_t cfs_timer_deadline(cfs_timer_t *l)
200 {
201         return l->expires;
202 }
203
204
205 #ifdef HAVE_LIBPTHREAD
206
207 /*
208  * Threads
209  */
210
211 struct lustre_thread_arg {
212         cfs_thread_t f;
213         void *arg;
214 };
215 static void *cfs_thread_helper(void *data)
216 {
217         struct lustre_thread_arg *targ = data;
218         cfs_thread_t f  = targ->f;
219         void *arg = targ->arg;
220
221         free(targ);
222
223         (void)f(arg);
224         return NULL;
225 }
226
227 int cfs_create_thread(cfs_thread_t func, void *arg, unsigned long flags)
228 {
229         pthread_t tid;
230         pthread_attr_t tattr;
231         int rc;
232         struct lustre_thread_arg *targ_p = malloc(sizeof(struct lustre_thread_arg));
233
234         if ( targ_p == NULL )
235                 return -ENOMEM;
236
237         targ_p->f = func;
238         targ_p->arg = arg;
239
240         pthread_attr_init(&tattr);
241         pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
242         rc = pthread_create(&tid, &tattr, cfs_thread_helper, targ_p);
243         pthread_attr_destroy(&tattr);
244         return -rc;
245 }
246 #endif
247
248 uid_t cfs_curproc_uid(void)
249 {
250         return getuid();
251 }
252
253 gid_t cfs_curproc_gid(void)
254 {
255         return getgid();
256 }
257
258 uid_t cfs_curproc_fsuid(void)
259 {
260         return getuid();
261 }
262
263 gid_t cfs_curproc_fsgid(void)
264 {
265         return getgid();
266 }
267
268 void cfs_enter_debugger(void)
269 {
270         /*
271          * nothing for now.
272          */
273 }
274
275 void cfs_daemonize(char *str)
276 {
277         return;
278 }
279
280 int cfs_daemonize_ctxt(char *str)
281 {
282         return 0;
283 }
284
285 cfs_sigset_t cfs_block_allsigs(void)
286 {
287         cfs_sigset_t   all;
288         cfs_sigset_t   old;
289         int            rc;
290
291         sigfillset(&all);
292         rc = sigprocmask(SIG_SETMASK, &all, &old);
293         LASSERT(rc == 0);
294
295         return old;
296 }
297
298 cfs_sigset_t cfs_block_sigs(cfs_sigset_t blocks)
299 {
300         cfs_sigset_t   old;
301         int   rc;
302
303         rc = sigprocmask(SIG_SETMASK, &blocks, &old);
304         LASSERT (rc == 0);
305
306         return old;
307 }
308
309 /* Block all signals except for the @sigs. It's only used in
310  * Linux kernel, just a dummy here. */
311 cfs_sigset_t cfs_block_sigsinv(unsigned long sigs)
312 {
313         cfs_sigset_t old;
314         int rc;
315
316         /* Return old blocked sigs */
317         rc = sigprocmask(SIG_SETMASK, NULL, &old);
318         LASSERT(rc == 0);
319
320         return old;
321 }
322
323 void cfs_restore_sigs(cfs_sigset_t old)
324 {
325         int   rc = sigprocmask(SIG_SETMASK, &old, NULL);
326
327         LASSERT (rc == 0);
328 }
329
330 int cfs_signal_pending(void)
331 {
332         cfs_sigset_t    empty;
333         cfs_sigset_t    set;
334         int  rc;
335
336         rc = sigpending(&set);
337         LASSERT (rc == 0);
338
339         sigemptyset(&empty);
340
341         return !memcmp(&empty, &set, sizeof(set));
342 }
343
344 void cfs_clear_sigpending(void)
345 {
346         return;
347 }
348
349 #ifdef __linux__
350
351 /*
352  * In glibc (NOT in Linux, so check above is not right), implement
353  * stack-back-tracing through backtrace() function.
354  */
355 #include <execinfo.h>
356
357 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
358 {
359         backtrace(trace->frame, ARRAY_SIZE(trace->frame));
360 }
361
362 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
363 {
364         if (0 <= frame_no && frame_no < ARRAY_SIZE(trace->frame))
365                 return trace->frame[frame_no];
366         else
367                 return NULL;
368 }
369
370 #else
371
372 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
373 {}
374 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
375 {
376         return NULL;
377 }
378
379 /* __linux__ */
380 #endif
381
382 void lbug_with_loc(const char *file, const char *func, const int line)
383 {
384         /* No libcfs_catastrophe in userspace! */
385         libcfs_debug_msg(NULL, 0, D_EMERG, file, func, line, "LBUG\n");
386         abort();
387 }
388
389 /* !__KERNEL__ */
390 #endif
391
392 /*
393  * Local variables:
394  * c-indentation-style: "K&R"
395  * c-basic-offset: 8
396  * tab-width: 8
397  * fill-column: 80
398  * scroll-step: 1
399  * End:
400  */