1 // -*- c-basic-offset: 4; related-file-name: "../../lib/glue.cc" -*-
2 #ifndef CLICK_GLUE_HH
3 #define CLICK_GLUE_HH
4 // Removes many common #include <header>s and abstracts differences between
5 // kernel and user space, and between operating systems.
6 
7 // HEADERS
8 
9 #if CLICK_LINUXMODULE
10 
11 # define _LOOSE_KERNEL_NAMES 1 /* define ino_t, off_t, etc. */
12 # undef __KERNEL_STRICT_NAMES
13 # ifndef __OPTIMIZE__
14 #  define __OPTIMIZE__ 1 /* get ntohl() macros. otherwise undefined. */
15 # endif
16 # include <click/cxxprotect.h>
17 CLICK_CXX_PROTECT
18 # ifdef WANT_MOD_USE_COUNT
19 #  define __NO_VERSION__
20 #  include <linux/module.h>
21 #  define HAVE_MOD_USE_COUNT 1
22 # endif
23 # include <linux/kernel.h>
24 # include <linux/string.h>
25 # include <linux/skbuff.h>
26 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
27 #  include <linux/malloc.h>
28 #  include <linux/vmalloc.h>
29 #  include <linux/interrupt.h>
30 # else
31 #  include <linux/hardirq.h>
32 # endif
33 # include <linux/ctype.h>
34 # include <linux/time.h>
35 # include <linux/errno.h>
36 CLICK_CXX_UNPROTECT
37 # include <click/cxxunprotect.h>
38 
39 #elif CLICK_BSDMODULE
40 
41 # include <click/cxxprotect.h>
42 CLICK_CXX_PROTECT
43 # include <sys/ctype.h>
44 # include <sys/systm.h>
45 # include <sys/time.h>
46 # include <sys/param.h>
47 # include <sys/kernel.h>
48 # include <sys/mbuf.h>
49 # include <sys/malloc.h>
50 # include <sys/libkern.h>
51 # include <sys/proc.h>
52 # include <sys/sysproto.h>
53 # include <sys/limits.h>
54 # include <sys/module.h> /* XXX: for packages */
55 CLICK_CXX_UNPROTECT
56 # include <click/cxxunprotect.h>
57 
58 #elif CLICK_MINIOS
59 
60 # include <click/cxxprotect.h>
61 CLICK_CXX_PROTECT
62 # include <stdio.h>
63 # include <stdlib.h>
64 # include <stddef.h>
65 # include <stdint.h>
66 # include <string.h>
67 # include <ctype.h>
68 # include <errno.h>
69 # include <limits.h>
70 # include <time.h>
71 # include <sys/socket.h>
72 # include <netinet/in.h>
73 # include <sys/time.h>
74 CLICK_CXX_UNPROTECT
75 # include <click/cxxunprotect.h>
76 
77 #else /* CLICK_USERLEVEL */
78 
79 # include <stdio.h>
80 # include <stdlib.h>
81 # include <stddef.h>
82 # include <stdint.h>
83 # include <string.h>
84 # include <ctype.h>
85 # include <errno.h>
86 # include <limits.h>
87 # include <time.h>
88 # include <sys/socket.h>
89 # include <netinet/in.h>
90 # include <sys/time.h>
91 # if CLICK_NS
92 extern "C" int simclick_gettimeofday(struct timeval *);
93 # endif
94 # if HAVE_MULTITHREAD
95 #  include <pthread.h>
96 #  include <sched.h>
97 # endif
98 
99 #endif
100 
101 
102 // DEBUGGING OUTPUT
103 extern "C" {
104 void click_chatter(const char *fmt, ...);
105 }
106 
107 
108 // DEBUG MALLOC
109 
110 #if CLICK_DMALLOC && (CLICK_LINUXMODULE || CLICK_BSDMODULE || CLICK_MINIOS)
111 extern uint32_t click_dmalloc_where;
112 # define CLICK_DMALLOC_REG(s) do { const unsigned char *__str = reinterpret_cast<const unsigned char *>(s); click_dmalloc_where = (__str[0]<<24) | (__str[1]<<16) | (__str[2]<<8) | __str[3]; } while (0)
113 #else
114 # define CLICK_DMALLOC_REG(s)
115 #endif
116 
117 
118 // LALLOC
119 
120 #if CLICK_LINUXMODULE
121 # define CLICK_LALLOC(size)	(click_lalloc((size)))
122 # define CLICK_LFREE(p, size)	(click_lfree((p), (size)))
123 extern "C" {
124 void *click_lalloc(size_t size);
125 void click_lfree(volatile void *p, size_t size);
126 }
127 #else
128 # define CLICK_LALLOC(size)	((void *)(new uint8_t[(size)]))
129 # define CLICK_LFREE(p, size)	delete[] ((void) (size), (uint8_t *)(p))
130 #endif
131 
132 
133 // RANDOMNESS
134 
135 CLICK_DECLS
136 
137 /** @brief Return a number between 0 and CLICK_RAND_MAX, inclusive.
138  *
139  * CLICK_RAND_MAX is guaranteed to be at least 2^31 - 1. */
140 uint32_t click_random();
141 
142 /** @brief Return a number between @a low and @a high, inclusive.
143  *
144  * Returns @a low if @a low >= @a high. */
145 uint32_t click_random(uint32_t low, uint32_t high);
146 
147 /** @brief Set the click_random() seed to @a seed. */
148 void click_srandom(uint32_t seed);
149 
150 /** @brief Set the click_random() seed using a source of true randomness,
151  * if available. */
152 void click_random_srandom();
153 
154 #if CLICK_BSDMODULE
155 # define CLICK_RAND_MAX 0x7FFFFFFFU
156 #elif !CLICK_LINUXMODULE && RAND_MAX >= 0x7FFFFFFFU
157 # define CLICK_RAND_MAX RAND_MAX
158 #else
159 # define CLICK_RAND_MAX 0x7FFFFFFFU
160 extern uint32_t click_random_seed;
161 #endif
162 
163 #if CLICK_NS
164 extern uint32_t click_random();
165 #else
click_random()166 inline uint32_t click_random() {
167 # if CLICK_BSDMODULE
168     return random();
169 # elif CLICK_LINUXMODULE
170     click_random_seed = click_random_seed * 69069L + 5;
171     return (click_random_seed ^ jiffies) & CLICK_RAND_MAX; // XXX jiffies??
172 #elif CLICK_MINIOS
173     return rand();
174 # elif HAVE_RANDOM && CLICK_RAND_MAX == RAND_MAX
175     // See also click_random() in ns/nsclick.cc
176     return random();
177 # else
178     return rand();
179 # endif
180 }
181 #endif
182 
click_srandom(uint32_t seed)183 inline void click_srandom(uint32_t seed) {
184 #if CLICK_BSDMODULE
185     srandom(seed);
186 #elif CLICK_LINUXMODULE
187     click_random_seed = seed;
188 #elif CLICK_MINIOS
189     srand(seed);
190 #elif CLICK_NS
191     (void) seed; /* XXX */
192 #elif HAVE_RANDOM && CLICK_RAND_MAX == RAND_MAX
193     srandom(seed);
194 #else
195     srand(seed);
196 #endif
197 }
198 
199 CLICK_ENDDECLS
200 
201 
202 // SORTING
203 
204 /** @brief Sort array of elements according to @a compar.
205  * @param base pointer to array of elements
206  * @param n number of elements in @a param
207  * @param size size of an element
208  * @param compar comparison function
209  * @param user_data user data for comparison function
210  *
211  * Sorts an array of elements.  The comparison function is called as "@a
212  * param(@i a, @i b, @a user_data)", where @i a and @i b are pointers into the
213  * array starting at @a base, and @a user_data is click_qsort's @a user_data
214  * parameter.  The function should return an integer less than zero, equal to
215  * zero, or greater than zero depending on whether @i a compares less than @i
216  * b, equal to @i b, or greater than @i b, respectively.  On return the
217  * elements in the @a param array have been reordered into strictly increasing
218  * order.  The function always returns 0.
219  *
220  * Click_qsort() is not a stable sort.
221  *
222  * @warning click_qsort() shuffles elements by swapping memory, rather than by
223  * calling copy constructors or swap().  It is thus not safe for all types.
224  * In particular, objects like Bitvector that maintain pointers into their own
225  * representations are not safe to sort with click_qsort().  Conservatively,
226  * it is safe to sort fundamental data types (like int and pointers), plain
227  * old data types, and simple objects.  It is also safe to sort String and
228  * StringAccum objects, and to sort Vector objects that contain objects
229  * that are safe to sort themselves.
230  *
231  * @note The implementation is based closely on "Engineering a Sort Function,"
232  * Jon L. Bentley and M. Douglas McIlroy, <em>Software---Practice &
233  * Experience</em>, 23(11), 1249-1265, Nov. 1993.  It has been coded
234  * iteratively rather than recursively, and does no dynamic memory allocation,
235  * so it will not exhaust stack space in the kernel. */
236 int click_qsort(void *base, size_t n, size_t size,
237 		int (*compar)(const void *a, const void *b, void *user_data),
238 		void *user_data = 0);
239 
240 /** @brief Sort array of elements according to @a compar.
241  * @param base pointer to array of elements
242  * @param n number of elements in @a param
243  * @param size size of an element
244  * @param compar comparison function
245  *
246  * @deprecated Prefer the variant where @a compar takes an extra void
247  * *user_data argument.  This variant depends on a nonstandard function
248  * pointer cast. */
249 int click_qsort(void *base, size_t n, size_t size,
250 		int (*compar)(const void *a, const void *b)) CLICK_DEPRECATED;
251 
252 /** @brief Generic comparison function useful for click_qsort.
253  *
254  * Compares @a a and @a b using operator<(). */
click_compare(const void * a,const void * b,void *)255 template <typename T> int click_compare(const void *a, const void *b, void *)
256 {
257     const T *ta = static_cast<const T *>(a);
258     const T *tb = static_cast<const T *>(b);
259     return (*ta < *tb ? -1 : (*tb < *ta ? 1 : 0));
260 }
261 
262 /** @brief Sort array of elements using operator<(). */
click_qsort(T * base,size_t n)263 template <typename T> int click_qsort(T *base, size_t n)
264 {
265     return click_qsort(base, n, sizeof(T), (int (*)(const void *, const void *, void *)) &click_compare<T>);
266 }
267 
268 
269 // OTHER
270 
271 #if CLICK_LINUXMODULE
272 
273 extern "C" {
274 
275 long strtol(const char *, char **, int);
276 
277 inline unsigned long
strtoul(const char * nptr,char ** endptr,int base)278 strtoul(const char *nptr, char **endptr, int base)
279 {
280     return simple_strtoul(nptr, endptr, base);
281 }
282 
283 # if __GNUC__ == 2 && __GNUC_MINOR__ == 96
284 int click_strcmp(const char *, const char *);
285 
286 inline int
strcmp(const char * a,const char * b)287 strcmp(const char *a, const char *b)
288 {
289     return click_strcmp(a, b);
290 }
291 # endif
292 
293 }
294 
295 #elif CLICK_BSDMODULE
296 
297 /* Char-type glue */
298 
299 # define _U	0x01	/* upper */
300 # define _L	0x02	/* lower */
301 # define _D	0x04	/* digit */
302 # define _C	0x08	/* cntrl */
303 # define _P	0x10	/* punct */
304 # define _S	0x20	/* white space (space/lf/tab) */
305 # define _X	0x40	/* hex digit */
306 # define _SP	0x80	/* hard space (0x20) */
307 
308 extern unsigned char _ctype[];
309 
310 # define __ismask(x)	(_ctype[(int)(unsigned char)(x)])
311 # define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)
312 
313 # define strchr(s, c)	index(s, c)
314 
315 # if __FreeBSD_version >= 700000 && __FreeBSD_version < 730000
316 /* memmove() appeared in the FreeBSD 7.3 kernel */
317 extern "C" void *memmove(void *dest, const void *src, size_t len);
318 # endif
319 
320 
321 typedef struct ifnet net_device;
322 
323 #else /* not CLICK_LINUXMODULE || CLICK_BSDMODULE */
324 
325 // provide a definition for net_device
326 typedef struct device net_device;
327 
328 #endif /* CLICK_LINUXMODULE */
329 
330 
331 // COMPILE-TIME ASSERTION CHECKING
332 
333 #if (!defined(__cplusplus) || !HAVE_CXX_STATIC_ASSERT) && !defined(static_assert)
334 # define static_assert(x, ...) switch ((int) (x)) case 0: case !!((int) (x)):
335 #endif
336 
337 
338 // PROCESSOR IDENTITIES
339 
340 #if CLICK_LINUXMODULE
341 typedef uint32_t click_processor_t;
342 #  define CLICK_CPU_MAX NR_CPUS
343 #elif CLICK_USERLEVEL && HAVE_MULTITHREAD
344 typedef pthread_t click_processor_t;
345 #  define CLICK_CPU_MAX 256
346 #else
347 typedef int8_t click_processor_t;
348 #  if HAVE_MULTITHREAD
349 #    define CLICK_CPU_MAX 256
350 #  else
351 #    define CLICK_CPU_MAX 1
352 #  endif
353 #endif
354 
355 inline click_processor_t
click_get_processor()356 click_get_processor()
357 {
358 #if CLICK_LINUXMODULE
359 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
360     return get_cpu();
361 # else
362     return current->processor;
363 # endif
364 #elif CLICK_USERLEVEL && HAVE_MULTITHREAD
365     return pthread_self();
366 #else
367     return 0;
368 #endif
369 }
370 
371 inline void
click_put_processor()372 click_put_processor()
373 {
374 #if CLICK_LINUXMODULE
375 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
376 #  ifdef put_cpu_no_resched
377     put_cpu_no_resched();
378 #  else
379     put_cpu();
380 #  endif
381 # endif
382 #endif
383 }
384 
385 #if CLICK_USERLEVEL && HAVE_MULTITHREAD && HAVE___THREAD_STORAGE_CLASS
386 extern __thread int click_current_thread_id;
387 #endif
388 
389 #if CLICK_USERLEVEL
390 extern int click_nthreads;
391 #endif
392 
393 inline click_processor_t
click_current_processor()394 click_current_processor()
395 {
396 #if CLICK_LINUXMODULE
397 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
398     return smp_processor_id();
399 # else
400     return current->processor;
401 # endif
402 #elif CLICK_USERLEVEL && HAVE_MULTITHREAD
403     return pthread_self();
404 #else
405     return 0;
406 #endif
407 }
408 
409 inline unsigned
click_current_cpu_id()410 click_current_cpu_id()
411 {
412 #if !HAVE_MULTITHREAD
413     return 0;
414 #elif CLICK_USERLEVEL
415 #  if HAVE___THREAD_STORAGE_CLASS
416     return click_current_thread_id & 0xffff;
417 #  else
418     return sched_getcpu();
419 #  endif
420 #else
421     return click_current_processor();
422 #endif
423 }
424 
425 /**
426  * Return an upper bound to click_current_cpu_id()
427  */
428 inline unsigned
click_max_cpu_ids()429 click_max_cpu_ids()
430 {
431 #if CLICK_LINUXMODULE
432     return NR_CPUS;
433 #elif CLICK_USERLEVEL && HAVE___THREAD_STORAGE_CLASS
434     return click_nthreads;
435 #else //XXX BSDMODULE?
436     return CLICK_CPU_MAX;
437 #endif
438 }
439 
440 
441 inline click_processor_t
click_invalid_processor()442 click_invalid_processor()
443 {
444 #if CLICK_LINUXMODULE
445     return -1;
446 #elif CLICK_USERLEVEL && HAVE_MULTITHREAD
447     return 0;
448 #else
449     return -1;
450 #endif
451 }
452 
453 // TIMEVALS AND JIFFIES
454 // click_jiffies_t is the type of click_jiffies() and must be unsigned.
455 // click_jiffies_difference_t is the signed version of click_jiffies_t.
456 // CLICK_JIFFIES_MONOTONIC is true if click_jiffies() never goes backwards.
457 
458 #if CLICK_LINUXMODULE
459 # define click_gettimeofday(tvp)	(do_gettimeofday(tvp))
460 typedef unsigned long click_jiffies_t;
461 typedef long click_jiffies_difference_t;
462 # define click_jiffies()		(jiffies)
463 # define CLICK_JIFFIES_MONOTONIC	1
464 # define CLICK_HZ			HZ
465 # define click_jiffies_less(a, b)	((click_jiffies_difference_t) ((a) - (b)) < 0)
466 # define HAS_LONG_CLICK_JIFFIES_T	1
467 #elif CLICK_BSDMODULE
468 # define click_gettimeofday(tvp)	(getmicrotime(tvp))
469 typedef unsigned click_jiffies_t;
470 typedef int click_jiffies_difference_t;
471 # define click_jiffies()		(ticks)
472 # define CLICK_HZ			hz
473 # define click_jiffies_less(a, b)	((click_jiffies_difference_t) ((a) - (b)) < 0)
474 #else
475 CLICK_DECLS
476 void click_gettimeofday(timeval *tvp) CLICK_DEPRECATED;
477 typedef unsigned click_jiffies_t;
478 typedef int click_jiffies_difference_t;
479 click_jiffies_t click_jiffies();
480 # define click_jiffies_less(a, b)	((click_jiffies_difference_t) ((a) - (b)) < 0)
481 CLICK_ENDDECLS
482 # define CLICK_HZ			1000
483 #endif
484 
485 #if SIZEOF_CLICK_JIFFIES_T != (HAS_LONG_CLICK_JIFFIES_T ? SIZEOF_LONG : SIZEOF_INT)
486 # error "SIZEOF_CLICK_JIFFIES_T declared incorrectly"
487 #endif
488 
489 
490 // TIMEVAL OPERATIONS
491 
492 #ifndef timercmp
493 // Convenience macros for operations on timevals.
494 // NOTE: 'timercmp' does not work for >= or <=.
495 # define timerisset(tvp)	((tvp)->tv_sec || (tvp)->tv_usec)
496 # define timerclear(tvp)	((tvp)->tv_sec = (tvp)->tv_usec = 0)
497 # define timercmp(a, b, CMP)			\
498   (((a)->tv_sec == (b)->tv_sec) ?		\
499    ((a)->tv_usec CMP (b)->tv_usec) :		\
500    ((a)->tv_sec CMP (b)->tv_sec))
501 #endif
502 #ifndef timeradd
503 # define timeradd(a, b, result)						      \
504   do {									      \
505     (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;			      \
506     (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;			      \
507     if ((result)->tv_usec >= 1000000)					      \
508       {									      \
509 	++(result)->tv_sec;						      \
510 	(result)->tv_usec -= 1000000;					      \
511       }									      \
512   } while (0)
513 #endif
514 #ifndef timersub
515 # define timersub(a, b, result)						      \
516   do {									      \
517     (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;			      \
518     (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;			      \
519     if ((result)->tv_usec < 0) {					      \
520       --(result)->tv_sec;						      \
521       (result)->tv_usec += 1000000;					      \
522     }									      \
523   } while (0)
524 #endif
525 
526 #ifndef CLICK_TIMEVAL_OPERATORS
527 
528 inline timeval make_timeval(int sec, int usec) CLICK_DEPRECATED;
529 inline bool operator==(const timeval &a, const timeval &b) CLICK_DEPRECATED;
530 inline bool operator!=(const timeval &a, const timeval &b) CLICK_DEPRECATED;
531 inline bool operator<(const timeval &a, const timeval &b) CLICK_DEPRECATED;
532 inline bool operator<=(const timeval &a, const timeval &b) CLICK_DEPRECATED;
533 inline bool operator>(const timeval &a, const timeval &b) CLICK_DEPRECATED;
534 inline bool operator>=(const timeval &a, const timeval &b) CLICK_DEPRECATED;
535 inline timeval &operator+=(timeval &a, const timeval &b) CLICK_DEPRECATED;
536 inline timeval &operator-=(timeval &a, const timeval &b) CLICK_DEPRECATED;
537 inline timeval operator+(timeval a, const timeval &b) CLICK_DEPRECATED;
538 inline timeval operator-(timeval a, const timeval &b) CLICK_DEPRECATED;
539 
540 inline struct timeval
make_timeval(int sec,int usec)541 make_timeval(int sec, int usec)
542 {
543     struct timeval tv;
544     tv.tv_sec = sec;
545     tv.tv_usec = usec;
546     return tv;
547 }
548 
549 inline bool
operator ==(const struct timeval & a,const struct timeval & b)550 operator==(const struct timeval &a, const struct timeval &b)
551 {
552     return a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec;
553 }
554 
555 inline bool
operator !=(const struct timeval & a,const struct timeval & b)556 operator!=(const struct timeval &a, const struct timeval &b)
557 {
558     return a.tv_sec != b.tv_sec || a.tv_usec != b.tv_usec;
559 }
560 
561 inline bool
operator <(const struct timeval & a,const struct timeval & b)562 operator<(const struct timeval &a, const struct timeval &b)
563 {
564     return a.tv_sec < b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec < b.tv_usec);
565 }
566 
567 inline bool
operator <=(const struct timeval & a,const struct timeval & b)568 operator<=(const struct timeval &a, const struct timeval &b)
569 {
570     return a.tv_sec < b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec <= b.tv_usec);
571 }
572 
573 inline bool
operator >=(const struct timeval & a,const struct timeval & b)574 operator>=(const struct timeval &a, const struct timeval &b)
575 {
576     return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec >= b.tv_usec);
577 }
578 
579 inline bool
operator >(const struct timeval & a,const struct timeval & b)580 operator>(const struct timeval &a, const struct timeval &b)
581 {
582     return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec);
583 }
584 
585 inline struct timeval &
operator +=(struct timeval & a,const struct timeval & b)586 operator+=(struct timeval &a, const struct timeval &b)
587 {
588     timeradd(&a, &b, &a);
589     return a;
590 }
591 
592 inline struct timeval &
operator -=(struct timeval & a,const struct timeval & b)593 operator-=(struct timeval &a, const struct timeval &b)
594 {
595     timersub(&a, &b, &a);
596     return a;
597 }
598 
599 inline struct timeval
operator +(struct timeval a,const struct timeval & b)600 operator+(struct timeval a, const struct timeval &b)
601 {
602     timeradd(&a, &b, &a);
603     return a;
604 }
605 
606 inline struct timeval
operator -(struct timeval a,const struct timeval & b)607 operator-(struct timeval a, const struct timeval &b)
608 {
609     timersub(&a, &b, &a);
610     return a;
611 }
612 
613 #endif
614 
615 CLICK_DECLS
616 class StringAccum;
617 StringAccum &operator<<(StringAccum &, const struct timeval &);
618 CLICK_ENDDECLS
619 
620 
621 // BYTE ORDER
622 
623 #ifndef le16_to_cpu
624 # if CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
625 #  define le16_to_cpu(x) (x)
626 #  define cpu_to_le16(x) (x)
627 #  define le32_to_cpu(x) (x)
628 #  define cpu_to_le32(x) (x)
629 # elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN && defined(__APPLE__)
630 #  include <machine/byte_order.h>
631 #  define le16_to_cpu(x) NXSwapShort((x))
632 #  define cpu_to_le16(x) NXSwapShort((x))
633 #  define le32_to_cpu(x) NXSwapInt((x))
634 #  define cpu_to_le32(x) NXSwapInt((x))
635 # elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN && HAVE_BYTESWAP_H
636 #  include <byteswap.h>
637 #  define le16_to_cpu(x) bswap_16((x))
638 #  define cpu_to_le16(x) bswap_16((x))
639 #  define le32_to_cpu(x) bswap_32((x))
640 #  define cpu_to_le32(x) bswap_32((x))
641 # elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN
642 #  define le16_to_cpu(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
643 #  define cpu_to_le16(x) le16_to_cpu((x))
644 #  define le32_to_cpu(x) (le16_to_cpu((x) >> 16) | (le16_to_cpu(x) << 16))
645 #  define cpu_to_le32(x) le32_to_cpu((x))
646 # else
647 /* leave them undefined */
648 # endif
649 #endif
650 
651 
652 // CYCLE COUNTS
653 
654 CLICK_DECLS
655 
656 #if HAVE_INT64_TYPES
657 typedef uint64_t click_cycles_t;
658 #else
659 typedef uint32_t click_cycles_t;
660 #endif
661 
662 inline click_cycles_t
click_get_cycles()663 click_get_cycles()
664 {
665 #if CLICK_LINUXMODULE && HAVE_INT64_TYPES && __i386__
666     uint64_t x;
667     __asm__ __volatile__ ("rdtsc" : "=A" (x));
668     return x;
669 #elif CLICK_LINUXMODULE && HAVE_INT64_TYPES && __x86_64__
670     uint32_t xlo, xhi;
671     __asm__ __volatile__ ("rdtsc" : "=a" (xlo), "=d" (xhi));
672     return xlo | (((uint64_t) xhi) << 32);
673 #elif CLICK_LINUXMODULE && __i386__
674     uint32_t xlo, xhi;
675     __asm__ __volatile__ ("rdtsc" : "=a" (xlo), "=d" (xhi));
676     return xlo;
677 #elif CLICK_BSDMODULE
678     return rdtsc();
679 #elif CLICK_USERLEVEL && HAVE_INT64_TYPES && __i386__
680     uint64_t x;
681     __asm__ __volatile__ ("rdtsc" : "=A" (x));
682     return x;
683 #elif CLICK_USERLEVEL && HAVE_INT64_TYPES && __x86_64__
684     uint32_t xlo, xhi;
685     __asm__ __volatile__ ("rdtsc" : "=a" (xlo), "=d" (xhi));
686     return xlo | (((uint64_t) xhi) << 32);
687 #elif CLICK_USERLEVEL && __i386__
688     uint32_t xlo, xhi;
689     __asm__ __volatile__ ("rdtsc" : "=a" (xlo), "=d" (xhi));
690     return xlo;
691 #elif CLICK_MINIOS
692     /* FIXME: Implement click_get_cycles for MiniOS */
693     return 0;
694 #else
695     // add other architectures here
696     return 0;
697 #endif
698 }
699 
700 CLICK_ENDDECLS
701 
702 #endif
703