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