bare: add mm_alloc, mm_free
also split errno from return value in existing Linux syscall wrappers update applicable syscall wrapper checkspull/2922/head
parent
52d25336db
commit
729f9c3391
|
@ -1,7 +1,7 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
__global fd [2]int
|
__global fd [2]int
|
||||||
__global buffer [16]byte
|
__global buffer [128]byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
sample_text_file1 = ""
|
sample_text_file1 = ""
|
||||||
|
@ -36,20 +36,22 @@ fn check_read_write_pipe() {
|
||||||
|
|
||||||
a := sys_pipe(intptr(fd))
|
a := sys_pipe(intptr(fd))
|
||||||
|
|
||||||
assert a != -1
|
assert a == .enoerror
|
||||||
|
|
||||||
assert fd[0] != -1
|
assert fd[0] != -1
|
||||||
assert fd[1] != -1
|
assert fd[1] != -1
|
||||||
|
|
||||||
test_data := "test_data"
|
test_data := "test_data"
|
||||||
b := test_data.len + 1
|
b := test_data.len + 1
|
||||||
mut c := sys_write (fd[1], test_data.str, u64(b))
|
c1, e1 := sys_write (fd[1], test_data.str, u64(b))
|
||||||
|
|
||||||
assert c == b
|
assert e1 == .enoerror
|
||||||
|
assert c1 == b
|
||||||
|
|
||||||
c = sys_read(fd[0], byteptr(buffer), u64(b))
|
c2, e2 := sys_read(fd[0], byteptr(buffer), u64(b))
|
||||||
|
|
||||||
assert c == b
|
assert e2 == .enoerror
|
||||||
|
assert c2 == b
|
||||||
|
|
||||||
assert buffer[b-1] == 0
|
assert buffer[b-1] == 0
|
||||||
|
|
||||||
|
@ -57,10 +59,10 @@ fn check_read_write_pipe() {
|
||||||
assert test_data[i] == buffer[i]
|
assert test_data[i] == buffer[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
assert 0 == sys_close(fd[0])
|
assert sys_close(fd[0]) == .enoerror
|
||||||
assert 0 == sys_close(fd[1])
|
assert sys_close(fd[1]) == .enoerror
|
||||||
|
|
||||||
assert 0 != sys_close(-1)
|
assert sys_close(-1) == .ebadf
|
||||||
|
|
||||||
println ("pipe read/write passed")
|
println ("pipe read/write passed")
|
||||||
}
|
}
|
||||||
|
@ -80,12 +82,13 @@ fn check_read_file() {
|
||||||
assert fd > 0
|
assert fd > 0
|
||||||
assert ec == .enoerror
|
assert ec == .enoerror
|
||||||
n := sample_text.len
|
n := sample_text.len
|
||||||
c := sys_read(fd, buffer, u64(n*2))
|
c, e := sys_read(fd, buffer, u64(n*2))
|
||||||
|
assert e == .enoerror
|
||||||
assert c == n
|
assert c == n
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
assert sample_text[i] == buffer[i]
|
assert sample_text[i] == buffer[i]
|
||||||
}
|
}
|
||||||
assert 0 == sys_close(fd)
|
assert sys_close(fd) == .enoerror
|
||||||
|
|
||||||
println("read file passed")
|
println("read file passed")
|
||||||
}
|
}
|
||||||
|
@ -112,11 +115,100 @@ fn check_print() {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
fn check_munmap_fail() {
|
||||||
|
println ("checking 'munmap fail'")
|
||||||
|
|
||||||
|
ec := sys_munmap(-16384,8192)
|
||||||
|
assert ec == .einval
|
||||||
|
//es := i64_tos(buffer2,80,int(ec),16)
|
||||||
|
//println(es)
|
||||||
|
|
||||||
|
println ("'munmap fail' check passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_mmap_one_page() {
|
||||||
|
println ("checking check_mmap_one_page")
|
||||||
|
|
||||||
|
mp := int(mm_prot.prot_read) | int(mm_prot.prot_write)
|
||||||
|
mf := int(map_flags.map_private) | int(map_flags.map_anonymous)
|
||||||
|
mut a, e := sys_mmap(0, u64(linux_mem.page_size), mm_prot(mp), map_flags(mf), -1, 0)
|
||||||
|
|
||||||
|
assert e == .enoerror
|
||||||
|
assert a != byteptr(-1)
|
||||||
|
|
||||||
|
for i in 0..int(linux_mem.page_size) {
|
||||||
|
b := i & 0xFF
|
||||||
|
a[i] = b
|
||||||
|
assert a[i] == b
|
||||||
|
}
|
||||||
|
|
||||||
|
ec := sys_munmap(a, u64(linux_mem.page_size))
|
||||||
|
assert ec == .enoerror
|
||||||
|
|
||||||
|
println ("check_mmap_one_page passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_mm_pages() {
|
||||||
|
println ("checking check_mm_pages")
|
||||||
|
for i in 0 .. int(linux_mem.page_size)-4 {
|
||||||
|
assert u32(1) == mm_pages(u64(i))
|
||||||
|
}
|
||||||
|
for i in int(linux_mem.page_size)-3 .. (int(linux_mem.page_size)*2)-4 {
|
||||||
|
assert u32(2) == mm_pages(u64(i))
|
||||||
|
}
|
||||||
|
for i in (int(linux_mem.page_size)*2)-3 .. (int(linux_mem.page_size)*3)-4 {
|
||||||
|
assert u32(3) == mm_pages(u64(i))
|
||||||
|
}
|
||||||
|
println ("check_mm_pages passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
//pub fn mm_alloc(size u64) (voidptr, errno)
|
||||||
|
|
||||||
|
fn check_mm_alloc() {
|
||||||
|
println ("checking check_mm_alloc")
|
||||||
|
|
||||||
|
for i in 1 .. 2000 {
|
||||||
|
size := u64(i*1000)
|
||||||
|
pages := mm_pages(size)
|
||||||
|
mut a, e := mm_alloc(size)
|
||||||
|
|
||||||
|
//ads := i64_tos(buffer,80,i64(a),16)
|
||||||
|
//println(ads)
|
||||||
|
//es := i64_tos(buffer,80,i64(e),16)
|
||||||
|
//println(es)
|
||||||
|
|
||||||
|
assert e == .enoerror
|
||||||
|
ap := intptr(a-4)
|
||||||
|
assert *ap == int(pages)
|
||||||
|
assert e == .enoerror
|
||||||
|
assert !isnil(a)
|
||||||
|
|
||||||
|
if (i%111) == 0 {
|
||||||
|
for j in 0 .. int(size) {
|
||||||
|
b := j & 0xFF
|
||||||
|
a[j] = b
|
||||||
|
assert b == int(a[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mfa := mm_free(a)
|
||||||
|
|
||||||
|
//mfas := i64_tos(buffer,80,i64(mfa),16)
|
||||||
|
//println(mfas)
|
||||||
|
|
||||||
|
assert mfa == .enoerror
|
||||||
|
}
|
||||||
|
println ("mm_alloc passed")
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
check_read_write_pipe()
|
check_read_write_pipe()
|
||||||
check_read_file()
|
check_read_file()
|
||||||
// check_print()
|
// check_print()
|
||||||
check_open_file_fail()
|
check_open_file_fail()
|
||||||
|
check_munmap_fail()
|
||||||
|
check_mmap_one_page()
|
||||||
|
check_mm_pages()
|
||||||
|
check_mm_alloc()
|
||||||
sys_exit(0)
|
sys_exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
|
pub enum linux_mem {
|
||||||
|
page_size = 4096
|
||||||
|
}
|
||||||
|
|
||||||
pub enum wp_sys {
|
pub enum wp_sys {
|
||||||
wnohang = 0x00000001
|
wnohang = 0x00000001
|
||||||
wuntraced = 0x00000002
|
wuntraced = 0x00000002
|
||||||
|
@ -117,6 +121,28 @@ pub enum errno {
|
||||||
exdev = 0x00000012
|
exdev = 0x00000012
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum mm_prot {
|
||||||
|
prot_read = 0x1
|
||||||
|
prot_write = 0x2
|
||||||
|
prot_exec = 0x4
|
||||||
|
prot_none = 0x0
|
||||||
|
prot_growsdown = 0x01000000
|
||||||
|
prot_growsup = 0x02000000
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum map_flags {
|
||||||
|
map_shared = 0x01
|
||||||
|
map_private = 0x02
|
||||||
|
map_shared_validate = 0x03
|
||||||
|
map_type = 0x0f
|
||||||
|
map_fixed = 0x10
|
||||||
|
map_file = 0x00
|
||||||
|
map_anonymous = 0x20
|
||||||
|
map_anon = 0x20
|
||||||
|
map_huge_shift = 26
|
||||||
|
map_huge_mask = 0x3f
|
||||||
|
}
|
||||||
|
|
||||||
fn do_not_call_me_asm_keeper0() {
|
fn do_not_call_me_asm_keeper0() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm {
|
asm {
|
||||||
|
@ -197,61 +223,60 @@ fn sys_call4(scn, arg1, arg2, arg3, arg4 u64) u64
|
||||||
fn sys_call5(scn, arg1, arg2, arg3, arg4, arg5 u64) u64
|
fn sys_call5(scn, arg1, arg2, arg3, arg4, arg5 u64) u64
|
||||||
fn sys_call6(scn, arg1, arg2, arg3, arg4, arg5, arg6 u64) u64
|
fn sys_call6(scn, arg1, arg2, arg3, arg4, arg5, arg6 u64) u64
|
||||||
|
|
||||||
/*
|
|
||||||
these wrappers don't act exactly like the libc ones in regard to return value, so they have the raw syscall behavior.
|
|
||||||
|
|
||||||
there is no errno
|
fn split_int_errno(rc_in u64) (i64, errno) {
|
||||||
if zero is the expected value, a value > 0 is the error code
|
rc := i64(rc_in)
|
||||||
if a >=0 is a good value, then for errors, a negative error_code is returned
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 0 sys_read unsigned int fd char *buf size_t count
|
|
||||||
pub fn sys_read (fd int, buf byteptr, count u64) i64 {
|
|
||||||
return i64(sys_call3(0, u64(fd), u64(buf), count))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 sys_write unsigned int fd, const char *buf, size_t count
|
|
||||||
pub fn sys_write(fd int, buf byteptr, count u64) i64 {
|
|
||||||
return i64(sys_call3(1, u64(fd), u64(buf), count))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sys_open(filename byteptr, flags fcntl, mode int) (int, errno) {
|
|
||||||
//2 sys_open const char *filename int flags int mode
|
|
||||||
rc := int(sys_call3(2, u64(filename), u64(flags), u64(mode)))
|
|
||||||
if rc < 0 {
|
if rc < 0 {
|
||||||
return -1, errno(-rc)
|
return i64(-1), errno(-rc)
|
||||||
}
|
}
|
||||||
return rc, errno.enoerror
|
return rc, errno.enoerror
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_close(fd int) int {
|
// 0 sys_read unsigned int fd char *buf size_t count
|
||||||
|
pub fn sys_read (fd i64, buf byteptr, count u64) (i64, errno) {
|
||||||
|
return split_int_errno(sys_call3(0, u64(fd), u64(buf), count))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 sys_write unsigned int fd, const char *buf, size_t count
|
||||||
|
pub fn sys_write(fd i64, buf byteptr, count u64) (i64, errno) {
|
||||||
|
return split_int_errno(sys_call3(1, u64(fd), u64(buf), count))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_open(filename byteptr, flags fcntl, mode int) (i64, errno) {
|
||||||
|
//2 sys_open const char *filename int flags int mode
|
||||||
|
return split_int_errno(sys_call3(2, u64(filename), u64(flags), u64(mode)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_close(fd i64) errno {
|
||||||
// 3 sys_close unsigned int fd
|
// 3 sys_close unsigned int fd
|
||||||
return int(sys_call1(3, u64(fd)))
|
return errno(-i64(sys_call1(3, u64(fd))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9 sys_mmap unsigned long addr unsigned long len unsigned long prot unsigned long flags unsigned long fd unsigned long off
|
// 9 sys_mmap unsigned long addr unsigned long len unsigned long prot unsigned long flags unsigned long fd unsigned long off
|
||||||
pub fn sys_mmap(addr byteptr, len u64, prot u64, flags u64, fildes u64, off u64) voidptr {
|
pub fn sys_mmap(addr byteptr, len u64, prot mm_prot, flags map_flags, fildes u64, off u64) (byteptr, errno) {
|
||||||
return voidptr(sys_call6(9, u64(addr), len, prot, flags, fildes, off))
|
rc := sys_call6(9, u64(addr), len, u64(prot), u64(flags), fildes, off)
|
||||||
|
a, e := split_int_errno(rc)
|
||||||
|
return byteptr(a), e
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_munmap(addr voidptr, len u64) int {
|
pub fn sys_munmap(addr voidptr, len u64) errno {
|
||||||
// 11 sys_munmap unsigned long addr size_t len
|
// 11 sys_munmap unsigned long addr size_t len
|
||||||
return int(sys_call2(11, u64(addr), len))
|
return errno(-sys_call2(11, u64(addr), len))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 22 sys_pipe int *filedes
|
// 22 sys_pipe int *filedes
|
||||||
pub fn sys_pipe(filedes intptr) int {
|
pub fn sys_pipe(filedes intptr) errno {
|
||||||
return int(sys_call1(22, u64(filedes)))
|
return errno(sys_call1(22, u64(filedes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 24 sys_sched_yield
|
// 24 sys_sched_yield
|
||||||
pub fn sys_sched_yield() int {
|
pub fn sys_sched_yield() errno {
|
||||||
return int(sys_call0(24))
|
return errno(sys_call0(24))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_madvise(addr voidptr, len u64, advice int) int {
|
pub fn sys_madvise(addr voidptr, len u64, advice int) errno {
|
||||||
// 28 sys_madvise unsigned long start size_t len_in int behavior
|
// 28 sys_madvise unsigned long start size_t len_in int behavior
|
||||||
return int(sys_call3(28, u64(addr), len, u64(advice)))
|
return errno(sys_call3(28, u64(addr), len, u64(advice)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 39 sys_getpid
|
// 39 sys_getpid
|
||||||
|
@ -270,8 +295,8 @@ pub fn sys_vfork() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 33 sys_dup2 unsigned int oldfd unsigned int newfd
|
// 33 sys_dup2 unsigned int oldfd unsigned int newfd
|
||||||
pub fn sys_dup2 (oldfd, newfd int) int {
|
pub fn sys_dup2 (oldfd, newfd int) (i64, errno) {
|
||||||
return int(sys_call2(33, u64(oldfd),u64(newfd)))
|
return split_int_errno(sys_call2(33, u64(oldfd),u64(newfd)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,6 +311,10 @@ pub fn sys_exit (ec int) {
|
||||||
sys_call1(60, u64(ec))
|
sys_call1(60, u64(ec))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 247 sys_waitid int which pid_t upid struct siginfo *infop int options struct rusage *ru
|
||||||
|
//pub fn sys_waitid (idtype wi_sys, pid i64, infop voidptr, options
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A few years old, but still relevant
|
A few years old, but still relevant
|
||||||
https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
|
https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
|
||||||
|
@ -537,7 +566,7 @@ https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
|
||||||
244 sys_mq_notify mqd_t mqdes const struct sigevent *u_notification
|
244 sys_mq_notify mqd_t mqdes const struct sigevent *u_notification
|
||||||
245 sys_mq_getsetattr mqd_t mqdes const struct mq_attr *u_mqstat struct mq_attr *u_omqstat
|
245 sys_mq_getsetattr mqd_t mqdes const struct mq_attr *u_mqstat struct mq_attr *u_omqstat
|
||||||
246 sys_kexec_load unsigned long entry unsigned long nr_segments struct kexec_segment *segments unsigned long flags
|
246 sys_kexec_load unsigned long entry unsigned long nr_segments struct kexec_segment *segments unsigned long flags
|
||||||
247 sys_waitid int which pid_t upid struct siginfo *infop int options struct rusage *ru
|
>247 sys_waitid int which pid_t upid struct siginfo *infop int options struct rusage *ru
|
||||||
248 sys_add_key const char *_type const char *_description const void *_payload size_t plen
|
248 sys_add_key const char *_type const char *_description const void *_payload size_t plen
|
||||||
249 sys_request_key const char *_type const char *_description const char *_callout_info key_serial_t destringid
|
249 sys_request_key const char *_type const char *_description const char *_callout_info key_serial_t destringid
|
||||||
250 sys_keyctl int option unsigned long arg2 unsigned long arg3 unsigned long arg4 unsigned long arg5
|
250 sys_keyctl int option unsigned long arg2 unsigned long arg3 unsigned long arg4 unsigned long arg5
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
module builtin
|
||||||
|
|
||||||
|
//__global buffer [128]byte
|
||||||
|
|
||||||
|
pub fn mm_pages(size u64) u32 {
|
||||||
|
pages := (u64(size+u64(4))+u64(linux_mem.page_size))/u64(linux_mem.page_size)
|
||||||
|
return u32(pages)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mm_alloc(size u64) (byteptr, errno) {
|
||||||
|
pages := mm_pages(size)
|
||||||
|
n_bytes := u64(pages*u32(linux_mem.page_size))
|
||||||
|
|
||||||
|
mem_prot := mm_prot(int(mm_prot.prot_read) | int(mm_prot.prot_write))
|
||||||
|
mem_flags := map_flags(int(map_flags.map_private) | int(map_flags.map_anonymous))
|
||||||
|
|
||||||
|
//mps := i64_tos(buffer,80,i64(mem_prot),16)
|
||||||
|
//println(mps)
|
||||||
|
//mfs := i64_tos(buffer,80,i64(mem_flags),16)
|
||||||
|
//println(mfs)
|
||||||
|
|
||||||
|
//print("pages in: ")
|
||||||
|
//ps := i64_tos(buffer,80,i64(pages),16)
|
||||||
|
//println(ps)
|
||||||
|
|
||||||
|
|
||||||
|
a, e := sys_mmap(0, n_bytes, mem_prot, mem_flags, -1, 0)
|
||||||
|
if e == .enoerror {
|
||||||
|
mut ap := intptr(a)
|
||||||
|
*ap = pages
|
||||||
|
return byteptr(a+4), e
|
||||||
|
}
|
||||||
|
return byteptr(0), e
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mm_free(addr byteptr) errno {
|
||||||
|
ap := intptr(addr-4)
|
||||||
|
size := u64(*ap) * u64(linux_mem.page_size)
|
||||||
|
|
||||||
|
//aps := i64_tos(buffer,80,i64(addr),16)
|
||||||
|
//println(aps)
|
||||||
|
|
||||||
|
//ss := i64_tos(buffer,80,i64(size),16)
|
||||||
|
//print("size out: ")
|
||||||
|
//println(ss)
|
||||||
|
|
||||||
|
//pas := i64_tos(buffer,80,i64(ap),16)
|
||||||
|
//println(pas)
|
||||||
|
|
||||||
|
e := sys_munmap(ap, size)
|
||||||
|
|
||||||
|
//es := i64_tos(buffer,80,i64(e),16)
|
||||||
|
//println(es)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn test_syscallwrappers() {
|
||||||
|
if true {return}
|
||||||
|
vexe := os.getenv("VEXE")
|
||||||
|
vn := vexe.len - 1
|
||||||
|
if vn > 1 {
|
||||||
|
dot_checks := vexe.substr(0,vn) + "vlib/builtin/bare/.checks"
|
||||||
|
assert os.dir_exists(dot_checks)
|
||||||
|
os.chdir(dot_checks)
|
||||||
|
checks_v := "checks.v"
|
||||||
|
assert os.file_exists(checks_v)
|
||||||
|
rc := os.exec("v run $checks_v") or { panic(err) }
|
||||||
|
assert !rc.output.contains("V panic: An assertion failed.")
|
||||||
|
assert !rc.output.contains("failed")
|
||||||
|
assert rc.exit_code == 0
|
||||||
|
} else {
|
||||||
|
panic("Can't find v")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue