diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-24 17:42:32 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-24 17:42:32 -0500 |
| commit | c12ae95ccc2dc80b4bd57363240cdb6eab2adcbc (patch) | |
| tree | af3312bda2b0740278767867dadcf9c6223dc377 | |
| parent | 47143b094d4700842e42b0a7cc2548d7ae292690 (diff) | |
| parent | 3edabee2ed22ee4f98f4b4bb38a41059226a8446 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
arch/tile: fix memchr() not to dereference memory for zero length
arch/tile: make glibc's sysconf(_SC_NPROCESSORS_CONF) work correctly
arch/tile: fix rwlock so would-be write lockers don't block new readers
| -rw-r--r-- | arch/tile/kernel/setup.c | 2 | ||||
| -rw-r--r-- | arch/tile/lib/memchr_32.c | 35 | ||||
| -rw-r--r-- | arch/tile/lib/spinlock_32.c | 29 |
3 files changed, 38 insertions, 28 deletions
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index fb0b3cbeae1..f18573643ed 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c | |||
| @@ -840,7 +840,7 @@ static int __init topology_init(void) | |||
| 840 | for_each_online_node(i) | 840 | for_each_online_node(i) |
| 841 | register_one_node(i); | 841 | register_one_node(i); |
| 842 | 842 | ||
| 843 | for_each_present_cpu(i) | 843 | for (i = 0; i < smp_height * smp_width; ++i) |
| 844 | register_cpu(&cpu_devices[i], i); | 844 | register_cpu(&cpu_devices[i], i); |
| 845 | 845 | ||
| 846 | return 0; | 846 | return 0; |
diff --git a/arch/tile/lib/memchr_32.c b/arch/tile/lib/memchr_32.c index 6235283b485..cc3d9badf03 100644 --- a/arch/tile/lib/memchr_32.c +++ b/arch/tile/lib/memchr_32.c | |||
| @@ -18,12 +18,24 @@ | |||
| 18 | 18 | ||
| 19 | void *memchr(const void *s, int c, size_t n) | 19 | void *memchr(const void *s, int c, size_t n) |
| 20 | { | 20 | { |
| 21 | const uint32_t *last_word_ptr; | ||
| 22 | const uint32_t *p; | ||
| 23 | const char *last_byte_ptr; | ||
| 24 | uintptr_t s_int; | ||
| 25 | uint32_t goal, before_mask, v, bits; | ||
| 26 | char *ret; | ||
| 27 | |||
| 28 | if (__builtin_expect(n == 0, 0)) { | ||
| 29 | /* Don't dereference any memory if the array is empty. */ | ||
| 30 | return NULL; | ||
| 31 | } | ||
| 32 | |||
| 21 | /* Get an aligned pointer. */ | 33 | /* Get an aligned pointer. */ |
| 22 | const uintptr_t s_int = (uintptr_t) s; | 34 | s_int = (uintptr_t) s; |
| 23 | const uint32_t *p = (const uint32_t *)(s_int & -4); | 35 | p = (const uint32_t *)(s_int & -4); |
| 24 | 36 | ||
| 25 | /* Create four copies of the byte for which we are looking. */ | 37 | /* Create four copies of the byte for which we are looking. */ |
| 26 | const uint32_t goal = 0x01010101 * (uint8_t) c; | 38 | goal = 0x01010101 * (uint8_t) c; |
| 27 | 39 | ||
| 28 | /* Read the first word, but munge it so that bytes before the array | 40 | /* Read the first word, but munge it so that bytes before the array |
| 29 | * will not match goal. | 41 | * will not match goal. |
| @@ -31,23 +43,14 @@ void *memchr(const void *s, int c, size_t n) | |||
| 31 | * Note that this shift count expression works because we know | 43 | * Note that this shift count expression works because we know |
| 32 | * shift counts are taken mod 32. | 44 | * shift counts are taken mod 32. |
| 33 | */ | 45 | */ |
| 34 | const uint32_t before_mask = (1 << (s_int << 3)) - 1; | 46 | before_mask = (1 << (s_int << 3)) - 1; |
| 35 | uint32_t v = (*p | before_mask) ^ (goal & before_mask); | 47 | v = (*p | before_mask) ^ (goal & before_mask); |
| 36 | 48 | ||
| 37 | /* Compute the address of the last byte. */ | 49 | /* Compute the address of the last byte. */ |
| 38 | const char *const last_byte_ptr = (const char *)s + n - 1; | 50 | last_byte_ptr = (const char *)s + n - 1; |
| 39 | 51 | ||
| 40 | /* Compute the address of the word containing the last byte. */ | 52 | /* Compute the address of the word containing the last byte. */ |
| 41 | const uint32_t *const last_word_ptr = | 53 | last_word_ptr = (const uint32_t *)((uintptr_t) last_byte_ptr & -4); |
| 42 | (const uint32_t *)((uintptr_t) last_byte_ptr & -4); | ||
| 43 | |||
| 44 | uint32_t bits; | ||
| 45 | char *ret; | ||
| 46 | |||
| 47 | if (__builtin_expect(n == 0, 0)) { | ||
| 48 | /* Don't dereference any memory if the array is empty. */ | ||
| 49 | return NULL; | ||
| 50 | } | ||
| 51 | 54 | ||
| 52 | while ((bits = __insn_seqb(v, goal)) == 0) { | 55 | while ((bits = __insn_seqb(v, goal)) == 0) { |
| 53 | if (__builtin_expect(p == last_word_ptr, 0)) { | 56 | if (__builtin_expect(p == last_word_ptr, 0)) { |
diff --git a/arch/tile/lib/spinlock_32.c b/arch/tile/lib/spinlock_32.c index 485e24d62c6..5cd1c4004ec 100644 --- a/arch/tile/lib/spinlock_32.c +++ b/arch/tile/lib/spinlock_32.c | |||
| @@ -167,23 +167,30 @@ void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val) | |||
| 167 | * when we compare them. | 167 | * when we compare them. |
| 168 | */ | 168 | */ |
| 169 | u32 my_ticket_; | 169 | u32 my_ticket_; |
| 170 | u32 iterations = 0; | ||
| 170 | 171 | ||
| 171 | /* Take out the next ticket; this will also stop would-be readers. */ | 172 | /* |
| 172 | if (val & 1) | 173 | * Wait until there are no readers, then bump up the next |
| 173 | val = get_rwlock(rwlock); | 174 | * field and capture the ticket value. |
| 174 | rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT); | 175 | */ |
| 176 | for (;;) { | ||
| 177 | if (!(val & 1)) { | ||
| 178 | if ((val >> RD_COUNT_SHIFT) == 0) | ||
| 179 | break; | ||
| 180 | rwlock->lock = val; | ||
| 181 | } | ||
| 182 | delay_backoff(iterations++); | ||
| 183 | val = __insn_tns((int *)&rwlock->lock); | ||
| 184 | } | ||
| 175 | 185 | ||
| 176 | /* Extract my ticket value from the original word. */ | 186 | /* Take out the next ticket and extract my ticket value. */ |
| 187 | rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT); | ||
| 177 | my_ticket_ = val >> WR_NEXT_SHIFT; | 188 | my_ticket_ = val >> WR_NEXT_SHIFT; |
| 178 | 189 | ||
| 179 | /* | 190 | /* Wait until the "current" field matches our ticket. */ |
| 180 | * Wait until the "current" field matches our ticket, and | ||
| 181 | * there are no remaining readers. | ||
| 182 | */ | ||
| 183 | for (;;) { | 191 | for (;;) { |
| 184 | u32 curr_ = val >> WR_CURR_SHIFT; | 192 | u32 curr_ = val >> WR_CURR_SHIFT; |
| 185 | u32 readers = val >> RD_COUNT_SHIFT; | 193 | u32 delta = ((my_ticket_ - curr_) & WR_MASK); |
| 186 | u32 delta = ((my_ticket_ - curr_) & WR_MASK) + !!readers; | ||
| 187 | if (likely(delta == 0)) | 194 | if (likely(delta == 0)) |
| 188 | break; | 195 | break; |
| 189 | 196 | ||
