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
48extern "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 */
92void 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
101int dapl_os_get_env_bool(
102	char		*env_str);
103
104int dapl_os_get_env_val(
105	char		*env_str,
106	int		def_val);
107
108/*
109 * Atomic operations
110 */
111typedef 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 * void dapl_os_atomic_inc(INOUT	DAPL_ATOMIC *v)
123 */
124#define	dapl_os_atomic_inc(v)	atomic_add_32((uint32_t *)(v), 1)
125
126/*
127 * dapl_os_atomic_dec
128 *
129 * decrement the current value of '*v'. No return value is required.
130 *
131 * void dapl_os_atomic_dec(INOUT	DAPL_ATOMIC *v)
132 */
133#define	dapl_os_atomic_dec(v)	assert(*v != 0);		\
134				atomic_add_32((uint32_t *)(v), -1)
135
136/*
137 * dapl_os_atomic_assign
138 *
139 * assign 'new_value' to '*v' if the current value
140 * matches the provided 'match_value'.
141 *
142 * Make no assignment if there is no match.
143 *
144 * Return the current value in any case.
145 *
146 * This matches the IBTA atomic operation compare & swap
147 * except that it is for local memory and a DAT_COUNT may
148 * be only 32 bits, rather than 64.
149 *
150 * DAT_COUNT dapl_os_atomic_assign(INOUT DAPL_ATOMIC *v,
151 *	IN DAT_COUNT match_value, IN DAT_COUNT new_value)
152 */
153#define	dapl_os_atomic_assign(v, match_value, new_value)		\
154		atomic_cas_32((uint32_t *)(v), (uint32_t)(match_value),	\
155		    (uint32_t)(new_value))
156
157/*
158 * Thread Functions
159 */
160typedef pthread_t		DAPL_OS_THREAD;
161
162DAT_RETURN
163dapl_os_thread_create(
164	IN  void			(*func)	(void *),
165	IN  void			*data,
166	OUT DAPL_OS_THREAD		*thread_id);
167
168
169/*
170 * Lock Functions
171 */
172
173typedef pthread_mutex_t 	DAPL_OS_LOCK;
174
175/*
176 * DAT_RETURN dapl_os_lock_init(IN DAPL_OS_LOCK *m)
177 */
178#define	dapl_os_lock_init(m)	(void)					\
179				((0 == pthread_mutex_init((m), NULL)) ?	\
180					DAT_SUCCESS :			\
181					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR))
182
183/* DAT_RETURN dapl_os_lock(IN DAPL_OS_LOCK *m) */
184#define	dapl_os_lock(m)		((DAT_RETURN)(				\
185				(0 == pthread_mutex_lock((m))) ?	\
186					DAT_SUCCESS :			\
187					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR)))
188
189/* DAT_RETURN dapl_os_unlock(IN DAPL_OS_LOCK *m) */
190#define	dapl_os_unlock(m)	((DAT_RETURN)(				\
191				(0 == pthread_mutex_unlock((m))) ?	\
192					DAT_SUCCESS :			\
193					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR)))
194
195/* DAT_RETURN dapl_os_lock_destroy(IN DAPL_OS_LOCK *m) */
196#define	dapl_os_lock_destroy(m)	((DAT_RETURN)(				\
197				(0 == pthread_mutex_destroy((m))) ?	\
198					DAT_SUCCESS :			\
199					(DAT_CLASS_ERROR | DAT_INTERNAL_ERROR)))
200/*
201 * Wait Objects
202 */
203
204/*
205 * The wait object invariant: Presuming a call to dapl_os_wait_object_wait
206 * occurs at some point, there will be at least one wakeup after each call
207 * to dapl_os_wait_object_signal.  I.e. Signals are not ignored, though
208 * they may be coallesced.
209 */
210
211typedef struct
212{
213    DAT_BOOLEAN		signaled;
214    pthread_cond_t	cv;
215    pthread_mutex_t	lock;
216} DAPL_OS_WAIT_OBJECT;
217
218/* function prototypes */
219DAT_RETURN
220dapl_os_wait_object_init(
221    IN DAPL_OS_WAIT_OBJECT *wait_obj);
222
223DAT_RETURN
224dapl_os_wait_object_wait(
225    IN	DAPL_OS_WAIT_OBJECT *wait_obj,
226    IN  DAT_TIMEOUT timeout_val);
227
228DAT_RETURN
229dapl_os_wait_object_wakeup(
230    IN	DAPL_OS_WAIT_OBJECT *wait_obj);
231
232DAT_RETURN
233dapl_os_wait_object_destroy(
234    IN	DAPL_OS_WAIT_OBJECT *wait_obj);
235
236/*
237 * Memory Functions
238 */
239
240/* void *dapl_os_alloc(int size) */
241#define	dapl_os_alloc(size)	malloc((size))
242
243/* void *dapl_os_realloc(void *ptr, int size) */
244#define	dapl_os_realloc(ptr, size) realloc((ptr), (size))
245
246/* void dapl_os_free(void *ptr, int size) */
247#define	dapl_os_free(ptr, size)	free((ptr))
248
249/* void * dapl_os_memzero(void *loc, int size) */
250#define	dapl_os_memzero(loc, size)	memset((loc), 0, (size))
251
252/* void * dapl_os_memcpy(void *dest, const void *src, int len) */
253#define	dapl_os_memcpy(dest, src, len)	memcpy((dest), (src), (len))
254
255/* int dapl_os_memcmp(const void *mem1, const void *mem2, int len) */
256#define	dapl_os_memcmp(mem1, mem2, len)	memcmp((mem1), (mem2), (len))
257
258/*
259 * String Functions
260 */
261
262/* unsigned int dapl_os_strlen(const char *str) */
263#define	dapl_os_strlen(str)	strlen((str))
264/* char * dapl_os_strdup(const char *str) */
265#define	dapl_os_strdup(str)	strdup((str))
266/* char *strcpy(char *dest, char *src) */
267#define	dapl_os_strcpy(dest, src) 	strcpy((dest), (src))
268/* char *strncpy(char *s1, const char *s2, size_t n) */
269#define	dapl_os_strncpy(dest, src, len) strncpy((dest), (src), (len))
270/* char *strcat(char *dest, char *src) */
271#define	dapl_os_strcat(dest, src) 	strcat((dest), (src))
272
273/*
274 * Timer Functions
275 */
276
277typedef DAT_UINT64		DAPL_OS_TIMEVAL;
278
279
280typedef unsigned long long int	DAPL_OS_TICKS;
281
282/* function prototypes */
283
284/*
285 * Sleep for the number of micro seconds specified by the invoking
286 * function
287 *
288 * void dapl_os_sleep_usec(int sleep_time)
289 */
290#define	dapl_os_sleep_usec(sleep_time)	{				\
291		struct timespec sleep_spec;				\
292		sleep_spec.tv_sec = (sleep_time) / 100000;		\
293		sleep_spec.tv_nsec = (sleep_time) % 100000 * 1000;	\
294		nanosleep(&sleep_spec, NULL);				\
295		}
296
297DAT_RETURN dapl_os_get_time(DAPL_OS_TIMEVAL *);
298
299/*
300 *
301 * Name Service Helper functions
302 *
303 */
304#if defined(IBHOSTS_NAMING)
305#define	dapls_osd_getaddrinfo(name, addr_ptr)		\
306				getaddrinfo((name), NULL, NULL, (addr_ptr))
307#define	dapls_osd_freeaddrinfo(addr) freeaddrinfo((addr))
308
309#endif /* IBHOSTS_NAMING */
310
311/*
312 * *printf format helpers. We use the C string constant concatenation
313 * ability to define 64 bit formats, which unfortunatly are non standard
314 * in the C compiler world. E.g. %llx for gcc, %I64x for Windows
315 */
316#define	F64d   "%lld"
317#define	F64u   "%llu"
318#define	F64x   "%llx"
319#define	F64X   "%llX"
320
321
322/*
323 *  Conversion Functions
324 */
325
326/* long int dapl_os_strtol(const char *nptr, char **endptr, int base) */
327#define	dapl_os_strtol(nptr, endptr, base)	strtol((nptr), (endptr), (base))
328
329/*
330 *  Helper Functions
331 */
332
333
334#define	dapl_os_assert(expression)	assert((expression))
335#define	dapl_os_printf			printf
336#define	dapl_os_vprintf(fmt, args)	vprintf((fmt), (args))
337#define	dapl_os_syslog(fmt, args)	vsyslog(LOG_USER | LOG_DEBUG,	\
338						(fmt), (args))
339#ifdef __cplusplus
340}
341#endif
342
343#endif /* _DAPL_OSD_H_ */
344