Whamcloud - gitweb
2447bbc8eec65ad0c7094cc6e62333a4dfd30bc6
[fs/lustre-release.git] / lnet / include / libcfs / user-prim.h
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 time API for user-level.
23  *
24  */
25
26 #ifndef __LIBCFS_USER_PRIM_H__
27 #define __LIBCFS_USER_PRIM_H__
28
29 #ifndef __LIBCFS_LIBCFS_H__
30 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
31 #endif
32
33 /* Implementations of portable APIs for liblustre */
34
35 /*
36  * liblustre is single-threaded, so most "synchronization" APIs are trivial.
37  */
38
39 #ifndef __KERNEL__
40
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/signal.h>
44 #include <sys/mman.h>
45 #include <libcfs/list.h>
46 #include <libcfs/user-time.h>
47 #include <signal.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50
51 #ifdef HAVE_LIBPTHREAD
52 #include <pthread.h>
53 #endif
54
55 #ifndef PAGE_SIZE
56
57 #define PAGE_SIZE (getpagesize())
58 static __inline__ int getpageshift()
59 {
60         int pagesize = getpagesize();
61 #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
62         /* unsigned int is 32 bits on all our architectures */
63         return (__builtin_clz(pagesize) ^ 31);
64 #else
65         register int pageshift = -1;
66         while (pagesize) { pagesize >>= 1; pageshift++; }
67         return pageshift;
68 #endif
69 }
70
71 #undef  PAGE_MASK
72 #define PAGE_MASK  (~(PAGE_SIZE-1))
73 #undef  PAGE_SHIFT
74 #define PAGE_SHIFT (getpageshift())
75
76 #endif
77
78 /*
79  * Wait Queue. No-op implementation.
80  */
81
82 typedef struct cfs_waitlink {
83         struct list_head sleeping;
84         void *process;
85 } cfs_waitlink_t;
86
87 typedef struct cfs_waitq {
88         struct list_head sleepers;
89 } cfs_waitq_t;
90
91 void cfs_waitq_init(struct cfs_waitq *waitq);
92 void cfs_waitlink_init(struct cfs_waitlink *link);
93 void cfs_waitq_add(struct cfs_waitq *waitq, struct cfs_waitlink *link);
94 void cfs_waitq_add_exclusive(struct cfs_waitq *waitq, 
95                              struct cfs_waitlink *link);
96 void cfs_waitq_forward(struct cfs_waitlink *link, struct cfs_waitq *waitq);
97 void cfs_waitq_del(struct cfs_waitq *waitq, struct cfs_waitlink *link);
98 int  cfs_waitq_active(struct cfs_waitq *waitq);
99 void cfs_waitq_signal(struct cfs_waitq *waitq);
100 void cfs_waitq_signal_nr(struct cfs_waitq *waitq, int nr);
101 void cfs_waitq_broadcast(struct cfs_waitq *waitq, int state);
102 void cfs_waitq_wait(struct cfs_waitlink *link);
103 int64_t cfs_waitq_timedwait(struct cfs_waitlink *link, int state, int64_t timeout);
104 #define cfs_schedule_timeout(s, t)              \
105         do {                                    \
106                 cfs_waitlink_t    l;            \
107                 cfs_waitq_timedwait(&l, s, t);  \
108         } while (0)
109
110 #define CFS_TASK_INTERRUPTIBLE  (0)
111 #define CFS_TASK_UNINT          (0)
112
113 /* 2.4 defines */
114
115 /* XXX
116  * for this moment, liblusre will not rely OST for non-page-aligned write
117  */
118 #define LIBLUSTRE_HANDLE_UNALIGNED_PAGE
119
120 struct page {
121         void   *addr;
122         unsigned long index;
123         struct list_head list;
124         unsigned long private;
125
126         /* internally used by liblustre file i/o */
127         int     _offset;
128         int     _count;
129 #ifdef LIBLUSTRE_HANDLE_UNALIGNED_PAGE
130         int     _managed;
131 #endif
132 };
133
134 typedef struct page cfs_page_t;
135
136 #define CFS_PAGE_SIZE                   PAGE_SIZE
137 #define CFS_PAGE_SHIFT                  PAGE_SHIFT
138 #define CFS_PAGE_MASK                   (~((__u64)CFS_PAGE_SIZE-1))
139
140 cfs_page_t *cfs_alloc_page(unsigned int flags);
141 void cfs_free_page(cfs_page_t *pg);
142 void *cfs_page_address(cfs_page_t *pg);
143 void *cfs_kmap(cfs_page_t *pg);
144 void cfs_kunmap(cfs_page_t *pg);
145
146 #define cfs_get_page(p)                 __I_should_not_be_called__(at_all)
147 #define cfs_page_count(p)               __I_should_not_be_called__(at_all)
148 #define cfs_page_index(p)               ((p)->index)
149
150 /*
151  * Memory allocator
152  * Inline function, so utils can use them without linking of libcfs
153  */
154 #define __ALLOC_ZERO    (1 << 2)
155 static inline void *cfs_alloc(size_t nr_bytes, u_int32_t flags)
156 {
157         void *result;
158
159         result = malloc(nr_bytes);
160         if (result != NULL && (flags & __ALLOC_ZERO))
161                 memset(result, 0, nr_bytes);
162         return result;
163 }
164
165 #define cfs_free(addr)  free(addr)
166 #define cfs_alloc_large(nr_bytes) cfs_alloc(nr_bytes, 0)
167 #define cfs_free_large(addr) cfs_free(addr)
168
169 #define CFS_ALLOC_ATOMIC_TRY   (0)
170 /*
171  * SLAB allocator
172  */
173 typedef struct {
174          int size;
175 } cfs_mem_cache_t;
176
177 #define SLAB_HWCACHE_ALIGN 0
178 #define SLAB_KERNEL 0
179 #define SLAB_NOFS 0
180
181 cfs_mem_cache_t *
182 cfs_mem_cache_create(const char *, size_t, size_t, unsigned long);
183 int cfs_mem_cache_destroy(cfs_mem_cache_t *c);
184 void *cfs_mem_cache_alloc(cfs_mem_cache_t *c, int gfp);
185 void cfs_mem_cache_free(cfs_mem_cache_t *c, void *addr);
186
187 typedef int (cfs_read_proc_t)(char *page, char **start, off_t off,
188                           int count, int *eof, void *data);
189
190 struct file; /* forward ref */
191 typedef int (cfs_write_proc_t)(struct file *file, const char *buffer,
192                                unsigned long count, void *data);
193
194 /*
195  * Signal
196  */
197 typedef sigset_t                        cfs_sigset_t;
198
199 /*
200  * Timer
201  */
202 #include <sys/time.h>
203
204 typedef struct {
205         struct list_head tl_list;
206         void (*function)(unsigned long unused);
207         unsigned long data;
208         long expires;
209 } cfs_timer_t;
210
211 #define cfs_init_timer(t)       do {} while(0)
212 #define cfs_jiffies                             \
213 ({                                              \
214         unsigned long _ret = 0;                 \
215         struct timeval tv;                      \
216         if (gettimeofday(&tv, NULL) == 0)       \
217                 _ret = tv.tv_sec;               \
218         _ret;                                   \
219 })
220
221 static inline int cfs_timer_init(cfs_timer_t *l, void (* func)(unsigned long), void *arg)
222 {
223         CFS_INIT_LIST_HEAD(&l->tl_list);
224         l->function = func;
225         l->data = (unsigned long)arg;
226         return 0;
227 }
228
229 static inline int cfs_timer_is_armed(cfs_timer_t *l)
230 {
231         if (cfs_time_before(cfs_jiffies, l->expires))
232                 return 1;
233         else
234                 return 0;
235 }
236
237 static inline void cfs_timer_arm(cfs_timer_t *l, int thetime)
238 {
239         l->expires = thetime;
240 }
241
242 static inline void cfs_timer_disarm(cfs_timer_t *l)
243 {
244 }
245
246 static inline long cfs_timer_deadline(cfs_timer_t *l)
247 {
248         return l->expires;
249 }
250
251 #if 0
252 #define cfs_init_timer(t)       do {} while(0)
253 void cfs_timer_init(struct cfs_timer *t, void (*func)(unsigned long), void *arg);
254 void cfs_timer_done(struct cfs_timer *t);
255 void cfs_timer_arm(struct cfs_timer *t, cfs_time_t deadline);
256 void cfs_timer_disarm(struct cfs_timer *t);
257 int  cfs_timer_is_armed(struct cfs_timer *t);
258
259 cfs_time_t cfs_timer_deadline(struct cfs_timer *t);
260 #endif
261
262 #define in_interrupt()    (0)
263
264 static inline void cfs_pause(cfs_duration_t d)
265 {
266         struct timespec s;
267         
268         cfs_duration_nsec(d, &s);
269         nanosleep(&s, NULL);
270 }
271
272 typedef void cfs_psdev_t;
273
274 static inline int cfs_psdev_register(cfs_psdev_t *foo)
275 {
276         return 0;
277 }
278
279 static inline int cfs_psdev_deregister(cfs_psdev_t *foo)
280 {
281         return 0;
282 }
283
284 #define cfs_lock_kernel()               do {} while (0)
285 #define cfs_sigfillset(l) do {}         while (0)
286 #define cfs_recalc_sigpending(l)        do {} while (0)
287 #define cfs_kernel_thread(l,m,n)        LBUG()
288
289 #ifdef HAVE_LIBPTHREAD
290 typedef int (*cfs_thread_t)(void *);
291 int cfs_create_thread(cfs_thread_t func, void *arg);
292 #else
293 #define cfs_create_thread(l,m) LBUG()
294 #endif
295
296 int cfs_parse_int_tunable(int *value, char *name);
297 uid_t cfs_curproc_uid(void);
298
299 #define LIBCFS_REALLOC(ptr, size) realloc(ptr, size)
300
301 #define cfs_online_cpus() sysconf(_SC_NPROCESSORS_ONLN)
302
303 // static inline void local_irq_save(unsigned long flag) {return;}
304 // static inline void local_irq_restore(unsigned long flag) {return;}
305
306 enum {
307         CFS_STACK_TRACE_DEPTH = 16
308 };
309
310 struct cfs_stack_trace {
311         void *frame[CFS_STACK_TRACE_DEPTH];
312 };
313
314 /*
315  * arithmetic
316  */
317 #define do_div(a,b)                     \
318         ({                              \
319                 unsigned long remainder;\
320                 remainder = (a) % (b);  \
321                 (a) = (a) / (b);        \
322                 (remainder);            \
323         })
324
325
326 /* !__KERNEL__ */
327 #endif
328
329 /* __LIBCFS_USER_PRIM_H__ */
330 #endif
331 /*
332  * Local variables:
333  * c-indentation-style: "K&R"
334  * c-basic-offset: 8
335  * tab-width: 8
336  * fill-column: 80
337  * scroll-step: 1
338  * End:
339  */