aboutsummaryrefslogtreecommitdiff
path: root/syscall.jai
blob: e30dc2f7e67ca68be6319ec7b2cab2cec0e2255a (plain)
1
2
3
4
5
6
7
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#import "Basic";
#import "POSIX";

// This prototype is suposed to allow me to use the "open" posix syscall
// that returns a file-descriptor (fd) that can then be used by the mmap
// syscall that allows to map a file to memory.
//
// Syscall info: https://filippo.io/linux-syscall-table/

main :: () {
    
    //sys_exit(-1);
    print("> open dummy\n");
    fd, error_open := sys_open("./dummy");
    print("> opened dummy with fd % and errno %\n", fd, error_open);
    if fd < 0 return;
    
    LOOPER :: "\\|/-";
    idx := 0;
    loop: string;
    loop.count = 1;
    for 0..1 {
        sleep_milliseconds(1000);
        loop.data = *LOOPER.data[idx];
        idx = (idx + 1) % LOOPER.count;
        print("\rlooping %", loop);
    }
        
    error_close := sys_close(fd);
    print("\r> close(%) with errno %\n", fd, error_close);
    
    print("---\n");
    error :s64;
    fd, error = sys_open("./fail");
    print("$ open(fail) returned fd % and error %\n", fd, error);
    error = sys_close(456);
    print("$ close(456) returned error %\n", error);
}








sys_open :: (path: string) -> file_descriptor: s64, error: s64 {
    
    #if OS == .WINDOWS {
        print("TODO Implement this\n"); // TODO Implement this.
    }
    else #if OS == .LINUX {
        SYS_OPEN :: 2;
        data:   *s8 = xx path.data;
        result: s64 = ---;
        #if CPU == .X64 {
            print("\r# LINUX:ASM\n");
            #asm SYSCALL_SYSRET {
            mov rax:    gpr === a,  SYS_OPEN;
            mov rdi:    gpr === di, data;
            mov rsi:    gpr === si, O_RDONLY;
            mov rdx:    gpr === d,  O_RDONLY;
            //syscall rcx, r11, rax, rdi, rsi, rdx; // TODO Cleanup?
            syscall
                rcx: gpr === c,     // Implicitly used by syscall to store RIP
                r11: gpr === 11,    // Implicitly used by syscall to store RFLAGS
                rax, rdi, rsi, rdx; 
            mov result, rax;
            }
            if result < 0
                return -1, -result; // Error.
            else
                return result, 0; // OK.
        } else {
            print("\r# LINUX:LIBC\n");
            result = syscall(SYS_OPEN, data, O_RDONLY);
            if result < 0
                return -1, errno(); // Error.
            else
                return result, 0; // OK.
        }
    }
}

sys_close :: (file_descriptor: s64) -> error: s64 {
    
    #if OS == .WINDOWS {
        print("TODO Implement this\n"); // TODO Implement this.
    }
    else #if OS == .LINUX {
        SYS_CLOSE :: 3;
        result: s64 = ---;
        #if CPU == .X64 {
            print("\r# LINUX:ASM\n");
            #asm SYSCALL_SYSRET {
                mov rax:    gpr === a, SYS_CLOSE;
                mov rdi:    gpr === di, file_descriptor;
                syscall
                    rcx: gpr === c,     // Implicitly used by syscall to store RIP
                    r11: gpr === 11,    // Implicitly used by syscall to store RFLAGS
                    rax, rdi;
                mov result, rax;
            }
            return ifx result < 0 then -result else 0;
        } else {
            print("\r# LINUX:LIBC\n");
            result = syscall(SYS_CLOSE, file_descriptor);
            return ifx result < 0 then errno() else 0;
        }
    }
}

sys_exit :: (status: s32) {
#if OS == .WINDOWS {
    // @Note TerminateProcess may be better, as it can't deadlock
    ExitProcess :: (error_code: u32) #foreign kernel32;
    ExitProcess(xx errno);
}
else #if OS == .LINUX {
    SYS_EXIT_GROUP :: 231;
    #if CPU==.X64 {
        print("\rLINUX-ASM\n");
        #asm SYSCALL_SYSRET {
            mov eax: gpr === a,  SYS_EXIT_GROUP;
            mov out: gpr === di,  status;
            syscall t1:, t2:, eax, out;
        };
    } else {
        syscall(SYS_EXIT_GROUP, status);
    }
}
}