8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
* see also: kmheapf() "heap free"
*/
/* arch specific headers */
#ifdef KFenv_posix
# include <posix/posix.h>
#endif
/* we define all our platform functions here, whether or not
* they're for the correct platform - only the ones that are
* called by the preprocessed form of the code will actually
* be linked, linker errors are our friend here! */
extern void* kmem_platform_mmap(void* addr,
unsigned long sz, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long off);
void* kmheapa(sz len) {
/* allocate an object on the heap and return
* a pointer, or NULL if the allocation failed. */
union {
void* raw;
ubyte* byte;
kmbox* header;
} region;
................................................................................
/* because munmap needs to be informed of the size of
* the region we are going to unmap, we need to store
* that information in the region that we are mapping.
* the user will receive an adjusted pointer that can
* be adjusted to point a field of type size_t that
* contains the size of the allocated space.*/
region.byte = kmem_platform_mmap(null, region_size,
posix_prot_read | posix_prot_write,
posix_flag_anonymous | posix_map_shared, -1, 0);
/* impl note: while per manpage fd is "ignored"
* for MAP_ANONYMOUS, "some implementations" require
* a value of -1 */
if (region.raw == (void*) -1) return null;
/* worth retrieving errno? discuss */
# else
Knoimpl(kmheapa,KVos);
# error missing implementation
# endif
void* const object = (region.byte + sizeof (kmbox));
region.header -> kind = kmkind_heap;
region.header -> size = len;
return object;
}
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
<
<
<
|
>
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
* see also: kmheapf() "heap free"
*/
/* arch specific headers */
#ifdef KFenv_posix
# include <posix/posix.h>
#endif
#include <error_table.h>
/* we define all our platform functions here, whether or not
* they're for the correct platform - only the ones that are
* called by the preprocessed form of the code will actually
* be linked, linker errors are our friend here! */
extern void* kmem_platform_mmap(void* addr,
unsigned long sz, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long off);
kmcond kmheapa(void** where, sz len) {
/* allocate an object on the heap and return
* a pointer, or NULL if the allocation failed. */
union {
void* raw;
ubyte* byte;
kmbox* header;
} region;
................................................................................
/* because munmap needs to be informed of the size of
* the region we are going to unmap, we need to store
* that information in the region that we are mapping.
* the user will receive an adjusted pointer that can
* be adjusted to point a field of type size_t that
* contains the size of the allocated space.*/
k_platform_syscall_arg args[] = {
null, region_size,
posix_prot_read | posix_prot_write,
posix_flag_anonymous | posix_map_shared,
-1, 0
};
struct k_platform_syscall_answer r = k_platform_syscall
(k_platform_syscall_mmap, Kmsz(args), args);
if (r.error == 0) region.byte = (ubyte*)r.ret; else {
switch (r.error) {
case k_platform_error_EAGAIN: return kmcond_bad_lock;
case k_platform_error_EINVAL: return kmcond_bad_size;
case k_platform_error_EMFILE: return kmcond_too_many;
case k_platform_error_ENOMEM: return kmcond_no_room;
default: return kmcond_fail_assert;
}
}
/* region.byte = kmem_platform_mmap(null, region_size, */
/* posix_prot_read | posix_prot_write, */
/* posix_flag_anonymous | posix_map_shared, -1, 0); */
/* impl note: while per manpage fd is "ignored"
* for MAP_ANONYMOUS, "some implementations" require
* a value of -1 */
# else
Knoimpl(kmheapa,KVos);
# error missing implementation
# endif
void* const object = (region.byte + sizeof (kmbox));
region.header -> kind = kmkind_heap;
region.header -> size = len;
*where = object;
return kmcond_ok;
}
|