aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-05-18 11:26:57 +0100
committergingerBill <bill@gingerbill.org>2023-05-18 11:26:57 +0100
commit49d1f6aca03672469d8fda0dedd27e330e698edc (patch)
treef762ab6c9b9d5ae0d374eda0b31a3c164fc94455 /core
parente82146bf17908dcc3619c8ec34bb0e902d7c213d (diff)
parent49cd9648b05c6eda252122104cb9b1faa2502602 (diff)
Merge branch 'master' into separate-int-word-sizes
Diffstat (limited to 'core')
-rw-r--r--core/bytes/buffer.odin5
-rw-r--r--core/encoding/hex/hex.odin73
-rw-r--r--core/net/url.odin54
-rw-r--r--core/os/file_windows.odin37
-rw-r--r--core/os/os.odin2
-rw-r--r--core/os/os2/env_linux.odin2
-rw-r--r--core/os/os2/file_linux.odin125
-rw-r--r--core/os/os2/heap_linux.odin2
-rw-r--r--core/os/os2/heap_windows.odin2
-rw-r--r--core/os/os2/path_linux.odin22
-rw-r--r--core/os/os2/stat_linux.odin17
-rw-r--r--core/os/os2/user.odin12
-rw-r--r--core/prof/spall/spall.odin17
-rw-r--r--core/runtime/core_builtin.odin2
-rw-r--r--core/runtime/os_specific_windows.odin2
-rw-r--r--core/sys/info/cpu_intel.odin11
-rw-r--r--core/time/perf.odin4
-rw-r--r--core/time/time.odin6
18 files changed, 209 insertions, 186 deletions
diff --git a/core/bytes/buffer.odin b/core/bytes/buffer.odin
index bba834f7e..b60a8e877 100644
--- a/core/bytes/buffer.odin
+++ b/core/bytes/buffer.odin
@@ -38,6 +38,11 @@ buffer_init_string :: proc(b: ^Buffer, s: string) {
}
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
+ if b.buf == nil {
+ b.buf = make([dynamic]byte, len, cap, allocator)
+ return
+ }
+
b.buf.allocator = allocator
reserve(&b.buf, cap)
resize(&b.buf, len)
diff --git a/core/encoding/hex/hex.odin b/core/encoding/hex/hex.odin
new file mode 100644
index 000000000..ef0bab1d0
--- /dev/null
+++ b/core/encoding/hex/hex.odin
@@ -0,0 +1,73 @@
+package hex
+
+import "core:strings"
+
+encode :: proc(src: []byte, allocator := context.allocator) -> []byte #no_bounds_check {
+ dst := make([]byte, len(src) * 2, allocator)
+ for i, j := 0, 0; i < len(src); i += 1 {
+ v := src[i]
+ dst[j] = HEXTABLE[v>>4]
+ dst[j+1] = HEXTABLE[v&0x0f]
+ j += 2
+ }
+
+ return dst
+}
+
+
+decode :: proc(src: []byte, allocator := context.allocator) -> (dst: []byte, ok: bool) #no_bounds_check {
+ if len(src) % 2 == 1 {
+ return
+ }
+
+ dst = make([]byte, len(src) / 2, allocator)
+ for i, j := 0, 1; j < len(src); j += 2 {
+ p := src[j-1]
+ q := src[j]
+
+ a := hex_digit(p) or_return
+ b := hex_digit(q) or_return
+
+ dst[i] = (a << 4) | b
+ i += 1
+ }
+
+ return dst, true
+}
+
+// Decodes the given sequence into one byte.
+// Should be called with one byte worth of the source, eg: 0x23 -> '#'.
+decode_sequence :: proc(str: string) -> (res: byte, ok: bool) {
+ str := str
+ if strings.has_prefix(str, "0x") || strings.has_prefix(str, "0X") {
+ str = str[2:]
+ }
+
+ if len(str) != 2 {
+ return 0, false
+ }
+
+ upper := hex_digit(str[0]) or_return
+ lower := hex_digit(str[1]) or_return
+
+ return upper << 4 | lower, true
+}
+
+@(private)
+HEXTABLE := [16]byte {
+ '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f',
+}
+
+@(private)
+hex_digit :: proc(char: byte) -> (u8, bool) {
+ switch char {
+ case '0' ..= '9': return char - '0', true
+ case 'a' ..= 'f': return char - 'a' + 10, true
+ case 'A' ..= 'F': return char - 'A' + 10, true
+ case: return 0, false
+ }
+}
+
diff --git a/core/net/url.odin b/core/net/url.odin
index a5e529928..ed39f7859 100644
--- a/core/net/url.odin
+++ b/core/net/url.odin
@@ -19,7 +19,7 @@ package net
import "core:strings"
import "core:strconv"
import "core:unicode/utf8"
-import "core:mem"
+import "core:encoding/hex"
split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string) {
s := url
@@ -36,9 +36,11 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host,
s = s[:i]
if query_str != "" {
queries_parts := strings.split(query_str, "&")
+ defer delete(queries_parts)
queries = make(map[string]string, len(queries_parts), allocator)
for q in queries_parts {
parts := strings.split(q, "=")
+ defer delete(parts)
switch len(parts) {
case 1: queries[parts[0]] = "" // NOTE(tetra): Query not set to anything, was but present.
case 2: queries[parts[0]] = parts[1] // NOTE(tetra): Query set to something.
@@ -76,13 +78,19 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, allocat
}
- if len(queries) > 0 do write_string(&b, "?")
+ query_length := len(queries)
+ if query_length > 0 do write_string(&b, "?")
+ i := 0
for query_name, query_value in queries {
write_string(&b, query_name)
if query_value != "" {
write_string(&b, "=")
write_string(&b, query_value)
}
+ if i < query_length - 1 {
+ write_string(&b, "&")
+ }
+ i += 1
}
return to_string(b)
@@ -119,12 +127,10 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) -
builder_grow(&b, len(encoded_string))
defer if !ok do builder_destroy(&b)
- stack_buf: [4]u8
- pending := mem.buffer_from_slice(stack_buf[:])
s := encoded_string
for len(s) > 0 {
- i := index_rune(s, '%')
+ i := index_byte(s, '%')
if i == -1 {
write_string(&b, s) // no '%'s; the string is already decoded
break
@@ -137,47 +143,15 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) -
s = s[1:]
if s[0] == '%' {
- write_rune(&b, '%')
+ write_byte(&b, '%')
s = s[1:]
continue
}
if len(s) < 2 do return // percent without encoded value
- n: int
- n, _ = strconv.parse_int(s[:2], 16)
- switch n {
- case 0x20: write_rune(&b, ' ')
- case 0x21: write_rune(&b, '!')
- case 0x23: write_rune(&b, '#')
- case 0x24: write_rune(&b, '$')
- case 0x25: write_rune(&b, '%')
- case 0x26: write_rune(&b, '&')
- case 0x27: write_rune(&b, '\'')
- case 0x28: write_rune(&b, '(')
- case 0x29: write_rune(&b, ')')
- case 0x2A: write_rune(&b, '*')
- case 0x2B: write_rune(&b, '+')
- case 0x2C: write_rune(&b, ',')
- case 0x2F: write_rune(&b, '/')
- case 0x3A: write_rune(&b, ':')
- case 0x3B: write_rune(&b, ';')
- case 0x3D: write_rune(&b, '=')
- case 0x3F: write_rune(&b, '?')
- case 0x40: write_rune(&b, '@')
- case 0x5B: write_rune(&b, '[')
- case 0x5D: write_rune(&b, ']')
- case:
- // utf-8 bytes
- // TODO(tetra): Audit this - 4 bytes???
- append(&pending, s[0])
- append(&pending, s[1])
- if len(pending) == 4 {
- r, _ := utf8.decode_rune(pending[:])
- write_rune(&b, r)
- clear(&pending)
- }
- }
+ val := hex.decode_sequence(s[:2]) or_return
+ write_byte(&b, val)
s = s[2:]
}
diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin
index a5f329d45..9d62014af 100644
--- a/core/os/file_windows.odin
+++ b/core/os/file_windows.odin
@@ -220,6 +220,7 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
@(private)
MAX_RW :: 1<<30
+ERROR_EOF :: 38
@(private)
pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
@@ -228,11 +229,6 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
buf = buf[:MAX_RW]
}
- curr_offset, e := seek(fd, offset, 1)
- if e != 0 {
- return 0, e
- }
- defer seek(fd, curr_offset, 0)
o := win32.OVERLAPPED{
OffsetHigh = u32(offset>>32),
@@ -243,6 +239,7 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
h := win32.HANDLE(fd)
done: win32.DWORD
+ e: Errno
if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
e = Errno(win32.GetLastError())
done = 0
@@ -256,11 +253,6 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
buf = buf[:MAX_RW]
}
- curr_offset, e := seek(fd, offset, 1)
- if e != 0 {
- return 0, e
- }
- defer seek(fd, curr_offset, 0)
o := win32.OVERLAPPED{
OffsetHigh = u32(offset>>32),
@@ -269,6 +261,7 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
h := win32.HANDLE(fd)
done: win32.DWORD
+ e: Errno
if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
e = Errno(win32.GetLastError())
done = 0
@@ -276,6 +269,16 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
return int(done), e
}
+/*
+read_at returns n: 0, err: 0 on EOF
+on Windows, read_at changes the position of the file cursor, on *nix, it does not.
+
+ bytes: [8]u8{}
+ read_at(fd, bytes, 0)
+ read(fd, bytes)
+
+will read from the location twice on *nix, and from two different locations on Windows
+*/
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
if offset < 0 {
return 0, ERROR_NEGATIVE_OFFSET
@@ -284,6 +287,10 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
b, offset := data, offset
for len(b) > 0 {
m, e := pread(fd, b, offset)
+ if e == ERROR_EOF {
+ err = 0
+ break
+ }
if e != 0 {
err = e
break
@@ -294,6 +301,16 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
}
return
}
+
+/*
+on Windows, write_at changes the position of the file cursor, on *nix, it does not.
+
+ bytes: [8]u8{}
+ write_at(fd, bytes, 0)
+ write(fd, bytes)
+
+will write to the location twice on *nix, and to two different locations on Windows
+*/
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
if offset < 0 {
return 0, ERROR_NEGATIVE_OFFSET
diff --git a/core/os/os.odin b/core/os/os.odin
index 971abd911..b71ea261e 100644
--- a/core/os/os.odin
+++ b/core/os/os.odin
@@ -194,7 +194,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
- if (size + diff) > space {
+ if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
diff --git a/core/os/os2/env_linux.odin b/core/os/os2/env_linux.odin
index 9a2c52739..e7165b583 100644
--- a/core/os/os2/env_linux.odin
+++ b/core/os/os2/env_linux.odin
@@ -3,7 +3,7 @@ package os2
import "core:runtime"
-_get_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
+_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
//TODO
return
}
diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin
index 1a6f69d31..890bbfc43 100644
--- a/core/os/os2/file_linux.odin
+++ b/core/os/os2/file_linux.odin
@@ -9,19 +9,20 @@ import "core:sys/unix"
INVALID_HANDLE :: -1
-_O_RDONLY :: 0o0
-_O_WRONLY :: 0o1
-_O_RDWR :: 0o2
-_O_CREAT :: 0o100
-_O_EXCL :: 0o200
-_O_TRUNC :: 0o1000
-_O_APPEND :: 0o2000
-_O_NONBLOCK :: 0o4000
-_O_LARGEFILE :: 0o100000
-_O_DIRECTORY :: 0o200000
-_O_NOFOLLOW :: 0o400000
-_O_SYNC :: 0o4010000
-_O_CLOEXEC :: 0o2000000
+_O_RDONLY :: 0o00000000
+_O_WRONLY :: 0o00000001
+_O_RDWR :: 0o00000002
+_O_CREAT :: 0o00000100
+_O_EXCL :: 0o00000200
+_O_NOCTTY :: 0o00000400
+_O_TRUNC :: 0o00001000
+_O_APPEND :: 0o00002000
+_O_NONBLOCK :: 0o00004000
+_O_LARGEFILE :: 0o00100000
+_O_DIRECTORY :: 0o00200000
+_O_NOFOLLOW :: 0o00400000
+_O_SYNC :: 0o04010000
+_O_CLOEXEC :: 0o02000000
_O_PATH :: 0o10000000
_AT_FDCWD :: -100
@@ -40,9 +41,12 @@ _file_allocator :: proc() -> runtime.Allocator {
_open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
- name_cstr := _name_to_cstring(name)
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
- flags_i: int
+ // Just default to using O_NOCTTY because needing to open a controlling
+ // terminal would be incredibly rare. This has no effect on files while
+ // allowing us to open serial devices.
+ flags_i: int = _O_NOCTTY
switch flags & O_RDONLY|O_WRONLY|O_RDWR {
case O_RDONLY: flags_i = _O_RDONLY
case O_WRONLY: flags_i = _O_WRONLY
@@ -56,7 +60,7 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error
flags_i |= (_O_TRUNC * int(.Trunc in flags))
flags_i |= (_O_CLOEXEC * int(.Close_On_Exec in flags))
- fd := unix.sys_open(name_cstr, flags_i, int(perm))
+ fd := unix.sys_open(name_cstr, flags_i, uint(perm))
if fd < 0 {
return nil, _get_platform_error(fd)
}
@@ -196,10 +200,7 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
}
_remove :: proc(name: string) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
fd := unix.sys_open(name_cstr, int(File_Flags.Read))
if fd < 0 {
@@ -214,40 +215,22 @@ _remove :: proc(name: string) -> Error {
}
_rename :: proc(old_name, new_name: string) -> Error {
- old_name_cstr, old_allocated := _name_to_cstring(old_name)
- new_name_cstr, new_allocated := _name_to_cstring(new_name)
- defer if old_allocated {
- delete(old_name_cstr)
- }
- defer if new_allocated {
- delete(new_name_cstr)
- }
+ old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
+ new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
return _ok_or_error(unix.sys_rename(old_name_cstr, new_name_cstr))
}
_link :: proc(old_name, new_name: string) -> Error {
- old_name_cstr, old_allocated := _name_to_cstring(old_name)
- new_name_cstr, new_allocated := _name_to_cstring(new_name)
- defer if old_allocated {
- delete(old_name_cstr)
- }
- defer if new_allocated {
- delete(new_name_cstr)
- }
+ old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
+ new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
return _ok_or_error(unix.sys_link(old_name_cstr, new_name_cstr))
}
_symlink :: proc(old_name, new_name: string) -> Error {
- old_name_cstr, old_allocated := _name_to_cstring(old_name)
- new_name_cstr, new_allocated := _name_to_cstring(new_name)
- defer if old_allocated {
- delete(old_name_cstr)
- }
- defer if new_allocated {
- delete(new_name_cstr)
- }
+ old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
+ new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
return _ok_or_error(unix.sys_symlink(old_name_cstr, new_name_cstr))
}
@@ -271,26 +254,17 @@ _read_link_cstr :: proc(name_cstr: cstring, allocator: runtime.Allocator) -> (st
}
_read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _read_link_cstr(name_cstr, allocator)
}
_unlink :: proc(name: string) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_unlink(name_cstr))
}
_chdir :: proc(name: string) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_chdir(name_cstr))
}
@@ -299,32 +273,23 @@ _fchdir :: proc(f: ^File) -> Error {
}
_chmod :: proc(name: string, mode: File_Mode) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
- return _ok_or_error(unix.sys_chmod(name_cstr, int(mode)))
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
+ return _ok_or_error(unix.sys_chmod(name_cstr, uint(mode)))
}
_fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
- return _ok_or_error(unix.sys_fchmod(f.impl.fd, int(mode)))
+ return _ok_or_error(unix.sys_fchmod(f.impl.fd, uint(mode)))
}
// NOTE: will throw error without super user priviledges
_chown :: proc(name: string, uid, gid: int) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_chown(name_cstr, uid, gid))
}
// NOTE: will throw error without super user priviledges
_lchown :: proc(name: string, uid, gid: int) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_lchown(name_cstr, uid, gid))
}
@@ -334,10 +299,7 @@ _fchown :: proc(f: ^File, uid, gid: int) -> Error {
}
_chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
times := [2]Unix_File_Time {
{ atime._nsec, 0 },
{ mtime._nsec, 0 },
@@ -354,18 +316,12 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
}
_exists :: proc(name: string) -> bool {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return unix.sys_access(name_cstr, F_OK) == 0
}
_is_file :: proc(name: string) -> bool {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
s: _Stat
res := unix.sys_stat(name_cstr, &s)
if res < 0 {
@@ -384,10 +340,7 @@ _is_file_fd :: proc(fd: int) -> bool {
}
_is_dir :: proc(name: string) -> bool {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
s: _Stat
res := unix.sys_stat(name_cstr, &s)
if res < 0 {
diff --git a/core/os/os2/heap_linux.odin b/core/os/os2/heap_linux.odin
index b631268a1..136c3e6cb 100644
--- a/core/os/os2/heap_linux.odin
+++ b/core/os/os2/heap_linux.odin
@@ -166,7 +166,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
- if (size + diff) > space {
+ if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
diff --git a/core/os/os2/heap_windows.odin b/core/os/os2/heap_windows.odin
index 0f154cd8c..eba403c1d 100644
--- a/core/os/os2/heap_windows.odin
+++ b/core/os/os2/heap_windows.odin
@@ -52,7 +52,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
- if (size + diff) > space {
+ if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
diff --git a/core/os/os2/path_linux.odin b/core/os/os2/path_linux.odin
index 3120fcda3..2a0ef29d8 100644
--- a/core/os/os2/path_linux.odin
+++ b/core/os/os2/path_linux.odin
@@ -31,11 +31,8 @@ _mkdir :: proc(path: string, perm: File_Mode) -> Error {
return .Invalid_Argument
}
- path_cstr, allocated := _name_to_cstring(path)
- defer if allocated {
- delete(path_cstr)
- }
- return _ok_or_error(unix.sys_mkdir(path_cstr, int(perm & 0o777)))
+ path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
+ return _ok_or_error(unix.sys_mkdir(path_cstr, uint(perm & 0o777)))
}
_mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
@@ -49,7 +46,7 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
new_dfd := unix.sys_openat(dfd, cstring(&path[0]), _OPENDIR_FLAGS)
switch new_dfd {
case -ENOENT:
- if res := unix.sys_mkdirat(dfd, cstring(&path[0]), perm); res < 0 {
+ if res := unix.sys_mkdirat(dfd, cstring(&path[0]), uint(perm)); res < 0 {
return _get_platform_error(res)
}
has_created^ = true
@@ -83,9 +80,6 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
} else {
path_bytes = make([]u8, len(path) + 1, context.temp_allocator)
}
- defer if allocated {
- delete(path_bytes)
- }
// NULL terminate the byte slice to make it a valid cstring
copy(path_bytes, path)
@@ -182,10 +176,7 @@ _remove_all :: proc(path: string) -> Error {
return nil
}
- path_cstr, allocated := _name_to_cstring(path)
- defer if allocated {
- delete(path_cstr)
- }
+ path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
fd := unix.sys_open(path_cstr, _OPENDIR_FLAGS)
switch fd {
@@ -222,10 +213,7 @@ _getwd :: proc(allocator: runtime.Allocator) -> (string, Error) {
}
_setwd :: proc(dir: string) -> Error {
- dir_cstr, allocated := _name_to_cstring(dir)
- defer if allocated {
- delete(dir_cstr)
- }
+ dir_cstr := strings.clone_to_cstring(dir, context.temp_allocator)
return _ok_or_error(unix.sys_chdir(dir_cstr))
}
diff --git a/core/os/os2/stat_linux.odin b/core/os/os2/stat_linux.odin
index 2f99f6d2e..530e0e7d0 100644
--- a/core/os/os2/stat_linux.odin
+++ b/core/os/os2/stat_linux.odin
@@ -3,6 +3,7 @@ package os2
import "core:time"
import "core:runtime"
+import "core:strings"
import "core:sys/unix"
import "core:path/filepath"
@@ -112,10 +113,7 @@ _fstat_internal :: proc(fd: int, allocator: runtime.Allocator) -> (File_Info, Er
// NOTE: _stat and _lstat are using _fstat to avoid a race condition when populating fullpath
_stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
fd := unix.sys_open(name_cstr, _O_RDONLY)
if fd < 0 {
@@ -126,10 +124,8 @@ _stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error)
}
_lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
+
fd := unix.sys_open(name_cstr, _O_RDONLY | _O_PATH | _O_NOFOLLOW)
if fd < 0 {
return {}, _get_platform_error(fd)
@@ -143,10 +139,7 @@ _same_file :: proc(fi1, fi2: File_Info) -> bool {
}
_stat_internal :: proc(name: string) -> (s: _Stat, res: int) {
- name_cstr, allocated := _name_to_cstring(name)
- defer if allocated {
- delete(name_cstr)
- }
+ name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
res = unix.sys_stat(name_cstr, &s)
return
}
diff --git a/core/os/os2/user.odin b/core/os/os2/user.odin
index 00cccd2a7..0e9f126aa 100644
--- a/core/os/os2/user.odin
+++ b/core/os/os2/user.odin
@@ -8,12 +8,12 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
case .Windows:
dir = get_env("LocalAppData", allocator)
if dir != "" {
- dir = strings.clone_safe(dir, allocator) or_return
+ dir = strings.clone(dir, allocator) or_return
}
case .Darwin:
dir = get_env("HOME", allocator)
if dir != "" {
- dir = strings.concatenate_safe({dir, "/Library/Caches"}, allocator) or_return
+ dir = strings.concatenate({dir, "/Library/Caches"}, allocator) or_return
}
case: // All other UNIX systems
dir = get_env("XDG_CACHE_HOME", allocator)
@@ -22,7 +22,7 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
if dir == "" {
return
}
- dir = strings.concatenate_safe({dir, "/.cache"}, allocator) or_return
+ dir = strings.concatenate({dir, "/.cache"}, allocator) or_return
}
}
if dir == "" {
@@ -36,12 +36,12 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
case .Windows:
dir = get_env("AppData", allocator)
if dir != "" {
- dir = strings.clone_safe(dir, allocator) or_return
+ dir = strings.clone(dir, allocator) or_return
}
case .Darwin:
dir = get_env("HOME", allocator)
if dir != "" {
- dir = strings.concatenate_safe({dir, "/Library/Application Support"}, allocator) or_return
+ dir = strings.concatenate({dir, "/Library/Application Support"}, allocator) or_return
}
case: // All other UNIX systems
dir = get_env("XDG_CACHE_HOME", allocator)
@@ -50,7 +50,7 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
if dir == "" {
return
}
- dir = strings.concatenate_safe({dir, "/.config"}, allocator) or_return
+ dir = strings.concatenate({dir, "/.config"}, allocator) or_return
}
}
if dir == "" {
diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin
index 6a78c466e..19a05d70a 100644
--- a/core/prof/spall/spall.odin
+++ b/core/prof/spall/spall.odin
@@ -67,16 +67,15 @@ Buffer :: struct {
BUFFER_DEFAULT_SIZE :: 0x10_0000
-context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_ok {
+context_create_with_scale :: proc(filename: string, precise_time: bool, timestamp_scale: f64) -> (ctx: Context, ok: bool) #optional_ok {
fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
if err != os.ERROR_NONE {
return
}
- ctx.fd = fd
- freq, freq_ok := time.tsc_frequency()
- ctx.precise_time = freq_ok
- ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
+ ctx.fd = fd
+ ctx.precise_time = precise_time
+ ctx.timestamp_scale = timestamp_scale
temp := [size_of(Manual_Header)]u8{}
_build_header(temp[:], ctx.timestamp_scale)
@@ -85,6 +84,14 @@ context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_o
return
}
+context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok {
+ freq, freq_ok := time.tsc_frequency(sleep)
+ timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
+ return context_create_with_scale(filename, freq_ok, timestamp_scale)
+}
+
+context_create :: proc{context_create_with_scale, context_create_with_sleep}
+
context_destroy :: proc(ctx: ^Context) {
if ctx == nil {
return
diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin
index 4b152e7cc..bd919247e 100644
--- a/core/runtime/core_builtin.odin
+++ b/core/runtime/core_builtin.odin
@@ -401,7 +401,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> int {
return 0
}
prev_len := len(array)
- resize(array, len(array)+1)
+ resize(array, len(array)+1, loc)
return len(array)-prev_len
}
diff --git a/core/runtime/os_specific_windows.odin b/core/runtime/os_specific_windows.odin
index 6e7474257..732715793 100644
--- a/core/runtime/os_specific_windows.odin
+++ b/core/runtime/os_specific_windows.odin
@@ -112,7 +112,7 @@ _windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, ol
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
- if (size + diff) > space {
+ if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
diff --git a/core/sys/info/cpu_intel.odin b/core/sys/info/cpu_intel.odin
index 8cd723203..5a11863d4 100644
--- a/core/sys/info/cpu_intel.odin
+++ b/core/sys/info/cpu_intel.odin
@@ -38,7 +38,7 @@ cpu_name: Maybe(string)
@(init, private)
init_cpu_features :: proc "c" () {
is_set :: #force_inline proc "c" (hwc: u32, value: u32) -> bool {
- return hwc&value != 0
+ return hwc&(1 << value) != 0
}
try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, hwc: u32, value: u32) {
if is_set(hwc, value) {
@@ -74,8 +74,15 @@ init_cpu_features :: proc "c" () {
return
}
+ // In certain rare cases (reason unknown), XGETBV generates an
+ // illegal instruction, even if OSXSAVE is set per CPUID.
+ //
+ // When Chrome ran into this problem, the problem went away
+ // after they started checking both OSXSAVE and XSAVE.
+ //
+ // See: crbug.com/375968
os_supports_avx := false
- if .os_xsave in set {
+ if .os_xsave in set && is_set(26, ecx1) {
eax, _ := xgetbv(0)
os_supports_avx = is_set(1, eax) && is_set(2, eax)
}
diff --git a/core/time/perf.odin b/core/time/perf.odin
index 69f7eceaa..87192093a 100644
--- a/core/time/perf.odin
+++ b/core/time/perf.odin
@@ -70,7 +70,7 @@ has_invariant_tsc :: proc "contextless" () -> bool {
return false
}
-tsc_frequency :: proc "contextless" () -> (u64, bool) {
+tsc_frequency :: proc "contextless" (fallback_sleep := 2 * Second) -> (u64, bool) {
if !has_invariant_tsc() {
return 0, false
}
@@ -81,7 +81,7 @@ tsc_frequency :: proc "contextless" () -> (u64, bool) {
tsc_begin := intrinsics.read_cycle_counter()
tick_begin := tick_now()
- sleep(2 * Second)
+ sleep(fallback_sleep)
tsc_end := intrinsics.read_cycle_counter()
tick_end := tick_now()
diff --git a/core/time/time.odin b/core/time/time.odin
index 74c80c8f7..6c424a62e 100644
--- a/core/time/time.odin
+++ b/core/time/time.odin
@@ -170,6 +170,12 @@ day :: proc "contextless" (t: Time) -> (day: int) {
return
}
+weekday :: proc "contextless" (t: Time) -> (weekday: Weekday) {
+ abs := _time_abs(t)
+ sec := (abs + u64(Weekday.Monday) * SECONDS_PER_DAY) % SECONDS_PER_WEEK
+ return Weekday(int(sec) / SECONDS_PER_DAY)
+}
+
clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch }
clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) {