Differences From
Artifact [641176b71f]:
- File
mod/kmem/heapa.fn.c
— part of check-in
[e50a476efe]
at
2019-08-22 02:52:20
on branch trunk
— removed sneaky segfault in x86-64 syscall fn where %r8 (the register that contains the pointer to the syscall arguments from the C syscall wrapper, which need to be copied into the correct registers before the kernel is invoked) gets overwritten if the syscall valency > 5, because of overlapping ccall and syscall ABI argument registers - r8 is clobbered by argument 5 and any further attempts to use it as a ptr segfault at best. also modified the report function so that it immediate cancels compilation if a sub-process reports failure. changed allocator function signatures so they can return a condition code if the kernel reports an error; updated example code so it compiles and runs without fault.
(user:
lexi,
size: 3183)
[annotate]
[blame]
[check-ins using]
8 8 * see also: kmheapf() "heap free"
9 9 */
10 10
11 11 /* arch specific headers */
12 12 #ifdef KFenv_posix
13 13 # include <posix/posix.h>
14 14 #endif
15 +
16 +#include <error_table.h>
15 17
16 18 /* we define all our platform functions here, whether or not
17 19 * they're for the correct platform - only the ones that are
18 20 * called by the preprocessed form of the code will actually
19 21 * be linked, linker errors are our friend here! */
20 22 extern void* kmem_platform_mmap(void* addr,
21 23 unsigned long sz, unsigned long prot, unsigned long flags,
22 24 unsigned long fd, unsigned long off);
23 25
24 -void* kmheapa(sz len) {
26 +kmcond kmheapa(void** where, sz len) {
25 27 /* allocate an object on the heap and return
26 28 * a pointer, or NULL if the allocation failed. */
27 29 union {
28 30 void* raw;
29 31 ubyte* byte;
30 32 kmbox* header;
31 33 } region;
................................................................................
49 51 /* because munmap needs to be informed of the size of
50 52 * the region we are going to unmap, we need to store
51 53 * that information in the region that we are mapping.
52 54 * the user will receive an adjusted pointer that can
53 55 * be adjusted to point a field of type size_t that
54 56 * contains the size of the allocated space.*/
55 57
56 - region.byte = kmem_platform_mmap(null, region_size,
57 - posix_prot_read | posix_prot_write,
58 - posix_flag_anonymous | posix_map_shared, -1, 0);
58 + k_platform_syscall_arg args[] = {
59 + null, region_size,
60 + posix_prot_read | posix_prot_write,
61 + posix_flag_anonymous | posix_map_shared,
62 + -1, 0
63 + };
64 +
65 + struct k_platform_syscall_answer r = k_platform_syscall
66 + (k_platform_syscall_mmap, Kmsz(args), args);
67 +
68 + if (r.error == 0) region.byte = (ubyte*)r.ret; else {
69 + switch (r.error) {
70 + case k_platform_error_EAGAIN: return kmcond_bad_lock;
71 + case k_platform_error_EINVAL: return kmcond_bad_size;
72 + case k_platform_error_EMFILE: return kmcond_too_many;
73 + case k_platform_error_ENOMEM: return kmcond_no_room;
74 + default: return kmcond_fail_assert;
75 + }
76 + }
77 +
78 + /* region.byte = kmem_platform_mmap(null, region_size, */
79 + /* posix_prot_read | posix_prot_write, */
80 + /* posix_flag_anonymous | posix_map_shared, -1, 0); */
81 +
59 82 /* impl note: while per manpage fd is "ignored"
60 83 * for MAP_ANONYMOUS, "some implementations" require
61 84 * a value of -1 */
62 85
63 - if (region.raw == (void*) -1) return null;
64 - /* worth retrieving errno? discuss */
65 -
66 86 # else
67 87 Knoimpl(kmheapa,KVos);
68 88 # error missing implementation
69 89 # endif
70 90
71 91 void* const object = (region.byte + sizeof (kmbox));
72 92
73 93 region.header -> kind = kmkind_heap;
74 94 region.header -> size = len;
75 95
76 - return object;
96 + *where = object;
97 + return kmcond_ok;
77 98 }