589 Commits

Author SHA1 Message Date
Logan Dimond
338323b7f9
Merge branch 'japaric:master' into bheap_into_vec 2022-05-14 15:38:23 -04:00
Jorge Aparicio
4431ae1e25 v0.7.12 v0.7.12 2022-05-12 15:27:32 +02:00
bors[bot]
02773a5b07
Merge #293
293: unconditionally depend on atomic-polyfill for riscv32i target r=japaric a=japaric

due to a limitation in the llvm backend [1] the `riscv32i-unknown-none-elf` target lacks the `core::sync::atomic` API even though the actual hardware is capable of atomic loads and stores (`fence` instruction). thus, at this point in time, this target needs `atomic-polyfill` for a working SPSC implementation

[1]: https://github.com/knurling-rs/defmt/issues/597#issuecomment-934467023

fixes #271 
closes #272 
closes #273 

Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com>
2022-05-12 13:06:27 +00:00
Jorge Aparicio
50c0930e1b update changelog 2022-05-12 15:04:06 +02:00
Jorge Aparicio
a94c1d0f59 riscv32imc needs the same treatment 2022-05-12 15:02:58 +02:00
Jorge Aparicio
34b05be696 add changelog entry 2022-05-12 14:58:29 +02:00
Jorge Aparicio
5d9e4b6268 unconditionally depend on atomic-polyfill for riscv32i target 2022-05-12 14:35:37 +02:00
Jorge Aparicio
3129e290a6 GHA: cargo check --no-default-features 2022-05-12 14:35:18 +02:00
bors[bot]
c2a022d9be
Merge #292
292: make Deque::pop_{front,back}_unchecked public r=japaric a=japaric

closes #268 

Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com>
2022-05-12 11:07:44 +00:00
Jorge Aparicio
fbc5d5bf09 make Deque::pop_{front,back}_unchecked public 2022-05-12 13:06:50 +02:00
bors[bot]
622a67673d
Merge #291
291: add first/last API to IndexMap and IndexSet r=japaric a=japaric

closes #256 

Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com>
2022-05-12 10:55:11 +00:00
Jorge Aparicio
7fd32f8a02 add first/last API to IndexMap and IndexSet 2022-05-12 12:54:15 +02:00
bors[bot]
e52d483271
Merge #290
290: optimize the codegen of Vec::clone r=japaric a=japaric

these changes optimize `Vec<u8, 1024>::clone` down to these operations

1. reserve the stack space (1028 bytes on 32-bit ARM) and leave it uninitialized
2. zero the `len` field
3. memcpy `len` bytes of data from the parent

analyzed source code

``` rust
use heapless::Vec;

fn clone(vec: &Vec<u8, 1024>) {
    let mut vec = vec.clone();
    black_box(&mut vec);
}

fn black_box<T>(val: &mut T) {
    unsafe { asm!("// {0}", in(reg) val) }
}
```

machine code with `lto = fat`, `codegen-units = 1` and `opt-level = 'z'` ('z' instead of 3 to avoid loop unrolling and keep the machine code readable)

``` armasm
00020100 <clone>:
   20100:              b5d0             push    {r4, r6, r7, lr}
   20102:              af02             add     r7, sp, #8
   20104:              f5ad 6d81        sub.w   sp, sp, #1032   ; 0x408
   20108:              2300             movs    r3, #0
   2010a:              c802             ldmia   r0!, {r1}
   2010c:              9301             str     r3, [sp, #4]
   2010e:              aa01             add     r2, sp, #4
   20110:       /--/-X b141             cbz     r1, 20124 <clone+0x24>
   20112:       |  |   4413             add     r3, r2
   20114:       |  |   f810 4b01        ldrb.w  r4, [r0], #1
   20118:       |  |   3901             subs    r1, #1
   2011a:       |  |   711c             strb    r4, [r3, #4]
   2011c:       |  |   9b01             ldr     r3, [sp, #4]
   2011e:       |  |   3301             adds    r3, #1
   20120:       |  |   9301             str     r3, [sp, #4]
   20122:       |  \-- e7f5             b.n     20110 <clone+0x10>
   20124:       \----> a801             add     r0, sp, #4
   20126:              f50d 6d81        add.w   sp, sp, #1032   ; 0x408
   2012a:              bdd0             pop     {r4, r6, r7, pc}
```

