~ubuntu-branches/ubuntu/trusty/eglibc/trusty

« back to all changes in this revision

Viewing changes to ports/sysdeps/tile/tilegx/memcpy.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-01-10 18:39:35 UTC
  • mfrom: (1.5.2) (4.4.24 experimental)
  • Revision ID: package-import@ubuntu.com-20130110183935-afsgfxkmg7wk5eaj
Tags: 2.17-0ubuntu1
* Merge with Debian, bringing in a new upstream and many small fixes:
  - patches/any/cvs-malloc-deadlock.diff: Dropped, merged upstream.
  - patches/ubuntu/lddebug-scopes.diff: Rebase for upstream changes.
  - patches/ubuntu/local-CVE-2012-3406.diff: Rebased against upstream.
  - patches/ubuntu/no-asm-mtune-i686.diff: Fixed in recent binutils.
* This upstream merge fixes a nasty hang in pulseaudio (LP: #1085342)
* Bump MIN_KERNEL_SUPPORTED to 2.6.32 on ARM, now that we no longer
  have to support shonky 2.6.31 kernels on imx51 babbage builders.
* Drop patches/ubuntu/local-disable-nscd-host-caching.diff, as these
  issues were apparently resolved upstream a while ago (LP: #613662)
* Fix the compiled-in bug URL to point to launchpad.net, not Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include <string.h>
20
20
#include <stdint.h>
21
21
#include <stdlib.h>
 
22
#include <memcopy.h>
22
23
#include <arch/chip.h>
23
24
 
24
 
/* Must be 8 bytes in size. */
25
 
#define word_t uint64_t
26
 
 
27
25
/* How many cache lines ahead should we prefetch? */
28
26
#define PREFETCH_LINES_AHEAD 3
29
27
 
34
32
  const char *__restrict src1 = (const char *) srcv;
35
33
  const char *__restrict src1_end;
36
34
  const char *__restrict prefetch;
37
 
  word_t *__restrict dst8; /* 8-byte pointer to destination memory. */
38
 
  word_t final; /* Final bytes to write to trailing word, if any */
 
35
  op_t *__restrict dst8; /* 8-byte pointer to destination memory. */
 
36
  op_t final; /* Final bytes to write to trailing word, if any */
39
37
  long i;
40
38
 
41
39
  if (n < 16)
55
53
    {
56
54
      __insn_prefetch (prefetch);
57
55
      prefetch += CHIP_L2_LINE_SIZE ();
58
 
      prefetch = (prefetch > src1_end) ? prefetch : src1;
 
56
      prefetch = (prefetch < src1_end) ? prefetch : src1;
59
57
    }
60
58
 
61
59
  /* Copy bytes until dst is word-aligned. */
62
 
  for (; (uintptr_t) dst1 & (sizeof (word_t) - 1); n--)
 
60
  for (; (uintptr_t) dst1 & (sizeof (op_t) - 1); n--)
63
61
    *dst1++ = *src1++;
64
62
 
65
63
  /* 8-byte pointer to destination memory. */
66
 
  dst8 = (word_t *) dst1;
 
64
  dst8 = (op_t *) dst1;
67
65
 
68
 
  if (__builtin_expect ((uintptr_t) src1 & (sizeof (word_t) - 1), 0))
 
66
  if (__builtin_expect ((uintptr_t) src1 & (sizeof (op_t) - 1), 0))
69
67
    {
70
 
      /* Misaligned copy.  Copy 8 bytes at a time, but don't bother
71
 
         with other fanciness.
72
 
         TODO: Consider prefetching and using wh64 as well.  */
73
 
 
74
 
      /* Create an aligned src8. */
75
 
      const word_t *__restrict src8 =
76
 
        (const word_t *) ((uintptr_t) src1 & -sizeof (word_t));
77
 
      word_t b;
78
 
 
79
 
      word_t a = *src8++;
80
 
      for (; n >= sizeof (word_t); n -= sizeof (word_t))
81
 
        {
82
 
          b = *src8++;
83
 
          a = __insn_dblalign (a, b, src1);
84
 
          *dst8++ = a;
85
 
          a = b;
86
 
        }
87
 
 
 
68
      /* Misaligned copy.  Use glibc's _wordcopy_fwd_dest_aligned, but
 
69
         inline it to avoid prologue/epilogue.  TODO: Consider
 
70
         prefetching and using wh64 as well.  */
 
71
      void * srci;
 
72
      op_t a0, a1, a2, a3;
 
73
      long int dstp = (long int) dst1;
 
74
      long int srcp = (long int) src1;
 
75
      long int len = n / OPSIZ;
 
76
 
 
77
      /* Save the initial source pointer so we know the number of
 
78
         bytes to shift for merging two unaligned results.  */
 
79
      srci = (void *) srcp;
 
80
 
 
81
      /* Make SRCP aligned by rounding it down to the beginning of the
 
82
         `op_t' it points in the middle of.  */
 
83
      srcp &= -OPSIZ;
 
84
 
 
85
      switch (len % 4)
 
86
        {
 
87
        case 2:
 
88
          a1 = ((op_t *) srcp)[0];
 
89
          a2 = ((op_t *) srcp)[1];
 
90
          len += 2;
 
91
          srcp += 2 * OPSIZ;
 
92
          goto do1;
 
93
        case 3:
 
94
          a0 = ((op_t *) srcp)[0];
 
95
          a1 = ((op_t *) srcp)[1];
 
96
          len += 1;
 
97
          srcp += 2 * OPSIZ;
 
98
          goto do2;
 
99
        case 0:
 
100
          if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 
101
            return dstv;
 
102
          a3 = ((op_t *) srcp)[0];
 
103
          a0 = ((op_t *) srcp)[1];
 
104
          len += 0;
 
105
          srcp += 2 * OPSIZ;
 
106
          goto do3;
 
107
        case 1:
 
108
          a2 = ((op_t *) srcp)[0];
 
109
          a3 = ((op_t *) srcp)[1];
 
110
          srcp += 2 * OPSIZ;
 
111
          len -= 1;
 
112
          if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 
113
            goto do0;
 
114
          goto do4;                     /* No-op.  */
 
115
        }
 
116
 
 
117
      do
 
118
        {
 
119
        do4:
 
120
          a0 = ((op_t *) srcp)[0];
 
121
          a2 = __insn_dblalign (a2, a3, srci);
 
122
          ((op_t *) dstp)[0] = a2;
 
123
          srcp += OPSIZ;
 
124
          dstp += OPSIZ;
 
125
        do3:
 
126
          a1 = ((op_t *) srcp)[0];
 
127
          a3 = __insn_dblalign (a3, a0, srci);
 
128
          ((op_t *) dstp)[0] = a3;
 
129
          srcp += OPSIZ;
 
130
          dstp += OPSIZ;
 
131
        do2:
 
132
          a2 = ((op_t *) srcp)[0];
 
133
          a0 = __insn_dblalign (a0, a1, srci);
 
134
          ((op_t *) dstp)[0] = a0;
 
135
          srcp += OPSIZ;
 
136
          dstp += OPSIZ;
 
137
        do1:
 
138
          a3 = ((op_t *) srcp)[0];
 
139
          a1 = __insn_dblalign (a1, a2, srci);
 
140
          ((op_t *) dstp)[0] = a1;
 
141
          srcp += OPSIZ;
 
142
          dstp += OPSIZ;
 
143
          len -= 4;
 
144
        }
 
145
      while (len != 0);
 
146
 
 
147
      /* This is the right position for do0.  Please don't move
 
148
         it into the loop.  */
 
149
    do0:
 
150
      ((op_t *) dstp)[0] = __insn_dblalign (a2, a3, srci);
 
151
 
 
152
      n = n % OPSIZ;
88
153
      if (n == 0)
89
 
        return dstv;
90
 
 
91
 
      b = ((const char *) src8 <= src1_end) ? *src8 : 0;
92
 
 
93
 
      /* Final source bytes to write to trailing partial word, if any. */
94
 
      final = __insn_dblalign (a, b, src1);
 
154
        return dstv;
 
155
 
 
156
      a0 = ((const char *) srcp <= src1_end) ? ((op_t *) srcp)[0] : 0;
 
157
 
 
158
      final = __insn_dblalign (a3, a0, srci);
 
159
      dst8 = (op_t *)(dstp + OPSIZ);
95
160
    }
96
161
  else
97
162
    {
98
163
      /* Aligned copy. */
99
164
 
100
 
      const word_t *__restrict src8 = (const word_t *) src1;
 
165
      const op_t *__restrict src8 = (const op_t *) src1;
101
166
 
102
167
      /* src8 and dst8 are both word-aligned. */
103
168
      if (n >= CHIP_L2_LINE_SIZE ())
104
169
        {
105
170
          /* Copy until 'dst' is cache-line-aligned. */
106
171
          for (; (uintptr_t) dst8 & (CHIP_L2_LINE_SIZE () - 1);
107
 
               n -= sizeof (word_t))
 
172
               n -= sizeof (op_t))
108
173
            *dst8++ = *src8++;
109
174
 
110
 
          /* If copying to self, return.  The test is cheap enough
111
 
             that we do it despite the fact that the memcpy() contract
112
 
             doesn't require us to support overlapping dst and src.
113
 
             This is the most common case of overlap, and any close
114
 
             overlap will cause corruption due to the wh64 below.
115
 
             This case is particularly important since the compiler
116
 
             will emit memcpy() calls for aggregate copies even if it
117
 
             can't prove that src != dst.  */
118
 
          if (__builtin_expect (dst8 == src8, 0))
119
 
            return dstv;
120
 
 
121
175
          for (; n >= CHIP_L2_LINE_SIZE ();)
122
 
            {
123
 
              __insn_wh64 (dst8);
124
 
 
125
 
              /* Prefetch and advance to next line to prefetch, but
126
 
                 don't go past the end.  */
127
 
              __insn_prefetch (prefetch);
128
 
              prefetch += CHIP_L2_LINE_SIZE ();
129
 
              prefetch = (prefetch > src1_end) ? prefetch :
130
 
                (const char *) src8;
131
 
 
132
 
              /* Copy an entire cache line.  Manually unrolled to
133
 
                 avoid idiosyncracies of compiler unrolling.  */
134
 
#define COPY_WORD(offset) ({ dst8[offset] = src8[offset]; n -= 8; })
135
 
              COPY_WORD (0);
136
 
              COPY_WORD (1);
137
 
              COPY_WORD (2);
138
 
              COPY_WORD (3);
139
 
              COPY_WORD (4);
140
 
              COPY_WORD (5);
141
 
              COPY_WORD (6);
142
 
              COPY_WORD (7);
 
176
            {
 
177
              op_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
 
178
 
 
179
              /* Prefetch and advance to next line to prefetch, but
 
180
                 don't go past the end.  */
 
181
              __insn_prefetch (prefetch);
 
182
              prefetch += CHIP_L2_LINE_SIZE ();
 
183
              prefetch = (prefetch < src1_end) ? prefetch :
 
184
                (const char *) src8;
 
185
 
 
186
              /* Do all the loads before wh64.  This is necessary if
 
187
                 [src8, src8+7] and [dst8, dst8+7] share the same
 
188
                 cache line and dst8 <= src8, as can be the case when
 
189
                 called from memmove, or with code tested on x86 whose
 
190
                 memcpy always works with forward copies.  */
 
191
              tmp0 = *src8++;
 
192
              tmp1 = *src8++;
 
193
              tmp2 = *src8++;
 
194
              tmp3 = *src8++;
 
195
              tmp4 = *src8++;
 
196
              tmp5 = *src8++;
 
197
              tmp6 = *src8++;
 
198
              tmp7 = *src8++;
 
199
 
 
200
              __insn_wh64 (dst8);
 
201
 
 
202
              *dst8++ = tmp0;
 
203
              *dst8++ = tmp1;
 
204
              *dst8++ = tmp2;
 
205
              *dst8++ = tmp3;
 
206
              *dst8++ = tmp4;
 
207
              *dst8++ = tmp5;
 
208
              *dst8++ = tmp6;
 
209
              *dst8++ = tmp7;
 
210
 
 
211
              n -= 64;
 
212
            }
143
213
#if CHIP_L2_LINE_SIZE() != 64
144
214
# error "Fix code that assumes particular L2 cache line size."
145
215
#endif
146
 
 
147
 
              dst8 += CHIP_L2_LINE_SIZE () / sizeof (word_t);
148
 
              src8 += CHIP_L2_LINE_SIZE () / sizeof (word_t);
149
 
            }
150
216
        }
151
217
 
152
 
      for (; n >= sizeof (word_t); n -= sizeof (word_t))
 
218
      for (; n >= sizeof (op_t); n -= sizeof (op_t))
153
219
        *dst8++ = *src8++;
154
220
 
155
221
      if (__builtin_expect (n == 0, 1))