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