note that it's not optimizing step (3) to an actual `memcpy` because we lack the 'trait specialization' code that libstd uses

---

before `clone` was optimized to

1. reserve and zero (`memclr`) 1028 (!?) bytes of stack space
2. (unnecessarily) runtime check if `len` is equal or less than 1024 (capacity) -- this included a panicking branch
3. memcpy `len` bytes of data from the parent

Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com>
2022-05-10 11:48:03 +00:00
Jorge Aparicio
b2268e7885 optimize the codegen of Vec::clone
these changes optimize `Vec<u8, 1024>::clone` down to these operations

1. reserve the stack space (1028 bytes on 32-bit ARM) and leave it uninitialized
2. zero the `len` field
3. memcpy `len` bytes of data from the parent

analyzed source code

``` rust
use heapless::Vec;

fn clone(vec: &Vec<u8, 1024>) {
    let mut vec = vec.clone();
    black_box(&mut vec);
}

fn black_box<T>(val: &mut T) {
    unsafe { asm!("// {0}", in(reg) val) }
}
```

machine code with `lto = fat`, `codegen-units = 1` and `opt-level = 'z'` ('z' instead of 3 to avoid loop unrolling and keep the machine code readable)

``` armasm
00020100 <clone>:
   20100:              b5d0             push    {r4, r6, r7, lr}
   20102:              af02             add     r7, sp, #8
   20104:              f5ad 6d81        sub.w   sp, sp, #1032   ; 0x408
   20108:              2300             movs    r3, #0
   2010a:              c802             ldmia   r0!, {r1}
   2010c:              9301             str     r3, [sp, #4]
   2010e:              aa01             add     r2, sp, #4
   20110:       /--/-X b141             cbz     r1, 20124 <clone+0x24>
   20112:       |  |   4413             add     r3, r2
   20114:       |  |   f810 4b01        ldrb.w  r4, [r0], #1
   20118:       |  |   3901             subs    r1, #1
   2011a:       |  |   711c             strb    r4, [r3, #4]
   2011c:       |  |   9b01             ldr     r3, [sp, #4]
   2011e:       |  |   3301             adds    r3, #1
   20120:       |  |   9301             str     r3, [sp, #4]
   20122:       |  \-- e7f5             b.n     20110 <clone+0x10>
   20124:       \----> a801             add     r0, sp, #4
   20126:              f50d 6d81        add.w   sp, sp, #1032   ; 0x408
   2012a:              bdd0             pop     {r4, r6, r7, pc}
```

note that it's not optimizing step (3) to an actual `memcpy` because we lack the 'trait specialization' code that libstd uses

---

before `clone` was optimized to

1. reserve and zero (`memclr`) 1028 (!?) bytes of stack space
2. (unnecessarily) runtime check if `len` is equal or less than 1024 (capacity) -- this included a panicking branch
3. memcpy `len` bytes of data from the parent
2022-05-10 12:49:02 +02:00
bors[bot]
aacc35997b
Merge #264
264: Add support for AVR. r=japaric a=jeremysalwen

In order to support AVR, the following changes were made:

 - AVR was added to the list of architectures not supporting atomics or cas.
 - AVR was configured to not use AtomicUsize, similarly to armv6m.
 - SortedLinkedList was modified to account for the fact that usize is differently sized on
   different architectures (16 bits on AVR).

Co-authored-by: Jeremy Salwen <jeremysalwen@gmail.com>
2022-05-10 09:34:40 +00:00
bors[bot]
705f93b400
Merge #289
289: entry API for IndexMap r=japaric a=japaric

rebased version of PR #276

`@MarcusGrass` thanks for the PR!

