[DAPL2] DAPL Counters & 2.0.3 extensions to support counter retrieval.
[mirror/winof/.git] / ulp / dapl2 / dapl / udapl / linux / dapl_osd.h
1 /*\r
2  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
3  *\r
4  * This Software is licensed under one of the following licenses:\r
5  *\r
6  * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
7  *    available from the Open Source Initiative, see\r
8  *    http://www.opensource.org/licenses/cpl.php.\r
9  *\r
10  * 2) under the terms of the "The BSD License" a copy of which is\r
11  *    available from the Open Source Initiative, see\r
12  *    http://www.opensource.org/licenses/bsd-license.php.\r
13  *\r
14  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
15  *    copy of which is available from the Open Source Initiative, see\r
16  *    http://www.opensource.org/licenses/gpl-license.php.\r
17  *\r
18  * Licensee has the right to choose one of the above licenses.\r
19  *\r
20  * Redistributions of source code must retain the above copyright\r
21  * notice and one of the license notices.\r
22  *\r
23  * Redistributions in binary form must reproduce both the above copyright\r
24  * notice, one of the license notices in the documentation\r
25  * and/or other materials provided with the distribution.\r
26  */\r
27 \r
28 /**********************************************************************\r
29  * \r
30  * HEADER: dapl_osd.h\r
31  *\r
32  * PURPOSE: Operating System Dependent layer\r
33  * Description:\r
34  *      Provide OS dependent data structures & functions with\r
35  *      a canonical DAPL interface. Designed to be portable\r
36  *      and hide OS specific quirks of common functions.\r
37  *\r
38  * $Id:$\r
39  **********************************************************************/\r
40 \r
41 #ifndef _DAPL_OSD_H_\r
42 #define _DAPL_OSD_H_\r
43 \r
44 /*\r
45  * This file is defined for Linux systems only, including it on any\r
46  * other build will cause an error\r
47  */\r
48 #ifndef __linux__\r
49 #error UNDEFINED OS TYPE\r
50 #endif /* __linux__ */\r
51 \r
52 #if !defined (__i386__) && !defined (__ia64__) && !defined(__x86_64__) && !defined(__PPC__) && !defined(__PPC64__)\r
53 #error UNDEFINED ARCH\r
54 #endif\r
55 \r
56 \r
57 #include <dat/udat.h>\r
58 #include <assert.h>\r
59 #include <errno.h>\r
60 #include <pthread.h>\r
61 #include <semaphore.h>\r
62 #include <stdint.h>\r
63 #include <stdio.h>\r
64 #include <stdlib.h>\r
65 #include <string.h>\r
66 #include <stdarg.h>                     /* for printf */\r
67 #include <sys/time.h>\r
68 #include <syslog.h>\r
69 #include <netdb.h>                      /* for getaddrinfo */\r
70 \r
71 #include "dapl_debug.h"\r
72 \r
73 /*\r
74  * Include files for setting up a network name\r
75  */\r
76 #include <unistd.h>\r
77 #include <sys/types.h>\r
78 #include <sys/socket.h>\r
79 #include <ctype.h>\r
80 \r
81 #if !defined(REDHAT_EL5) && (defined(__ia64__))\r
82 #include <asm/atomic.h>\r
83 #endif\r
84 \r
85 /* Useful debug definitions */\r
86 #ifndef STATIC\r
87 #define STATIC static\r
88 #endif /* STATIC */\r
89 #ifndef _INLINE_\r
90 #define _INLINE_ __inline__\r
91 #endif /* _INLINE_ */\r
92 \r
93 #define LINUX_VERSION(a,b) (((a) << 16) + (b))\r
94 \r
95 void dapl_os_init ( void );     /* initialization function */\r
96 \r
97 #define dapl_os_panic(...)                      \\r
98         do {                                    \\r
99              fprintf(stderr, "PANIC in %s:%i:%s\n", __FILE__, __LINE__, __func__); \\r
100              fprintf(stderr, __VA_ARGS__);      \\r
101              exit(1);                           \\r
102         } while(0)\r
103 \r
104 #define dapl_ip_addr6(sockaddr) (((struct sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr32)\r
105 \r
106 /*\r
107  * Atomic operations\r
108  */\r
109 \r
110 typedef volatile DAT_COUNT DAPL_ATOMIC;\r
111 \r
112 /* atomic function prototypes */\r
113 STATIC _INLINE_ void /* DAT_COUNT */\r
114 dapl_os_atomic_inc (\r
115         INOUT   DAPL_ATOMIC *v);\r
116 \r
117 STATIC _INLINE_ void /* DAT_COUNT */\r
118 dapl_os_atomic_dec ( \r
119         INOUT   DAPL_ATOMIC *v);\r
120 \r
121 STATIC _INLINE_ DAT_COUNT\r
122 dapl_os_atomic_assign (\r
123     INOUT DAPL_ATOMIC *v,\r
124     IN  DAT_COUNT match_value,\r
125     IN  DAT_COUNT new_value );\r
126 \r
127 #define dapl_os_atomic_read(v)  (*v)\r
128 #define dapl_os_atomic_set(v,i) (*v = i)\r
129 \r
130 int dapl_os_get_env_bool (\r
131         char            *env_str );\r
132 \r
133 int dapl_os_get_env_val (\r
134         char            *env_str,\r
135         int             def_val );\r
136 \r
137 \r
138 \r
139 /* atomic functions */\r
140 \r
141 /* dapl_os_atomic_inc\r
142  *\r
143  * get the current value of '*v', and then increment it.\r
144  *\r
145  * This is equivalent to an IB atomic fetch and add of 1,\r
146  * except that a DAT_COUNT might be 32 bits, rather than 64\r
147  * and it occurs in local memory.\r
148  */\r
149 \r
150 STATIC _INLINE_ void\r
151 dapl_os_atomic_inc (\r
152         INOUT   DAPL_ATOMIC *v)\r
153 {\r
154 #ifdef __ia64__\r
155         DAT_COUNT       old_value;\r
156 #if defined(REDHAT_EL5)\r
157         old_value = __sync_fetch_and_add(v, 1); \r
158 #elif !defined(REDHAT_EL4) && (OS_RELEASE >= LINUX_VERSION(2,6))\r
159         IA64_FETCHADD(old_value,v,1,4,rel);\r
160 #else\r
161         IA64_FETCHADD(old_value,v,1,4);\r
162 #endif\r
163 #elif defined(__PPC__) || defined(__PPC64__)\r
164         int tmp;\r
165 \r
166     __asm__ __volatile__(\r
167         "1:     lwarx   %0,0,%2\n\\r
168                 addic   %0,%0,1\n\\r
169                 stwcx.  %0,0,%2\n\\r
170                 bne-    1b"\r
171         : "=&r" (tmp), "+m" (v)\r
172         : "r" (&v)\r
173         : "cc");\r
174 #else  /* !__ia64__ */\r
175     __asm__ __volatile__ (\r
176         "lock;" "incl %0"\r
177         :"=m" (*v)\r
178         :"m" (*v));\r
179 #endif\r
180     return;\r
181 }\r
182 \r
183 \r
184 /* dapl_os_atomic_dec\r
185  *\r
186  * decrement the current value of '*v'. No return value is required.\r
187  */\r
188 \r
189 STATIC _INLINE_ void\r
190 dapl_os_atomic_dec ( \r
191         INOUT   DAPL_ATOMIC *v)\r
192 {\r
193 #ifdef __ia64__\r
194         DAT_COUNT       old_value;\r
195 #if defined(REDHAT_EL5)\r
196         old_value = __sync_fetch_and_sub(v, 1); \r
197 #elif !defined(REDHAT_EL4) && (OS_RELEASE >= LINUX_VERSION(2,6))\r
198         IA64_FETCHADD(old_value,v,-1,4,rel);\r
199 #else\r
200         IA64_FETCHADD(old_value,v,-1,4);\r
201 #endif\r
202 #elif defined (__PPC__) || defined(__PPC64__)\r
203         int tmp;\r
204 \r
205     __asm__ __volatile__(\r
206         "1:     lwarx   %0,0,%2\n\\r
207                 addic   %0,%0,-1\n\\r
208                 stwcx.  %0,0,%2\n\\r
209                 bne-    1b"\r
210         : "=&r" (tmp), "+m" (v)\r
211         : "r" (&v)\r
212         : "cc");\r
213 #else  /* !__ia64__ */\r
214     __asm__ __volatile__ (\r
215         "lock;" "decl %0"\r
216         :"=m" (*v)\r
217         :"m" (*v));\r
218 #endif\r
219     return;\r
220 }\r
221 \r
222 \r
223 /* dapl_os_atomic_assign\r
224  *\r
225  * assign 'new_value' to '*v' if the current value\r
226  * matches the provided 'match_value'.\r
227  *\r
228  * Make no assignment if there is no match.\r
229  *\r
230  * Return the current value in any case.\r
231  *\r
232  * This matches the IBTA atomic operation compare & swap\r
233  * except that it is for local memory and a DAT_COUNT may\r
234  * be only 32 bits, rather than 64.\r
235  */\r
236 \r
237 STATIC _INLINE_ DAT_COUNT\r
238 dapl_os_atomic_assign (\r
239     INOUT DAPL_ATOMIC *v,\r
240     IN  DAT_COUNT match_value,\r
241     IN  DAT_COUNT new_value )\r
242 {\r
243     DAT_COUNT   current_value;\r
244 \r
245     /*\r
246      * Use the Pentium compare and exchange instruction\r
247      */\r
248 \r
249 #ifdef __ia64__\r
250 #if defined(REDHAT_EL5)\r
251     current_value = __sync_val_compare_and_swap(v,match_value,new_value); \r
252 #elif defined(REDHAT_EL4) \r
253     current_value = ia64_cmpxchg("acq",v,match_value,new_value,4);\r
254 #else\r
255     current_value = ia64_cmpxchg(acq,v,match_value,new_value,4);\r
256 #endif /* __ia64__ */\r
257 #elif defined(__PPC__) || defined(__PPC64__)\r
258         __asm__ __volatile__ (\r
259 "       lwsync\n\\r
260 1:      lwarx   %0,0,%2         # __cmpxchg_u32\n\\r
261         cmpw    0,%0,%3\n\\r
262         bne-    2f\n\\r
263         stwcx.  %4,0,%2\n\\r
264         bne-    1b\n\\r
265         isync\n\\r
266 2:"\r
267         : "=&r" (current_value), "=m" (*v)\r
268         : "r" (v), "r" (match_value), "r" (new_value), "m" (*v)\r
269         : "cc", "memory");\r
270 #else\r
271     __asm__ __volatile__ (\r
272         "lock; cmpxchgl %1, %2"\r
273         : "=a" (current_value)\r
274         : "q" (new_value), "m" (*v), "0" (match_value)\r
275         : "memory");\r
276 #endif\r
277     return current_value;\r
278 }\r
279 \r
280 /*\r
281  * Thread Functions\r
282  */\r
283 typedef pthread_t               DAPL_OS_THREAD;\r
284 \r
285 DAT_RETURN \r
286 dapl_os_thread_create (\r
287         IN  void                        (*func) (void *),\r
288         IN  void                        *data,\r
289         OUT DAPL_OS_THREAD              *thread_id );\r
290 \r
291 \r
292 /*\r
293  * Lock Functions\r
294  */\r
295 \r
296 typedef pthread_mutex_t         DAPL_OS_LOCK;\r
297 \r
298 /* function prototypes */\r
299 STATIC _INLINE_ DAT_RETURN \r
300 dapl_os_lock_init (\r
301     IN  DAPL_OS_LOCK *m);\r
302 \r
303 STATIC _INLINE_ DAT_RETURN \r
304 dapl_os_lock (\r
305     IN  DAPL_OS_LOCK *m);\r
306 \r
307 STATIC _INLINE_ DAT_RETURN \r
308 dapl_os_unlock (\r
309     IN  DAPL_OS_LOCK *m);\r
310 \r
311 STATIC _INLINE_ DAT_RETURN \r
312 dapl_os_lock_destroy (\r
313     IN  DAPL_OS_LOCK *m);\r
314 \r
315 /* lock functions */\r
316 STATIC _INLINE_ DAT_RETURN \r
317 dapl_os_lock_init (\r
318     IN  DAPL_OS_LOCK *m)\r
319 {\r
320     /* pthread_mutex_init always returns 0 */\r
321     pthread_mutex_init (m, NULL);\r
322 \r
323     return DAT_SUCCESS;\r
324 }\r
325 \r
326 STATIC _INLINE_ DAT_RETURN \r
327 dapl_os_lock (\r
328     IN  DAPL_OS_LOCK *m)\r
329 {\r
330     if (0 == pthread_mutex_lock (m))\r
331     {\r
332         return DAT_SUCCESS;\r
333     }\r
334     else\r
335     {\r
336         return DAT_CLASS_ERROR | DAT_INTERNAL_ERROR;\r
337     }\r
338 }\r
339 \r
340 STATIC _INLINE_ DAT_RETURN \r
341 dapl_os_unlock (\r
342     IN  DAPL_OS_LOCK *m)\r
343 {\r
344     if (0 == pthread_mutex_unlock (m))\r
345     {\r
346         return DAT_SUCCESS;\r
347     }\r
348     else\r
349     {\r
350         return DAT_CLASS_ERROR | DAT_INTERNAL_ERROR;\r
351     }\r
352 }\r
353 \r
354 STATIC _INLINE_ DAT_RETURN \r
355 dapl_os_lock_destroy (\r
356     IN  DAPL_OS_LOCK *m)\r
357 {\r
358     if (0 == pthread_mutex_destroy (m))\r
359     {\r
360         return DAT_SUCCESS;\r
361     }\r
362     else\r
363     {\r
364         return DAT_CLASS_ERROR | DAT_INTERNAL_ERROR;\r
365     }\r
366 }\r
367 \r
368 \r
369 /*\r
370  * Wait Objects\r
371  */\r
372 \r
373 /*\r
374  * The wait object invariant: Presuming a call to dapl_os_wait_object_wait\r
375  * occurs at some point, there will be at least one wakeup after each call\r
376  * to dapl_os_wait_object_signal.  I.e. Signals are not ignored, though\r
377  * they may be coallesced.\r
378  */\r
379 \r
380 typedef struct\r
381 {\r
382     DAT_BOOLEAN         signaled;\r
383     pthread_cond_t      cv;\r
384     pthread_mutex_t     lock;\r
385 } DAPL_OS_WAIT_OBJECT;\r
386 \r
387 /* function prototypes */\r
388 DAT_RETURN \r
389 dapl_os_wait_object_init (\r
390     IN DAPL_OS_WAIT_OBJECT *wait_obj);\r
391 \r
392 DAT_RETURN \r
393 dapl_os_wait_object_wait (\r
394     IN  DAPL_OS_WAIT_OBJECT *wait_obj, \r
395     IN  DAT_TIMEOUT timeout_val);\r
396 \r
397 DAT_RETURN \r
398 dapl_os_wait_object_wakeup (\r
399     IN  DAPL_OS_WAIT_OBJECT *wait_obj);\r
400 \r
401 DAT_RETURN \r
402 dapl_os_wait_object_destroy (\r
403     IN  DAPL_OS_WAIT_OBJECT *wait_obj);\r
404 \r
405 /*\r
406  * Memory Functions\r
407  */\r
408 \r
409 /* function prototypes */\r
410 STATIC _INLINE_ void *dapl_os_alloc (int size);\r
411 \r
412 STATIC _INLINE_ void *dapl_os_realloc (void *ptr, int size);\r
413 \r
414 STATIC _INLINE_ void dapl_os_free (void *ptr, int size);\r
415 \r
416 STATIC _INLINE_ void * dapl_os_memzero (void *loc, int size);\r
417 \r
418 STATIC _INLINE_ void * dapl_os_memcpy (void *dest, const void *src, int len);\r
419 \r
420 STATIC _INLINE_ int dapl_os_memcmp (const void *mem1, const void *mem2, int len);\r
421 \r
422 /* memory functions */\r
423 \r
424 \r
425 STATIC _INLINE_ void *dapl_os_alloc (int size)\r
426 {\r
427     return malloc (size);\r
428 }\r
429 \r
430 STATIC _INLINE_ void *dapl_os_realloc (void *ptr, int size)\r
431 {\r
432     return realloc(ptr, size);\r
433 }\r
434 \r
435 STATIC _INLINE_ void dapl_os_free (void *ptr, int size)\r
436 {\r
437     free (ptr);\r
438 }\r
439 \r
440 STATIC _INLINE_ void * dapl_os_memzero (void *loc, int size)\r
441 {\r
442     return memset (loc, 0, size);\r
443 }\r
444 \r
445 STATIC _INLINE_ void * dapl_os_memcpy (void *dest, const void *src, int len)\r
446 {\r
447     return memcpy (dest, src, len);\r
448 }\r
449 \r
450 STATIC _INLINE_ int dapl_os_memcmp (const void *mem1, const void *mem2, int len)\r
451 {\r
452     return memcmp (mem1, mem2, len);\r
453 }\r
454 \r
455 /*\r
456  * Memory coherency functions\r
457  * For i386 Linux, there are no coherency issues so we just return success.\r
458  */\r
459 STATIC _INLINE_  DAT_RETURN\r
460 dapl_os_sync_rdma_read (\r
461     IN      const DAT_LMR_TRIPLET       *local_segments,\r
462     IN      DAT_VLEN                    num_segments)\r
463 {\r
464     return DAT_SUCCESS;\r
465 }\r
466 \r
467 STATIC _INLINE_  DAT_RETURN\r
468 dapl_os_sync_rdma_write (\r
469     IN      const DAT_LMR_TRIPLET       *local_segments,\r
470     IN      DAT_VLEN                    num_segments)\r
471 {\r
472     return DAT_SUCCESS;\r
473 }\r
474 \r
475 \r
476 /*\r
477  * String Functions\r
478  */\r
479 \r
480 STATIC _INLINE_ unsigned int dapl_os_strlen(const char *str)\r
481 {\r
482     return strlen(str);\r
483 }\r
484 \r
485 STATIC _INLINE_ char * dapl_os_strdup(const char *str)\r
486 {\r
487     return strdup(str);\r
488 }\r
489 \r
490 \r
491 /*\r
492  * Timer Functions\r
493  */\r
494 \r
495 typedef DAT_UINT64                 DAPL_OS_TIMEVAL;\r
496 typedef struct dapl_timer_entry    DAPL_OS_TIMER;\r
497 typedef unsigned long long int     DAPL_OS_TICKS;\r
498 \r
499 /* function prototypes */\r
500 DAT_RETURN dapl_os_get_time (DAPL_OS_TIMEVAL *);\r
501 \r
502 \r
503 /*\r
504  *\r
505  * Name Service Helper functions\r
506  *\r
507  */\r
508 #if defined(IBHOSTS_NAMING) || defined(CM_BUSTED)\r
509 #define dapls_osd_getaddrinfo(name, addr_ptr) getaddrinfo(name,NULL,NULL,addr_ptr)\r
510 #define dapls_osd_freeaddrinfo(addr) freeaddrinfo (addr)\r
511 \r
512 #endif /* IBHOSTS_NAMING */\r
513 \r
514 /*\r
515  * *printf format helpers. We use the C string constant concatenation\r
516  * ability to define 64 bit formats, which unfortunatly are non standard\r
517  * in the C compiler world. E.g. %llx for gcc, %I64x for Windows\r
518  */\r
519 #include <inttypes.h>\r
520 #define F64d   "%"PRId64\r
521 #define F64u   "%"PRIu64\r
522 #define F64x   "%"PRIx64\r
523 #define F64X   "%"PRIX64\r
524 \r
525 \r
526 /*\r
527  *  Conversion Functions\r
528  */\r
529 \r
530 STATIC _INLINE_ long int\r
531 dapl_os_strtol(const char *nptr, char **endptr, int base)\r
532 {\r
533     return strtol(nptr, endptr, base);\r
534 }\r
535 \r
536 \r
537 /*\r
538  *  Helper Functions\r
539  */\r
540 \r
541 \r
542 #define dapl_os_assert(expression)      assert(expression)\r
543 #define dapl_os_printf(...)             printf(__VA_ARGS__)\r
544 #define dapl_os_vprintf(fmt,args)       vprintf(fmt,args)\r
545 #define dapl_os_syslog(fmt,args)        vsyslog(LOG_USER|LOG_WARNING,fmt,args)\r
546 \r
547 #define dapl_os_getpid getpid\r
548 \r
549 \r
550 #endif /*  _DAPL_OSD_H_ */\r
551 \r
552 /*\r
553  * Local variables:\r
554  *  c-indent-level: 4\r
555  *  c-basic-offset: 4\r
556  *  tab-width: 8\r
557  * End:\r
558  */\r