1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 /*
32  *
33  * HEADER: dapl_osd.h
34  *
35  * PURPOSE: Operating System Dependent layer
36  * Description:
37  *	Provide OS dependent data structures & functions with
38  *	a canonical DAPL interface. Designed to be portable
39  *	and hide OS specific quirks of common functions.
40  *
41  * $Id: dapl_osd.h,v 1.38 2003/08/20 14:08:57 sjs2 Exp $
42  */
43 
44 #ifndef _DAPL_OSD_H_
45 #define	_DAPL_OSD_H_
46 
47 #ifdef __cplusplus
48 extern "C" {
49 #endif
50 
51 /*
52  * <assert.h> keys off of NDEBUG
53  */
54 #ifdef	DAPL_DBG
55 #undef	NDEBUG
56 #else
57 #define	NDEBUG
58 #endif
59 
60 #include <dat/udat.h>
61 #include <assert.h>
62 #include <errno.h>
63 #include <pthread.h>
64 #include <semaphore.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <stdarg.h>
69 #include <time.h>
70 #include <syslog.h>
71 #include <netdb.h>
72 #include <atomic.h>
73 #include "dapl_debug.h"
74 
75 /*
76  * networking related headers
77  */
78 #include <unistd.h>
79 #include <fcntl.h>
80 #include <sys/types.h>
81 #include <sys/socket.h>
82 #include <ctype.h>
83 #include <arpa/inet.h>
84 
85 #ifndef _INLINE_
86 #define	_INLINE_
87 #endif /* _INLINE_ */
88 
89 /*
90  * initialization function
91  */
92 void dapl_os_init(void);
93 
94 #define	dapl_os_panic(args) 			\
95 {					\
96 	fprintf(stderr, "PANIC in %s:%i:\n", __FILE__, __LINE__); \
97 	fprintf(stderr, args);			\
98 	exit(1);				\
99 }
100 
101 int dapl_os_get_env_bool(
102 	char		*env_str);
103 
104 int dapl_os_get_env_val(
105 	char		*env_str,
106 	int		def_val);
107 
108 /*
109  * Atomic operations
110  */
111 typedef volatile DAT_COUNT DAPL_ATOMIC;
112 
113 /*
114  * dapl_os_atomic_inc
115  *
116  * get the current value of '*v', and then increment it.
117  *
118  * This is equivalent to an IB atomic fetch and add of 1,
119  * except that a DAT_COUNT might be 32 bits, rather than 64
120  * and it occurs in local memory.
121  *
122  * DAT_COUNT dapl_os_atomic_inc(INOUT	DAPL_ATOMIC *v)
123  */
124 #define	dapl_os_atomic_inc(v)	((DAT_COUNT)			\
125 				(atomic_add_32_nv((uint32_t *)(v), 1) - 1))
126 
127 /*
128  * dapl_os_atomic_dec
129  *
130  * decrement the current value of '*v'. No return value is required.
131  *
132  * DAT_COUNT dapl_os_atomic_dec(INOUT	DAPL_ATOMIC *v)
133  */
134 #define	dapl_os_atomic_dec(v)	assert(*v != 0);		\
135 				((DAT_COUNT)			\
136 				(atomic_add_32_nv((uint32_t *)(v), -1) + 1))
137 
138 /*
139  * dapl_os_atomic_assign
140  *
141  * assign 'new_value' to '*v' if the current value
142  * matches the provided 'match_value'.
143  *
144  * Make no assignment if there is no match.
145  *
146  * Return the current value in any case.
147  *
148  * This matches the IBTA atomic operation compare & swap
149  * except that it is for local memory and a DAT_COUNT may
150  * be only 32 bits, rather than 64.
151  *
152  * DAT_COUNT dapl_os_atomic_assign(INOUT DAPL_ATOMIC *v,
153  *	IN DAT_COUNT match_value, IN DAT_COUNT new_value)
154  */
155 #define	dapl_os_atomic_assign(v, match_value, new_value)		\
156 		atomic_cas_32((uint32_t *)(v), (uint32_t)(match_value),	\
157 		    (uint32_t)(new_value))
158 
159 /*
160  * Thread Functions
161  */
162 typedef pthread_t		DAPL_OS_THREAD;
163 
164 DAT_RETURN
165 dapl_os_thread_create(
166 	IN  void			(*func)	(void *),
167 	IN  void			*data,
168 	OUT DAPL_OS_THREAD		*thread_id);
169 
170 
171 /*
172  * Lock Functions
173  */
174 
175 typedef pthread_mutex_t 	DAPL_OS_LOCK;
176 
177 /*
178  * DAT_RETURN dapl_os_lock_init(IN DAPL_OS_LOCK *m)
179  */
180 #define	dapl_os_lock_init(m)	(void)					\
181 				((0 == pthread_mutex_init((m), NULL)) ?	\
182 					DAT_SUCCESS :			\
183 					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR))
184 
185 /* DAT_RETURN dapl_os_lock(IN DAPL_OS_LOCK *m) */
186 #define	dapl_os_lock(m)		((DAT_RETURN)(				\
187 				(0 == pthread_mutex_lock((m))) ?	\
188 					DAT_SUCCESS :			\
189 					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR)))
190 
191 /* DAT_RETURN dapl_os_unlock(IN DAPL_OS_LOCK *m) */
192 #define	dapl_os_unlock(m)	((DAT_RETURN)(				\
193 				(0 == pthread_mutex_unlock((m))) ?	\
194 					DAT_SUCCESS :			\
195 					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR)))
196 
197 /* DAT_RETURN dapl_os_lock_destroy(IN DAPL_OS_LOCK *m) */
198 #define	dapl_os_lock_destroy(m)	((DAT_RETURN)(				\
199 				(0 == pthread_mutex_destroy((m))) ?	\
200 					DAT_SUCCESS :			\
201 					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR)))
202 /*
203  * Wait Objects
204  */
205 
206 /*
207  * The wait object invariant: Presuming a call to dapl_os_wait_object_wait
208  * occurs at some point, there will be at least one wakeup after each call
209  * to dapl_os_wait_object_signal.  I.e. Signals are not ignored, though
210  * they may be coallesced.
211  */
212 
213 typedef struct
214 {
215     DAT_BOOLEAN		signaled;
216     pthread_cond_t	cv;
217     pthread_mutex_t	lock;
218 } DAPL_OS_WAIT_OBJECT;
219 
220 /* function prototypes */
221 DAT_RETURN
222 dapl_os_wait_object_init(
223     IN DAPL_OS_WAIT_OBJECT *wait_obj);
224 
225 DAT_RETURN
226 dapl_os_wait_object_wait(
227     IN	DAPL_OS_WAIT_OBJECT *wait_obj,
228     IN  DAT_TIMEOUT timeout_val);
229 
230 DAT_RETURN
231 dapl_os_wait_object_wakeup(
232     IN	DAPL_OS_WAIT_OBJECT *wait_obj);
233 
234 DAT_RETURN
235 dapl_os_wait_object_destroy(
236     IN	DAPL_OS_WAIT_OBJECT *wait_obj);
237 
238 /*
239  * Memory Functions
240  */
241 
242 /* void *dapl_os_alloc(int size) */
243 #define	dapl_os_alloc(size)	malloc((size))
244 
245 /* void *dapl_os_realloc(void *ptr, int size) */
246 #define	dapl_os_realloc(ptr, size) realloc((ptr), (size))
247 
248 /* void dapl_os_free(void *ptr, int size) */
249 #define	dapl_os_free(ptr, size)	free((ptr))
250 
251 /* void * dapl_os_memzero(void *loc, int size) */
252 #define	dapl_os_memzero(loc, size)	memset((loc), 0, (size))
253 
254 /* void * dapl_os_memcpy(void *dest, const void *src, int len) */
255 #define	dapl_os_memcpy(dest, src, len)	memcpy((dest), (src), (len))
256 
257 /* int dapl_os_memcmp(const void *mem1, const void *mem2, int len) */
258 #define	dapl_os_memcmp(mem1, mem2, len)	memcmp((mem1), (mem2), (len))
259 
260 /*
261  * String Functions
262  */
263 
264 /* unsigned int dapl_os_strlen(const char *str) */
265 #define	dapl_os_strlen(str)	strlen((str))
266 /* char * dapl_os_strdup(const char *str) */
267 #define	dapl_os_strdup(str)	strdup((str))
268 /* char *strcpy(char *dest, char *src) */
269 #define	dapl_os_strcpy(dest, src) 	strcpy((dest), (src))
270 /* char *strncpy(char *s1, const char *s2, size_t n) */
271 #define	dapl_os_strncpy(dest, src, len) strncpy((dest), (src), (len))
272 /* char *strcat(char *dest, char *src) */
273 #define	dapl_os_strcat(dest, src) 	strcat((dest), (src))
274 
275 /*
276  * Timer Functions
277  */
278 
279 typedef DAT_UINT64		DAPL_OS_TIMEVAL;
280 
281 
282 typedef unsigned long long int	DAPL_OS_TICKS;
283 
284 /* function prototypes */
285 
286 /*
287  * Sleep for the number of micro seconds specified by the invoking
288  * function
289  *
290  * void dapl_os_sleep_usec(int sleep_time)
291  */
292 #define	dapl_os_sleep_usec(sleep_time)	{				\
293 		struct timespec sleep_spec;				\
294 		sleep_spec.tv_sec = (sleep_time) / 100000;		\
295 		sleep_spec.tv_nsec = (sleep_time) % 100000 * 1000;	\
296 		nanosleep(&sleep_spec, NULL);				\
297 		}
298 
299 DAT_RETURN dapl_os_get_time(DAPL_OS_TIMEVAL *);
300 
301 /*
302  *
303  * Name Service Helper functions
304  *
305  */
306 #if defined(IBHOSTS_NAMING)
307 #define	dapls_osd_getaddrinfo(name, addr_ptr)		\
308 				getaddrinfo((name), NULL, NULL, (addr_ptr))
309 #define	dapls_osd_freeaddrinfo(addr) freeaddrinfo((addr))
310 
311 #endif /* IBHOSTS_NAMING */
312 
313 /*
314  * *printf format helpers. We use the C string constant concatenation
315  * ability to define 64 bit formats, which unfortunatly are non standard
316  * in the C compiler world. E.g. %llx for gcc, %I64x for Windows
317  */
318 #define	F64d   "%lld"
319 #define	F64u   "%llu"
320 #define	F64x   "%llx"
321 #define	F64X   "%llX"
322 
323 
324 /*
325  *  Conversion Functions
326  */
327 
328 /* long int dapl_os_strtol(const char *nptr, char **endptr, int base) */
329 #define	dapl_os_strtol(nptr, endptr, base)	strtol((nptr), (endptr), (base))
330 
331 /*
332  *  Helper Functions
333  */
334 
335 
336 #define	dapl_os_assert(expression)	assert((expression))
337 #define	dapl_os_printf			printf
338 #define	dapl_os_vprintf(fmt, args)	vprintf((fmt), (args))
339 #define	dapl_os_syslog(fmt, args)	vsyslog(LOG_USER | LOG_DEBUG,	\
340 						(fmt), (args))
341 #ifdef __cplusplus
342 }
343 #endif
344 
345 #endif /* _DAPL_OSD_H_ */
346