Co-authored-by: gramar <marcus.grass@gmail.com>
Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com>
2022-05-09 15:00:27 +00:00
Jorge Aparicio
0484efb5bf update changelog 2022-05-09 16:58:51 +02:00
Jorge Aparicio
1735e6e58c rustfmt 2022-05-09 16:58:01 +02:00
gramar
b6f4bc03d2 Add changelog entry for Indexmap entry api 2022-05-09 16:57:47 +02:00
gramar
9b03b5940d Drive-by fix insert on full map 2022-05-09 16:57:03 +02:00
gramar
b6b3438f21 Add entry API 2022-05-09 16:55:35 +02:00
gramar
d2c85a18e0 Add entry API 2022-05-09 16:55:32 +02:00
Jorge Aparicio
fa1e92dacd rustfmt 2022-05-09 16:53:10 +02:00
Jorge Aparicio
b36367a28e
Merge pull request #275 from MarcusGrass/indexmap_into_iter
Add intoiter for Indexmap
2022-05-09 14:52:55 +00:00
bors[bot]
4ad6060f31
Merge #274
274: Implement FromIterator for String r=japaric a=VersBinarii

Implements FromIterator trait on String.

It also addresses issue: https://github.com/japaric/heapless/issues/245

Co-authored-by: VersBinarii <versbinarii@gmail.com>
2022-05-09 13:54:37 +00:00
Jorge Aparicio
0cb35c7170 v0.7.11 v0.7.11 2022-05-09 15:25:16 +02:00
Jorge Aparicio
56d2a37f76
Merge pull request #288 from japaric/safe-droppable
remove unsafe from Droppable test helper
2022-05-09 13:23:30 +00:00
Jorge Aparicio
433e4a3cdb remove unsafe from Droppable test helper 2022-05-09 15:14:34 +02:00
Jorge Aparicio
44fb37d168
Merge pull request #287 from japaric/binary-heap-double-drop
fix: BinaryHeap elements are dropped twice
2022-05-09 13:13:38 +00:00
Jorge Aparicio
5c39f5c7ee fix: BinaryHeap elements are dropped twice 2022-05-09 15:07:03 +02:00
bors[bot]
6877eedfd4
Merge #280
280: Fix undefined behavior identified by Miri r=japaric a=jgallagher

Hi! We ran into an exception triggered by new undefined behavior checks inserted into the nightly compiler (https://github.com/rust-lang/rust/pull/92686/files#diff-54110dcedc5a4d976321aa5d2a6767ac0744a3ef1363b75ffc62faf81cf14c30R230-L229). Running `heapless`'s test suite under Miri didn't flag anything at first, but it did once we added `MIRIFLAGS="-Zmiri-tag-raw-pointers"`. All three of the fixes in this PR were identified via

```
MIRIFLAGS="-Zmiri-tag-raw-pointers -Zmiri-ignore-leaks" cargo +nightly miri test -- --skip pool::
```

and the fixes came from copying the implementations from the equivalent methods in `std`. Note that I skipped the `pool::` tests; there is at least one miri failure in them, but it wasn't immediately obvious how to fix it so I skipped it for now. It's probably worth adding the flag above to the CI miri run, but I didn't do that either (since it would immediately cause failures given I didn't fix the problem in `pool`).

The specific output for `pool` is

```
test pool::singleton::tests::sanity ... error: Undefined Behavior: trying to reborrow <untagged> for SharedReadWrite permission at alloc36[0x1], but that tag does not exist in the borrow stack for this location
   --> /home/john/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/non_null.rs:380:18
    |
380 |         unsafe { &*self.as_ptr() }
    |                  ^^^^^^^^^^^^^^^
    |                  |
    |                  trying to reborrow <untagged> for SharedReadWrite permission at alloc36[0x1], but that tag does not exist in the borrow stack for this location
    |                  this error occurs as part of a reborrow at alloc36[0x1..0x9]
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information

    = note: inside `std::ptr::NonNull::<pool::stack::Node<u8>>::as_ref` at /home/john/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/non_null.rs:380:18
note: inside `pool::stack::Stack::<u8>::push` at src/pool/cas.rs:43:17
   --> src/pool/cas.rs:43:17
    |
43  | /                 new_head
44  | |                     .as_raw()
45  | |                     .as_ref()
    | |_____________________________^
note: inside `pool::Pool::<u8>::grow` at src/pool/mod.rs:390:25
   --> src/pool/mod.rs:390:25
    |
390 |                         self.stack.push(p);
    |                         ^^^^^^^^^^^^^^^^^^
note: inside `<pool::singleton::tests::sanity::A as pool::singleton::Pool>::grow` at src/pool/singleton.rs:78:9
   --> src/pool/singleton.rs:78:9
    |
78  |         Self::ptr().grow(memory)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `pool::singleton::tests::sanity` at src/pool/singleton.rs:362:9
   --> src/pool/singleton.rs:362:9
    |
362 |         A::grow(unsafe { &mut MEMORY });
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside closure at src/pool/singleton.rs:353:5
   --> src/pool/singleton.rs:353:5
    |
352 |       #[test]
    |       ------- in this procedural macro expansion
353 | /     fn sanity() {
354 | |         const SZ: usize = 2 * mem::size_of::<Node<u8>>() - 1;
355 | |         static mut MEMORY: [u8; SZ] = [0; SZ];
356 | |
...   |
373 | |         assert_eq!(*A::alloc().unwrap().init(1), 1);
374 | |     }
    | |_____^
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
```

