aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-02-22 21:50:51 +0000
committergingerBill <bill@gingerbill.org>2023-02-22 21:50:51 +0000
commit3d325e52c603b4ff8b3abcc8a892a364fa940b9d (patch)
tree7237665a5ca745731a361c79358d704414f0b623
parent6a6d7701f9892a3468c74f0c7d1e70e04f529824 (diff)
parent50c688f0f7fdbf9dfcc4f89da5045efd0c91f658 (diff)
Merge branch 'master' of https://github.com/odin-lang/Odin
-rw-r--r--core/intrinsics/intrinsics.odin4
-rw-r--r--core/sys/darwin/xnu_system_call_numbers.odin2
-rw-r--r--core/sys/darwin/xnu_system_call_wrappers.odin96
-rw-r--r--core/sys/unix/syscalls_linux.odin153
-rw-r--r--core/time/perf.odin51
-rw-r--r--core/time/tsc_darwin.odin21
-rw-r--r--core/time/tsc_freebsd.odin21
-rw-r--r--core/time/tsc_linux.odin35
-rw-r--r--core/time/tsc_openbsd.odin7
-rw-r--r--core/time/tsc_windows.odin7
-rw-r--r--src/check_stmt.cpp1
11 files changed, 344 insertions, 54 deletions
diff --git a/core/intrinsics/intrinsics.odin b/core/intrinsics/intrinsics.odin
index 38542d2fc..890a6881d 100644
--- a/core/intrinsics/intrinsics.odin
+++ b/core/intrinsics/intrinsics.odin
@@ -283,7 +283,7 @@ wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
// x86 Targets (i386, amd64)
-x86_cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) ---
+x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) ---
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
@@ -305,4 +305,4 @@ valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2,
// Internal compiler use only
-__entry_point :: proc() --- \ No newline at end of file
+__entry_point :: proc() ---
diff --git a/core/sys/darwin/xnu_system_call_numbers.odin b/core/sys/darwin/xnu_system_call_numbers.odin
index b90373fdc..429d18964 100644
--- a/core/sys/darwin/xnu_system_call_numbers.odin
+++ b/core/sys/darwin/xnu_system_call_numbers.odin
@@ -1,6 +1,6 @@
package darwin
-unix_offset_syscall :: proc(number: System_Call_Number) -> uintptr {
+unix_offset_syscall :: proc "contextless" (number: System_Call_Number) -> uintptr {
return uintptr(number) + uintptr(0x2000000)
}
diff --git a/core/sys/darwin/xnu_system_call_wrappers.odin b/core/sys/darwin/xnu_system_call_wrappers.odin
index 685f75ffa..c7a6d6bc4 100644
--- a/core/sys/darwin/xnu_system_call_wrappers.odin
+++ b/core/sys/darwin/xnu_system_call_wrappers.odin
@@ -229,191 +229,191 @@ _Proc_Bsdinfo :: struct {
/*--==========================================================================--*/
-syscall_fsync :: #force_inline proc(fildes: c.int) -> bool {
+syscall_fsync :: #force_inline proc "contextless" (fildes: c.int) -> bool {
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.fsync), uintptr(fildes)))
}
-syscall_write :: #force_inline proc (fildes: c.int, buf: ^byte, nbyte: u64) -> bool {
+syscall_write :: #force_inline proc "contextless" (fildes: c.int, buf: ^byte, nbyte: u64) -> bool {
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.write), uintptr(fildes), uintptr(buf), uintptr(nbyte)))
}
-syscall_read :: #force_inline proc(fildes: c.int, buf: ^byte, nbyte: u64) -> i64 {
+syscall_read :: #force_inline proc "contextless" (fildes: c.int, buf: ^byte, nbyte: u64) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.read), uintptr(fildes), uintptr(buf), uintptr(nbyte))
}
-syscall_open :: #force_inline proc(path: cstring, oflag: u32, mode: u32) -> c.int {
+syscall_open :: #force_inline proc "contextless" (path: cstring, oflag: u32, mode: u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.open), transmute(uintptr)path, uintptr(oflag), uintptr(mode))
}
-syscall_close :: #force_inline proc(fd: c.int) -> bool {
+syscall_close :: #force_inline proc "contextless" (fd: c.int) -> bool {
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.close), uintptr(fd)))
}
-syscall_fchmod :: #force_inline proc(fildes: c.int, mode: u32) -> c.int {
+syscall_fchmod :: #force_inline proc "contextless" (fildes: c.int, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.fchmod), uintptr(fildes), uintptr(mode)))
}
-syscall_chmod :: #force_inline proc(path: cstring, mode: u32) -> c.int {
+syscall_chmod :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.chmod), transmute(uintptr)path, uintptr(mode)))
}
-syscall_mkdir :: #force_inline proc(path: cstring, mode: u32) -> c.int {
+syscall_mkdir :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.mkdir), transmute(uintptr)path, uintptr(mode)))
}
-syscall_mkdir_at :: #force_inline proc(fd: c.int, path: cstring, mode: u32) -> c.int {
+syscall_mkdir_at :: #force_inline proc "contextless" (fd: c.int, path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.mkdir), uintptr(fd), transmute(uintptr)path, uintptr(mode)))
}
-syscall_rmdir :: #force_inline proc(path: cstring, mode: u32) -> c.int {
+syscall_rmdir :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.rmdir), transmute(uintptr)path, uintptr(mode)))
}
-syscall_rename :: #force_inline proc(path_old: cstring, path_new: cstring) -> c.int {
+syscall_rename :: #force_inline proc "contextless" (path_old: cstring, path_new: cstring) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.rename), transmute(uintptr)path_old, transmute(uintptr)path_new))
}
-syscall_rename_at :: #force_inline proc(from_fd: c.int, from: cstring, to_fd: c.int, to: cstring) -> c.int {
+syscall_rename_at :: #force_inline proc "contextless" (from_fd: c.int, from: cstring, to_fd: c.int, to: cstring) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.renameat), uintptr(from_fd), transmute(uintptr)from, uintptr(to_fd), transmute(uintptr)to))
}
-syscall_lseek :: #force_inline proc(fd: c.int, offset: i64, whence: c.int) -> i64 {
+syscall_lseek :: #force_inline proc "contextless" (fd: c.int, offset: i64, whence: c.int) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.lseek), uintptr(fd), uintptr(offset), uintptr(whence))
}
-syscall_gettid :: #force_inline proc() -> u64 {
+syscall_gettid :: #force_inline proc "contextless" () -> u64 {
return cast(u64)intrinsics.syscall(unix_offset_syscall(.gettid))
}
-syscall_fstat :: #force_inline proc(fd: c.int, status: ^stat) -> c.int {
+syscall_fstat :: #force_inline proc "contextless" (fd: c.int, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fstat), uintptr(fd), uintptr(status))
}
-syscall_lstat :: #force_inline proc(path: cstring, status: ^stat) -> c.int {
+syscall_lstat :: #force_inline proc "contextless" (path: cstring, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.lstat), transmute(uintptr)path, uintptr(status))
}
-syscall_stat :: #force_inline proc(path: cstring, status: ^stat) -> c.int {
+syscall_stat :: #force_inline proc "contextless" (path: cstring, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.stat), transmute(uintptr)path, uintptr(status))
}
-syscall_fstatat :: #force_inline proc(fd: c.int, path: cstring, status: ^stat) -> c.int {
+syscall_fstatat :: #force_inline proc "contextless" (fd: c.int, path: cstring, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fstatat), uintptr(fd), transmute(uintptr)path, uintptr(status))
}
-syscall_link :: #force_inline proc(path: cstring, to_link: cstring) -> c.int {
+syscall_link :: #force_inline proc "contextless" (path: cstring, to_link: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.link), transmute(uintptr)path, transmute(uintptr)to_link)
}
-syscall_linkat :: #force_inline proc(fd: c.int, path: cstring, fd2: c.int, to_link: cstring) -> c.int {
+syscall_linkat :: #force_inline proc "contextless" (fd: c.int, path: cstring, fd2: c.int, to_link: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.linkat), uintptr(fd), transmute(uintptr)path, uintptr(fd2), transmute(uintptr)to_link)
}
-syscall_readlink :: #force_inline proc(path: cstring, buf: ^u8, buf_size: u64) -> i64 {
+syscall_readlink :: #force_inline proc "contextless" (path: cstring, buf: ^u8, buf_size: u64) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.readlink), transmute(uintptr)path, uintptr(buf), uintptr(buf_size))
}
-syscall_readlinkat :: #force_inline proc(fd: c.int, path: cstring, buf: ^u8, buf_size: u64) -> i64 {
+syscall_readlinkat :: #force_inline proc "contextless" (fd: c.int, path: cstring, buf: ^u8, buf_size: u64) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.readlinkat), uintptr(fd), transmute(uintptr)path, uintptr(buf), uintptr(buf_size))
}
-syscall_access :: #force_inline proc(path: cstring, mode: c.int) -> c.int {
+syscall_access :: #force_inline proc "contextless" (path: cstring, mode: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.access), transmute(uintptr)path, uintptr(mode))
}
-syscall_faccessat :: #force_inline proc(fd: c.int, path: cstring, mode: c.int, flag: c.int) -> c.int {
+syscall_faccessat :: #force_inline proc "contextless" (fd: c.int, path: cstring, mode: c.int, flag: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.faccessat), uintptr(fd), transmute(uintptr)path, uintptr(mode), uintptr(flag))
}
-syscall_getdirentries :: #force_inline proc(fd: c.int, buf: ^u8, nbytes: c.int, base_pointer: ^u32) -> c.int {
+syscall_getdirentries :: #force_inline proc "contextless" (fd: c.int, buf: ^u8, nbytes: c.int, base_pointer: ^u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getdirentries), uintptr(fd), uintptr(buf), uintptr(nbytes), uintptr(base_pointer))
}
-syscall_truncate :: #force_inline proc (path: cstring, length: off_t) -> c.int {
+syscall_truncate :: #force_inline proc "contextless" (path: cstring, length: off_t) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.truncate), transmute(uintptr)path, uintptr(length))
}
-syscall_ftruncate :: #force_inline proc (fd: c.int, length: off_t) -> c.int {
+syscall_ftruncate :: #force_inline proc "contextless" (fd: c.int, length: off_t) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.ftruncate), uintptr(fd), uintptr(length))
}
-syscall_sysctl :: #force_inline proc (name: ^c.int, namelen: c.uint, oldp: rawptr, oldlenp: ^i64, newp: ^i8, newlen: i64) -> c.int {
+syscall_sysctl :: #force_inline proc "contextless" (name: ^c.int, namelen: c.uint, oldp: rawptr, oldlenp: ^i64, newp: ^i8, newlen: i64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.sysctl), uintptr(name), uintptr(namelen), uintptr(oldp), uintptr(oldlenp), uintptr(newp), uintptr(newlen))
}
-syscall_copyfile :: #force_inline proc(from: cstring, to: cstring, state: rawptr, flags: u32) -> c.int {
+syscall_copyfile :: #force_inline proc "contextless" (from: cstring, to: cstring, state: rawptr, flags: u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.copyfile), transmute(uintptr)from, transmute(uintptr)to, uintptr(state), uintptr(flags))
}
// think about this? last arg should be more than one
-syscall_fcntl :: #force_inline proc(fd: c.int, cmd: c.int, other: rawptr) -> c.int {
+syscall_fcntl :: #force_inline proc "contextless" (fd: c.int, cmd: c.int, other: rawptr) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fsctl), uintptr(fd), uintptr(cmd), uintptr(other))
}
-syscall_exit :: #force_inline proc(code: c.int) {
+syscall_exit :: #force_inline proc "contextless" (code: c.int) {
intrinsics.syscall(unix_offset_syscall(.exit), uintptr(code))
}
-syscall_kill :: #force_inline proc(pid: pid_t, sig: c.int) -> c.int {
+syscall_kill :: #force_inline proc "contextless" (pid: pid_t, sig: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.kill), uintptr(pid), uintptr(sig))
}
-syscall_dup :: #force_inline proc(fd: c.int) -> c.int {
+syscall_dup :: #force_inline proc "contextless" (fd: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.dup), uintptr(fd))
}
-syscall_execve :: #force_inline proc(path: cstring, argv: [^]cstring, env: [^]cstring) -> c.int {
+syscall_execve :: #force_inline proc "contextless" (path: cstring, argv: [^]cstring, env: [^]cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.execve), transmute(uintptr)path, transmute(uintptr)argv, transmute(uintptr)env)
}
-syscall_munmap :: #force_inline proc(addr: rawptr, len: u64) -> c.int {
+syscall_munmap :: #force_inline proc "contextless" (addr: rawptr, len: u64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len))
}
-syscall_mmap :: #force_inline proc(addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 {
+syscall_mmap :: #force_inline proc "contextless" (addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 {
return cast(^u8)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len), uintptr(port), uintptr(flags), uintptr(fd), uintptr(offset))
}
-syscall_flock :: #force_inline proc(fd: c.int, operation: c.int) -> c.int {
+syscall_flock :: #force_inline proc "contextless" (fd: c.int, operation: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.flock), uintptr(fd), uintptr(operation))
}
-syscall_utimes :: #force_inline proc(path: cstring, times: ^timeval) -> c.int {
+syscall_utimes :: #force_inline proc "contextless" (path: cstring, times: ^timeval) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.utimes), transmute(uintptr)path, uintptr(times))
}
-syscall_futimes :: #force_inline proc(fd: c.int, times: ^timeval) -> c.int {
+syscall_futimes :: #force_inline proc "contextless" (fd: c.int, times: ^timeval) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.futimes), uintptr(fd), uintptr(times))
}
-syscall_adjtime :: #force_inline proc(delta: ^timeval, old_delta: ^timeval) -> c.int {
+syscall_adjtime :: #force_inline proc "contextless" (delta: ^timeval, old_delta: ^timeval) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.adjtime), uintptr(delta), uintptr(old_delta))
}
-syscall_sysctlbyname :: #force_inline proc(name: cstring, oldp: rawptr, oldlenp: ^i64, newp: rawptr, newlen: i64) -> c.int {
+syscall_sysctlbyname :: #force_inline proc "contextless" (name: cstring, oldp: rawptr, oldlenp: ^i64, newp: rawptr, newlen: i64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.sysctlbyname), transmute(uintptr)name, uintptr(oldp), uintptr(oldlenp), uintptr(newp), uintptr(newlen))
}
-syscall_proc_info :: #force_inline proc(num: c.int, pid: u32, flavor: c.int, arg: u64, buffer: rawptr, buffer_size: c.int) -> c.int {
+syscall_proc_info :: #force_inline proc "contextless" (num: c.int, pid: u32, flavor: c.int, arg: u64, buffer: rawptr, buffer_size: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.proc_info), uintptr(num), uintptr(pid), uintptr(flavor), uintptr(arg), uintptr(buffer), uintptr(buffer_size))
}
-syscall_openat :: #force_inline proc(fd: int, path: cstring, oflag: u32, mode: u32) -> c.int {
+syscall_openat :: #force_inline proc "contextless" (fd: int, path: cstring, oflag: u32, mode: u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.openat), uintptr(fd), transmute(uintptr)path, uintptr(oflag), uintptr(mode))
}
-syscall_getentropy :: #force_inline proc(buf: [^]u8, buflen: u64) -> c.int {
+syscall_getentropy :: #force_inline proc "contextless" (buf: [^]u8, buflen: u64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(buf), uintptr(buflen))
}
-syscall_pipe :: #force_inline proc(fds: [^]c.int) -> c.int {
+syscall_pipe :: #force_inline proc "contextless" (fds: [^]c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(&fds[0]), uintptr(&fds[1]))
}
-syscall_chdir :: #force_inline proc(path: cstring) -> c.int {
+syscall_chdir :: #force_inline proc "contextless" (path: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), transmute(uintptr)path)
}
-syscall_fchdir :: #force_inline proc(fd: c.int, path: cstring) -> c.int {
+syscall_fchdir :: #force_inline proc "contextless" (fd: c.int, path: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(fd), transmute(uintptr)path)
-} \ No newline at end of file
+}
diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin
index 8ce3ca3cb..1e89da2d6 100644
--- a/core/sys/unix/syscalls_linux.odin
+++ b/core/sys/unix/syscalls_linux.odin
@@ -1563,6 +1563,155 @@ MADV_WIPEONFORK :: 18
MADV_KEEPONFORK :: 19
MADV_HWPOISON :: 100
+// perf event data
+Perf_Sample :: struct #raw_union {
+ period: u64,
+ frequency: u64,
+}
+Perf_Wakeup :: struct #raw_union {
+ events: u32,
+ watermark: u32,
+}
+Perf_Field1 :: struct #raw_union {
+ breakpoint_addr: u64,
+ kprobe_func: u64,
+ uprobe_path: u64,
+ config1: u64,
+}
+Perf_Field2 :: struct #raw_union {
+ breakpoint_len: u64,
+ kprobe_addr: u64,
+ uprobe_offset: u64,
+ config2: u64,
+}
+Perf_Event_Attr :: struct #packed {
+ type: u32,
+ size: u32,
+ config: u64,
+ sample: Perf_Sample,
+ sample_type: u64,
+ read_format: u64,
+ flags: Perf_Flags,
+ wakeup: Perf_Wakeup,
+ breakpoint_type: u32,
+ field1: Perf_Field1,
+ field2: Perf_Field2,
+ branch_sample_type: u64,
+ sample_regs_user: u64,
+ sample_stack_user: u32,
+ clock_id: i32,
+ sample_regs_intr: u64,
+ aux_watermark: u32,
+ sample_max_stack: u16,
+ _padding: u16,
+}
+
+Perf_Event_Flags :: distinct bit_set[Perf_Event_Flag; u64]
+Perf_Event_Flag :: enum u64 {
+ Bit0 = 0,
+ Bit0_Is_Deprecated = 1,
+ User_Rdpmc = 2,
+ User_Time = 3,
+ User_Time_Zero = 4,
+ User_Time_Short = 5,
+}
+Perf_Capabilities :: struct #raw_union {
+ capabilities: u64,
+ flags: Perf_Event_Flags,
+}
+Perf_Event_mmap_Page :: struct #packed {
+ version: u32,
+ compat_version: u32,
+ lock: u32,
+ index: u32,
+ offset: i64,
+ time_enabled: u64,
+ time_running: u64,
+ cap: Perf_Capabilities,
+ pmc_width: u16,
+ time_shift: u16,
+ time_mult: u32,
+ time_offset: u64,
+ time_zero: u64,
+ size: u32,
+ reserved1: u32,
+ time_cycles: u64,
+ time_mask: u64,
+ reserved2: [116*8]u8,
+ data_head: u64,
+ data_tail: u64,
+ data_offset: u64,
+ data_size: u64,
+ aux_head: u64,
+ aux_tail: u64,
+ aux_offset: u64,
+ aux_size: u64,
+}
+
+Perf_Type_Id :: enum u32 {
+ Hardware = 0,
+ Software = 1,
+ Tracepoint = 2,
+ HW_Cache = 3,
+ Raw = 4,
+ Breakpoint = 5,
+}
+
+Perf_Hardware_Id :: enum u64 {
+ CPU_Cycles = 0,
+ Instructions = 1,
+ Cache_References = 2,
+ Cache_Misses = 3,
+ Branch_Instructions = 4,
+ Branch_Misses = 5,
+ Bus_Cycles = 6,
+ Stalled_Cycles_Frontend = 7,
+ Stalled_Cycles_Backend = 8,
+ Ref_CPU_Cycles = 9,
+}
+
+Perf_Flags :: distinct bit_set[Perf_Flag; u64]
+Perf_Flag :: enum u64 {
+ Disabled = 0,
+ Inherit = 1,
+ Pinned = 2,
+ Exclusive = 3,
+ Exclude_User = 4,
+ Exclude_Kernel = 5,
+ Exclude_HV = 6,
+ Exclude_Idle = 7,
+ mmap = 8,
+ Comm = 9,
+ Freq = 10,
+ Inherit_Stat = 11,
+ Enable_On_Exec = 12,
+ Task = 13,
+ Watermark = 14,
+ Precise_IP_0 = 15,
+ Precise_IP_1 = 16,
+ mmap_Data = 17,
+ Sample_Id_All = 18,
+ Exclude_Host = 19,
+ Exclude_Guest = 20,
+ Exclude_Callchain_Kernel = 21,
+ Exclude_Callchain_User = 22,
+ mmap2 = 23,
+ Comm_Exec = 24,
+ Use_Clockid = 25,
+ Context_Switch = 26,
+ Write_Backward = 27,
+ Namespaces = 28,
+ KSymbol = 29,
+ BPF_Event = 30,
+ Aux_Output = 31,
+ CGroup = 32,
+ Text_Poke = 33,
+ Build_Id = 34,
+ Inherit_Thread = 35,
+ Remove_On_Exec = 36,
+ Sigtrap = 37,
+}
+
sys_gettid :: proc "contextless" () -> int {
return cast(int)intrinsics.syscall(SYS_gettid)
}
@@ -1846,6 +1995,10 @@ sys_utimensat :: proc "contextless" (dfd: int, path: cstring, times: rawptr, fla
return int(intrinsics.syscall(SYS_utimensat, uintptr(dfd), uintptr(rawptr(path)), uintptr(times), uintptr(flags)))
}
+sys_perf_event_open :: proc "contextless" (event_attr: rawptr, pid: i32, cpu: i32, group_fd: i32, flags: u32) -> int {
+ return int(intrinsics.syscall(SYS_perf_event_open, uintptr(event_attr), uintptr(pid), uintptr(cpu), uintptr(group_fd), uintptr(flags)))
+}
+
get_errno :: proc "contextless" (res: int) -> i32 {
if res < 0 && res > -4096 {
return i32(-res)
diff --git a/core/time/perf.odin b/core/time/perf.odin
index 53406646f..e51b17441 100644
--- a/core/time/perf.odin
+++ b/core/time/perf.odin
@@ -1,11 +1,11 @@
package time
import "core:runtime"
+import "core:intrinsics"
Tick :: struct {
_nsec: i64, // relative amount
}
-
tick_now :: proc "contextless" () -> Tick {
return _tick_now()
}
@@ -40,6 +40,53 @@ _tick_duration_end :: proc "contextless" (d: ^Duration, t: Tick) {
d^ = tick_since(t)
}
+when ODIN_ARCH == .amd64 {
+ @(private)
+ x86_has_invariant_tsc :: proc "contextless" () -> bool {
+ eax, _, _, _ := intrinsics.x86_cpuid(0x80_000_000, 0)
+
+ // Is this processor *really* ancient?
+ if eax < 0x80_000_007 {
+ return false
+ }
+
+ // check if the invariant TSC bit is set
+ _, _, _, edx := intrinsics.x86_cpuid(0x80_000_007, 0)
+ return (edx & (1 << 8)) != 0
+ }
+}
+
+has_invariant_tsc :: proc "contextless" () -> bool {
+ when ODIN_ARCH == .amd64 {
+ return x86_has_invariant_tsc()
+ }
+
+ return false
+}
+
+tsc_frequency :: proc "contextless" () -> (u64, bool) {
+ if !has_invariant_tsc() {
+ return 0, false
+ }
+
+ hz, ok := _get_tsc_frequency()
+ if !ok {
+ // fallback to approximate TSC
+ tsc_begin := intrinsics.read_cycle_counter()
+ tick_begin := tick_now()
+
+ sleep(2 * Second)
+
+ tsc_end := intrinsics.read_cycle_counter()
+ tick_end := tick_now()
+
+ time_diff := u128(duration_nanoseconds(tick_diff(tick_begin, tick_end)))
+ hz = u64((u128(tsc_end - tsc_begin) * 1_000_000_000) / time_diff)
+ }
+
+ return hz, true
+}
+
/*
Benchmark helpers
*/
@@ -94,4 +141,4 @@ benchmark :: proc(options: ^Benchmark_Options, allocator := context.allocator) -
options->teardown(allocator) or_return
}
return
-} \ No newline at end of file
+}
diff --git a/core/time/tsc_darwin.odin b/core/time/tsc_darwin.odin
new file mode 100644
index 000000000..9e54ee8f7
--- /dev/null
+++ b/core/time/tsc_darwin.odin
@@ -0,0 +1,21 @@
+//+private
+//+build darwin
+package time
+
+import "core:c"
+
+foreign import libc "System.framework"
+foreign libc {
+ @(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
+}
+
+_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
+ tmp_freq : u64 = 0
+ tmp_size : i64 = size_of(tmp_freq)
+ ret := _sysctlbyname("machdep.tsc.frequency", &tmp_freq, &tmp_size, nil, 0)
+ if ret < 0 {
+ return 0, false
+ }
+
+ return tmp_freq, true
+}
diff --git a/core/time/tsc_freebsd.odin b/core/time/tsc_freebsd.odin
new file mode 100644
index 000000000..f4d6ccc3a
--- /dev/null
+++ b/core/time/tsc_freebsd.odin
@@ -0,0 +1,21 @@
+//+private
+//+build freebsd
+package time
+
+import "core:c"
+
+foreign import libc "system:c"
+foreign libc {
+ @(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
+}
+
+_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
+ tmp_freq : u64 = 0
+ tmp_size : i64 = size_of(tmp_freq)
+ ret := _sysctlbyname("machdep.tsc_freq", &tmp_freq, &tmp_size, nil, 0)
+ if ret < 0 {
+ return 0, false
+ }
+
+ return tmp_freq, true
+}
diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin
new file mode 100644
index 000000000..c5f2902e9
--- /dev/null
+++ b/core/time/tsc_linux.odin
@@ -0,0 +1,35 @@
+//+private
+//+build linux
+package time
+
+import "core:intrinsics"
+import "core:sys/unix"
+
+_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
+ perf_attr := unix.Perf_Event_Attr{}
+ perf_attr.type = u32(unix.Perf_Type_Id.Hardware)
+ perf_attr.config = u64(unix.Perf_Hardware_Id.Instructions)
+ perf_attr.size = size_of(perf_attr)
+ perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV}
+ fd := unix.sys_perf_event_open(&perf_attr, 0, -1, -1, 0)
+ if fd == -1 {
+ return 0, false
+ }
+ defer unix.sys_close(fd)
+
+ page_size : uint = 4096
+ ret := unix.sys_mmap(nil, page_size, unix.PROT_READ, unix.MAP_SHARED, fd, 0)
+ if ret < 0 && ret > -4096 {
+ return 0, false
+ }
+ addr := rawptr(uintptr(ret))
+ defer unix.sys_munmap(addr, page_size)
+
+ event_page := (^unix.Perf_Event_mmap_Page)(addr)
+ if .User_Time not_in event_page.cap.flags {
+ return 0, false
+ }
+
+ frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
+ return frequency, true
+}
diff --git a/core/time/tsc_openbsd.odin b/core/time/tsc_openbsd.odin
new file mode 100644
index 000000000..ab126d5c1
--- /dev/null
+++ b/core/time/tsc_openbsd.odin
@@ -0,0 +1,7 @@
+//+private
+//+build openbsd
+package time
+
+_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
+ return 0, false
+}
diff --git a/core/time/tsc_windows.odin b/core/time/tsc_windows.odin
new file mode 100644
index 000000000..7f7be6393
--- /dev/null
+++ b/core/time/tsc_windows.odin
@@ -0,0 +1,7 @@
+//+private
+//+build windows
+package time
+
+_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
+ return 0, false
+}
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 7e3948336..fcd87e1a5 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1293,7 +1293,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
for (Type *t : variants) {
if (!type_ptr_set_exists(&seen, t)) {
array_add(&unhandled, t);
- gb_printf_err("HERE: %p %s\n", t, type_to_string(t));
}
}