1    	// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2    	// vim: ts=8 sw=2 smarttab
3    	/*
4    	 * Ceph - scalable distributed file system
5    	 *
6    	 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7    	 *
8    	 * This is free software; you can redistribute it and/or
9    	 * modify it under the terms of the GNU Lesser General Public
10   	 * License version 2.1, as published by the Free Software 
11   	 * Foundation.  See file COPYING.
12   	 * 
13   	 */
14   	#ifndef CEPH_INLINE_MEMORY_H
15   	#define CEPH_INLINE_MEMORY_H
16   	
17   	#if defined(__GNUC__)
18   	
19   	// optimize for the common case, which is very small copies
20   	static inline void *maybe_inline_memcpy(void *dest, const void *src, size_t l,
21   					       size_t inline_len)
22   	  __attribute__((always_inline));
23   	
24   	void *maybe_inline_memcpy(void *dest, const void *src, size_t l,
25   				 size_t inline_len)
26   	{
(1) Event cond_false: Condition "l > inline_len", taking false branch.
27   	  if (l > inline_len) {
28   	    return memcpy(dest, src, l);
(2) Event if_end: End of if statement.
29   	  }
(3) Event switch: Switch case value "8UL".
30   	  switch (l) {
(4) Event switch_case: Reached case "8UL".
31   	  case 8:
(5) Event access_dbuff_const: Calling "__builtin_memcpy" indexes array "src" with index "8UL" at byte position 7.
32   	    return __builtin_memcpy(dest, src, 8);
33   	  case 4:
34   	    return __builtin_memcpy(dest, src, 4);
35   	  case 3:
36   	    return __builtin_memcpy(dest, src, 3);
37   	  case 2:
38   	    return __builtin_memcpy(dest, src, 2);
39   	  case 1:
40   	    return __builtin_memcpy(dest, src, 1);
41   	  default:
42   	    int cursor = 0;
43   	    while (l >= sizeof(uint64_t)) {
44   	      __builtin_memcpy((char*)dest + cursor, (char*)src + cursor,
45   			       sizeof(uint64_t));
46   	      cursor += sizeof(uint64_t);
47   	      l -= sizeof(uint64_t);
48   	    }
49   	    while (l >= sizeof(uint32_t)) {
50   	      __builtin_memcpy((char*)dest + cursor, (char*)src + cursor,
51   			       sizeof(uint32_t));
52   	      cursor += sizeof(uint32_t);
53   	      l -= sizeof(uint32_t);
54   	    }
55   	    while (l > 0) {
56   	      *((char*)dest + cursor) = *((char*)src + cursor);
57   	      cursor++;
58   	      l--;
59   	    }
60   	  }
61   	  return dest;
62   	}
63   	
64   	#else
65   	
66   	#define maybe_inline_memcpy(d, s, l, x) memcpy(d, s, l)
67   	
68   	#endif
69   	
70   	
71   	#if defined(__GNUC__) && defined(__x86_64__)
72   	
73   	namespace ceph {
74   	typedef unsigned uint128_t __attribute__ ((mode (TI)));
75   	}
76   	using ceph::uint128_t;
77   	
78   	static inline bool mem_is_zero(const char *data, size_t len)
79   	  __attribute__((always_inline));
80   	
81   	bool mem_is_zero(const char *data, size_t len)
82   	{
83   	  // we do have XMM registers in x86-64, so if we need to check at least
84   	  // 16 bytes, make use of them
85   	  if (len / sizeof(uint128_t) > 0) {
86   	    // align data pointer to 16 bytes, otherwise it'll segfault due to bug
87   	    // in (at least some) GCC versions (using MOVAPS instead of MOVUPS).
88   	    // check up to 15 first bytes while at it.
89   	    while (((unsigned long long)data) & 15) {
90   	      if (*(uint8_t*)data != 0) {
91   		return false;
92   	      }
93   	      data += sizeof(uint8_t);
94   	      --len;
95   	    }
96   	
97   	    const char* data_start = data;
98   	    const char* max128 = data + (len / sizeof(uint128_t))*sizeof(uint128_t);
99   	
100  	    while (data < max128) {
101  	      if (*(uint128_t*)data != 0) {
102  		return false;
103  	      }
104  	      data += sizeof(uint128_t);
105  	    }
106  	    len -= (data - data_start);
107  	  }
108  	
109  	  const char* max = data + len;
110  	  const char* max32 = data + (len / sizeof(uint32_t))*sizeof(uint32_t);
111  	  while (data < max32) {
112  	    if (*(uint32_t*)data != 0) {
113  	      return false;
114  	    }
115  	    data += sizeof(uint32_t);
116  	  }
117  	  while (data < max) {
118  	    if (*(uint8_t*)data != 0) {
119  	      return false;
120  	    }
121  	    data += sizeof(uint8_t);
122  	  }
123  	  return true;
124  	}
125  	
126  	#else  // gcc and x86_64
127  	
128  	static inline bool mem_is_zero(const char *data, size_t len) {
129  	  const char *end = data + len;
130  	  const char* end64 = data + (len / sizeof(uint64_t))*sizeof(uint64_t);
131  	
132  	  while (data < end64) {
133  	    if (*(uint64_t*)data != 0) {
134  	      return false;
135  	    }
136  	    data += sizeof(uint64_t);
137  	  }
138  	
139  	  while (data < end) {
140  	    if (*data != 0) {
141  	      return false;
142  	    }
143  	    ++data;
144  	  }
145  	  return true;
146  	}
147  	
148  	#endif  // !x86_64
149  	
150  	#endif
151