Co-authored-by: John Gallagher <john@oxidecomputer.com>
2022-05-02 08:55:31 +00:00
Emil Fresk
1c56672469
Merge pull request #283 from japaric/rm-scoped_threadpool
use std:🧵:scope instead of scoped_threadpool
2022-05-01 09:39:06 +02:00
John Gallagher
8fd2907115 Add note to CHANGELOG 2022-04-29 12:42:52 -04:00
Jorge Aparicio
57ac20eeb7 ubuntu-specific(?) suppressions 2022-04-29 16:16:24 +02:00
Jorge Aparicio
1e1d801b07 fix typo 2022-04-29 15:29:15 +02:00
Jorge Aparicio
3d3277f6d3 only build tests that require thread::scope on nightly 2022-04-29 15:21:58 +02:00
Jorge Aparicio
477c53b25d use std:🧵:scope instead of scoped_threadpool
as it's easier to deal with TSAN false positives in the former API

as surfaced in PR 280 the current supression rules don't handle newer versions of the
scoped_threadpool crate

trying to update the supression rules related to scoped_threadpool in PR #282 revealed that the
supression rules are masking (hiding) real data races:
https://github.com/japaric/heapless/pull/282#issuecomment-1113173358

std:🧵:scope requires less supression rules and does not mask real data races -- for instance,
the data race in the linked issue comment is not masked when using std:🧵:scope

tradeoffs:
- pro: one less dev dependency
- pro: supressions file is simpler
- cons: std:🧵:scope is only available on recent nightlies
2022-04-29 15:20:55 +02:00
John Gallagher
713abb8bd6 Fix undefined behavior in Vec::swap_remove_unchecked() 2022-04-28 17:42:30 -04:00
John Gallagher
f7eb54477c Fix undefined behavior in Vec::truncate() 2022-04-28 17:29:20 -04:00
John Gallagher
d304960424 Fix undefined behavior in Hole::move_to() 2022-04-28 17:26:02 -04:00
Jeremy Salwen
8aa68d77d7 Add support for AVR.
In order to support AVR, the following changes were made:

 - AVR was added to the list of architectures supported by atomic-polyfill.
 - SortedLinkedList was modified to account for the fact that usize is
   differently sized on different architectures (16 bits on AVR).
2022-03-31 19:25:39 -04:00
gramar
8b3c7f238a Add intoiter for Indexmap 2022-03-23 13:38:15 +01:00
VersBinarii
c7bc3c8166 Implement FromIterator for String 2022-03-15 15:36:10 +01:00
Emil Fresk
9fb9cd7045
Merge pull request #269 from quartiq/fix-pool-example
pool: fix example
2022-02-14 16:43:38 +01:00
Robert Jördens
668033f991 add changelog entry 2022-02-14 14:19:15 +01:00
Robert Jördens
6ffbcb84f1 pool: fix example
* Pool trait and exception use missing
2022-02-11 10:28:40 +01:00
Emil Fresk
3b2bc421a0 Remove deploy CI, docs.rs works well 2022-01-21 12:04:30 +01:00
Emil Fresk
98b7dd41f8 Release 0.7.10 v0.7.10 2022-01-21 12:03:14 +01:00
Emil Fresk
4a204da35d
Merge pull request #267 from TDHolmes/allow-non-x86-hosts
assume native compilation if target_os is not "none" to allow non-x86 hosts to run tests
2022-01-21 11:46:23 +01:00
Tyler Holmes
5cf74504da
Merge branch 'master' into allow-non-x86-hosts 2022-01-20 09:59:22 -08:00