Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / libcfs / include / libcfs / util / platform.h
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  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * libcfs/include/libcfs/libcfsutil.h
37  *
38  * A portability layer for multi-threaded userspace applications.
39  *
40  */
41
42 #ifndef __LUSTRE_UTILS_PLATFORM_H
43 #define __LUSTRE_UTILS_PLATFORM_H
44
45 #ifdef __linux__
46
47 #ifdef HAVE_LIBREADLINE
48 #define READLINE_LIBRARY
49 #include <readline/readline.h>
50
51 /* completion_matches() is #if 0-ed out in modern glibc */
52
53 #ifndef completion_matches
54 #  define completion_matches rl_completion_matches
55 #endif
56 extern void using_history(void);
57 extern void stifle_history(int);
58 extern void add_history(char *);
59 #endif /* HAVE_LIBREADLINE */
60
61 #include <errno.h>
62 #include <string.h>
63 #if HAVE_LIBPTHREAD
64 #include <sys/ipc.h>
65 #include <sys/shm.h>
66 #include <pthread.h>
67
68 typedef pthread_mutex_t l_mutex_t;
69 typedef pthread_cond_t  l_cond_t;
70 #define l_mutex_init(s)         pthread_mutex_init(s, NULL)
71 #define l_mutex_lock(s)         pthread_mutex_lock(s)
72 #define l_mutex_unlock(s)       pthread_mutex_unlock(s)
73 #define l_cond_init(c)          pthread_cond_init(c, NULL)
74 #define l_cond_broadcast(c)     pthread_cond_broadcast(c)
75 #define l_cond_wait(c, s)       pthread_cond_wait(c, s)
76 #endif
77
78 #elif __APPLE__
79
80 #ifdef HAVE_LIBREADLINE
81 #define READLINE_LIBRARY
82 #include <readline/readline.h>
83 typedef VFunction       rl_vintfunc_t;
84 typedef VFunction       rl_voidfunc_t;
85 #endif /* HAVE_LIBREADLINE */
86
87 #include <stdlib.h>
88 #include <errno.h>
89 #include <sys/types.h>
90 #include <fcntl.h>
91 #include <stdio.h>
92 #include <sys/shm.h>
93 #include <sys/semaphore.h>
94
95 /*
96  * POSIX compliant inter-process synchronization aren't supported well
97  * in Darwin, pthread_mutex_t and pthread_cond_t can only work as
98  * inter-thread synchronization, they wouldn't work even being put in
99  * shared memory for multi-process. PTHREAD_PROCESS_SHARED is not 
100  * supported by Darwin also (pthread_mutexattr_setpshared() with the 
101  * PTHREAD_PROCESS_SHARED attribute will return EINVAL). 
102  *
103  * The only inter-process sychronization mechanism can be used in Darwin
104  * is POSIX NAMED semaphores and file lock, here we use NAMED semaphore
105  * to implement mutex and condition. 
106  *
107  * XXX Liang:
108  * They are just proto-type now, more tests are needed. 
109  */
110 #define L_LOCK_DEBUG            (0)             
111
112 #define L_SEM_NAMESIZE          32
113
114 typedef struct {
115         sem_t           *s_sem;
116 #if L_LOCK_DEBUG
117         char            s_name[L_SEM_NAMESIZE];
118 #endif
119 } l_sem_t;
120
121 typedef l_sem_t         l_mutex_t;
122
123 typedef struct {
124         l_mutex_t       c_guard;
125         int             c_count;
126         l_sem_t         c_waiter;
127 } l_cond_t;
128
129 static inline int l_sem_init(l_sem_t *sem, int val)
130 {
131         char *s_name;
132 #if L_LOCK_DEBUG
133         s_name = sem->s_name;
134 #else
135         char buf[L_SEM_NAMESIZE];
136         s_name = buf;
137 #endif
138         /* get an unique name for named semaphore */
139         snprintf(s_name, L_SEM_NAMESIZE, "%d-%p", (int)getpid(), sem);
140         sem->s_sem = sem_open(s_name, O_CREAT, 0600, val);
141         if ((int)sem->s_sem == SEM_FAILED) {
142                 fprintf(stderr, "lock %s creating fail: %d, %d!\n",
143                                 s_name, (int)sem->s_sem, errno);
144                 return -1;
145         } else {
146 #if L_LOCK_DEBUG
147                 printf("open lock: %s\n", s_name);
148 #endif
149         }
150         return 0;
151 }
152
153 static inline void l_sem_done(l_sem_t *sem)
154 {
155 #if L_LOCK_DEBUG
156         printf("close lock: %s.\n", sem->s_name);
157 #endif
158         sem_close(sem->s_sem);
159 }
160
161 static inline void l_sem_down(l_sem_t *sem)
162 {
163 #if L_LOCK_DEBUG
164         printf("sem down :%s\n", sem->s_name);
165 #endif
166         sem_wait(sem->s_sem);
167 }
168
169 static inline void l_sem_up(l_sem_t *sem)
170 {
171 #if L_LOCK_DEBUG
172         printf("sem up  :%s\n", sem->s_name);
173 #endif
174         sem_post(sem->s_sem);
175 }
176
177 static inline void l_mutex_init(l_mutex_t *mutex)
178 {
179         l_sem_init((l_sem_t *)mutex, 1);
180 }
181
182 static inline void l_mutex_init_locked(l_mutex_t *mutex)
183 {
184         l_sem_init((l_sem_t *)mutex, 0);
185 }
186
187 static inline void l_mutex_done(l_mutex_t *mutex)
188 {
189         l_sem_done((l_sem_t *)mutex);
190 }
191
192 static inline void l_mutex_lock(l_mutex_t *mutex)
193 {
194 #if L_LOCK_DEBUG
195         printf("lock mutex  :%s\n", mutex->s_name);
196 #endif
197         sem_wait(mutex->s_sem);
198 }
199
200 static inline void l_mutex_unlock(l_mutex_t *mutex)
201 {
202 #if L_LOCK_DEBUG
203         printf("unlock mutex: %s\n", mutex->s_name);
204 #endif
205         sem_post(mutex->s_sem);
206 }
207
208 static inline void l_cond_init(l_cond_t *cond)
209 {
210         l_mutex_init(&cond->c_guard);
211         l_sem_init(&cond->c_waiter, 0);
212         cond->c_count = 0;
213 }
214
215 static inline void l_cond_done(l_cond_t *cond)
216 {
217         if (cond->c_count != 0)
218                 fprintf(stderr, "your waiter list is not empty: %d!\n", cond->c_count);
219         l_mutex_done(&cond->c_guard);
220         l_sem_done(&cond->c_waiter);
221 }
222
223 static inline void l_cond_wait(l_cond_t *cond, l_mutex_t *lock)
224 {
225         l_mutex_lock(&cond->c_guard);
226         cond->c_count --;
227         l_mutex_unlock(&cond->c_guard);
228         l_mutex_unlock(lock);
229         l_sem_down(&cond->c_waiter);
230         l_mutex_lock(lock);
231 }
232
233 static inline void l_cond_broadcast(l_cond_t *cond)
234 {
235         l_mutex_lock(&cond->c_guard);
236         while (cond->c_count < 0) {
237                 l_sem_up(&cond->c_waiter);
238                 cond->c_count ++;
239         }
240         l_mutex_unlock(&cond->c_guard);
241 }
242
243 #else /* other platform */
244
245 #ifdef HAVE_LIBREADLINE
246 #define READLINE_LIBRARY
247 #include <readline/readline.h>
248 #endif /* HAVE_LIBREADLINE */
249 #include <errno.h>
250 #include <string.h>
251 #if HAVE_LIBPTHREAD
252 #include <sys/ipc.h>
253 #include <sys/shm.h>
254 #include <pthread.h>
255
256 typedef pthread_mutex_t l_mutex_t;
257 typedef pthread_cond_t  l_cond_t;
258 #define l_mutex_init(s)         pthread_mutex_init(s, NULL)
259 #define l_mutex_lock(s)         pthread_mutex_lock(s)
260 #define l_mutex_unlock(s)       pthread_mutex_unlock(s)
261 #define l_cond_init(c)          pthread_cond_init(c, NULL)
262 #define l_cond_broadcast(c)     pthread_cond_broadcast(c)
263 #define l_cond_wait(c, s)       pthread_cond_wait(c, s)
264 #endif /* HAVE_LIBPTHREAD */
265
266 #endif /* __linux__  */
267
268 #endif