From 656de10ba4d681263399d2bcb6b9b527a378d670 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Feb 2024 13:59:22 +0000 Subject: [PATCH 1/5] Minor changes to sync/chan (HIGHLY EXPERIMENTAL) --- core/sync/chan/chan.odin | 156 ++++++++++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 34 deletions(-) diff --git a/core/sync/chan/chan.odin b/core/sync/chan/chan.odin index fbd11be99..cbcfdf3bf 100644 --- a/core/sync/chan/chan.odin +++ b/core/sync/chan/chan.odin @@ -7,12 +7,6 @@ import "core:mem" import "core:sync" import "core:math/rand" -_ :: runtime -_ :: mem -_ :: sync - - - Direction :: enum { Send = -1, Both = 0, @@ -20,29 +14,28 @@ Direction :: enum { } Chan :: struct($T: typeid, $D: Direction = Direction.Both) { - #subtype impl: ^Raw_Chan, + #subtype impl: ^Raw_Chan `fmt:"-"`, } Raw_Chan :: struct { - allocator: runtime.Allocator, + // Shared + allocator: runtime.Allocator, allocation_size: int, + msg_size: u16, + closed: b16, // atomic + mutex: sync.Mutex, + r_cond: sync.Cond, + w_cond: sync.Cond, + r_waiting: int, // atomic + w_waiting: int, // atomic // Buffered queue: ^Raw_Queue, // Unbuffered - r_mutex: sync.Mutex, - w_mutex: sync.Mutex, + r_mutex: sync.Mutex, + w_mutex: sync.Mutex, unbuffered_data: rawptr, - msg_size: int, - - // Shared - mutex: sync.Mutex, - r_cond: sync.Cond, - w_cond: sync.Cond, - closed: bool, // atomic - r_waiting: int, // atomic - w_waiting: int, // atomic } @@ -52,13 +45,15 @@ create :: proc{ } @(require_results) -create_unbuffered :: proc($C: typeid/Chan($T), allocator: runtime.Allocator) -> (c: C, err: runtime.Allocator_Error) { +create_unbuffered :: proc($C: typeid/Chan($T), allocator: runtime.Allocator) -> (c: C, err: runtime.Allocator_Error) + where size_of(T) <= int(max(u16)) { c.impl, err = create_raw_unbuffered(size_of(T), align_of(T), allocator) return } @(require_results) -create_buffered :: proc($C: typeid/Chan($T), #any_int cap: int, allocator: runtime.Allocator) -> (c: C, err: runtime.Allocator_Error) { +create_buffered :: proc($C: typeid/Chan($T), #any_int cap: int, allocator: runtime.Allocator) -> (c: C, err: runtime.Allocator_Error) + where size_of(T) <= int(max(u16)) { c.impl, err = create_raw_buffered(size_of(T), align_of(T), cap, allocator) return } @@ -70,6 +65,7 @@ create_raw :: proc{ @(require_results) create_raw_unbuffered :: proc(#any_int msg_size, msg_alignment: int, allocator: runtime.Allocator) -> (c: ^Raw_Chan, err: runtime.Allocator_Error) { + assert(msg_size <= int(max(u16))) align := max(align_of(Raw_Chan), msg_alignment) size := mem.align_forward_int(size_of(Raw_Chan), align) @@ -81,12 +77,13 @@ create_raw_unbuffered :: proc(#any_int msg_size, msg_alignment: int, allocator: c = (^Raw_Chan)(ptr) c.allocation_size = size c.unbuffered_data = ([^]byte)(ptr)[offset:] - c.msg_size = msg_size + c.msg_size = u16(msg_size) return } @(require_results) create_raw_buffered :: proc(#any_int msg_size, msg_alignment: int, #any_int cap: int, allocator: runtime.Allocator) -> (c: ^Raw_Chan, err: runtime.Allocator_Error) { + assert(msg_size <= int(max(u16))) if cap <= 0 { return create_raw_unbuffered(msg_size, msg_alignment, allocator) } @@ -97,7 +94,7 @@ create_raw_buffered :: proc(#any_int msg_size, msg_alignment: int, #any_int cap: q_offset := size size = mem.align_forward_int(q_offset + size_of(Raw_Queue), msg_alignment) offset := size - size += msg_size * (cap+1) + size += msg_size * cap size = mem.align_forward_int(size, align) ptr := mem.alloc(size, align, allocator) or_return @@ -107,20 +104,18 @@ create_raw_buffered :: proc(#any_int msg_size, msg_alignment: int, #any_int cap: bptr := ([^]byte)(ptr) c.queue = (^Raw_Queue)(bptr[q_offset:]) - c.msg_size = msg_size + c.msg_size = u16(msg_size) - items := ([^]byte)(bptr[offset:]) - c.unbuffered_data = items - raw_queue_init(c.queue, items[msg_size:], cap, msg_size) + raw_queue_init(c.queue, ([^]byte)(bptr[offset:]), cap, msg_size) return } -destroy :: proc(c: ^Raw_Chan) -> runtime.Allocator_Error { +destroy :: proc(c: ^Raw_Chan) -> (err: runtime.Allocator_Error) { if c != nil { allocator := c.allocator - return mem.free_with_size(c, c.allocation_size, allocator) + err = mem.free_with_size(c, c.allocation_size, allocator) } - return nil + return } @(require_results) @@ -139,6 +134,13 @@ send :: proc "contextless" (c: $C/Chan($T, $D), data: T) -> (ok: bool) where C.D return } +@(require_results) +try_send :: proc "contextless" (c: $C/Chan($T, $D), data: T) -> (ok: bool) where C.D <= .Both { + data := data + ok = try_send_raw(c, &data) + return +} + @(require_results) recv :: proc "contextless" (c: $C/Chan($T)) -> (data: T, ok: bool) where C.D >= .Both { ok = recv_raw(c, &data) @@ -146,6 +148,13 @@ recv :: proc "contextless" (c: $C/Chan($T)) -> (data: T, ok: bool) where C.D >= } +@(require_results) +try_recv :: proc "contextless" (c: $C/Chan($T)) -> (data: T, ok: bool) where C.D >= .Both { + ok = try_recv_raw(c, &data) + return +} + + @(require_results) send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) { if c == nil { @@ -171,7 +180,7 @@ send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) { return false } - mem.copy(c.unbuffered_data, msg_in, c.msg_size) + mem.copy(c.unbuffered_data, msg_in, int(c.msg_size)) sync.atomic_add(&c.w_waiting, 1) if sync.atomic_load(&c.r_waiting) > 0 { sync.signal(&c.r_cond) @@ -201,7 +210,7 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) { msg := raw_queue_pop(c.queue) if msg != nil { - mem.copy(msg_out, msg, c.msg_size) + mem.copy(msg_out, msg, int(c.msg_size)) } if sync.atomic_load(&c.w_waiting) > 0 { @@ -223,7 +232,7 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) { return } - mem.copy(msg_out, c.unbuffered_data, c.msg_size) + mem.copy(msg_out, c.unbuffered_data, int(c.msg_size)) sync.atomic_sub(&c.w_waiting, 1) sync.signal(&c.w_cond) @@ -233,11 +242,90 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) { } +@(require_results) +try_send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) { + if c == nil { + return false + } + if c.queue != nil { // buffered + sync.guard(&c.mutex) + if c.queue.len == c.queue.cap { + return false + } + + ok = raw_queue_push(c.queue, msg_in) + if sync.atomic_load(&c.r_waiting) > 0 { + sync.signal(&c.r_cond) + } + } else if c.unbuffered_data != nil { // unbuffered + sync.guard(&c.w_mutex) + sync.guard(&c.mutex) + + if sync.atomic_load(&c.closed) { + return false + } + + mem.copy(c.unbuffered_data, msg_in, int(c.msg_size)) + sync.atomic_add(&c.w_waiting, 1) + if sync.atomic_load(&c.r_waiting) > 0 { + sync.signal(&c.r_cond) + } + sync.wait(&c.w_cond, &c.mutex) + ok = true + } + return +} + +@(require_results) +try_recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> bool { + if c == nil { + return false + } + if c.queue != nil { // buffered + sync.guard(&c.mutex) + if c.queue.len == 0 { + return false + } + + msg := raw_queue_pop(c.queue) + if msg != nil { + mem.copy(msg_out, msg, int(c.msg_size)) + } + + if sync.atomic_load(&c.w_waiting) > 0 { + sync.signal(&c.w_cond) + } + return true + } else if c.unbuffered_data != nil { // unbuffered + sync.guard(&c.r_mutex) + sync.guard(&c.mutex) + + if sync.atomic_load(&c.closed) || + sync.atomic_load(&c.w_waiting) == 0 { + return false + } + + mem.copy(msg_out, c.unbuffered_data, int(c.msg_size)) + sync.atomic_sub(&c.w_waiting, 1) + + sync.signal(&c.w_cond) + return true + } + return false +} + + + @(require_results) is_buffered :: proc "contextless" (c: ^Raw_Chan) -> bool { return c != nil && c.queue != nil } +@(require_results) +is_unbuffered :: proc "contextless" (c: ^Raw_Chan) -> bool { + return c != nil && c.unbuffered_data != nil +} + @(require_results) len :: proc "contextless" (c: ^Raw_Chan) -> int { if c != nil && c.queue != nil { @@ -276,7 +364,7 @@ is_closed :: proc "contextless" (c: ^Raw_Chan) -> bool { return true } sync.guard(&c.mutex) - return sync.atomic_load(&c.closed) + return bool(sync.atomic_load(&c.closed)) } From 213b2fd0f8059751b0cdd05b904c49109b21d474 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Feb 2024 14:01:23 +0000 Subject: [PATCH 2/5] Add `bit_field` as a keyword --- core/odin/tokenizer/token.odin | 2 ++ src/tokenizer.cpp | 1 + src/types.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/odin/tokenizer/token.odin b/core/odin/tokenizer/token.odin index 23808cf44..cd8953841 100644 --- a/core/odin/tokenizer/token.odin +++ b/core/odin/tokenizer/token.odin @@ -137,6 +137,7 @@ Token_Kind :: enum u32 { Union, // union Enum, // enum Bit_Set, // bit_set + Bit_Field, // bit_field Map, // map Dynamic, // dynamic Auto_Cast, // auto_cast @@ -270,6 +271,7 @@ tokens := [Token_Kind.COUNT]string { "union", "enum", "bit_set", + "bit_field", "map", "dynamic", "auto_cast", diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index dd9908be5..3d5348074 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -106,6 +106,7 @@ TOKEN_KIND(Token__KeywordBegin, ""), \ TOKEN_KIND(Token_union, "union"), \ TOKEN_KIND(Token_enum, "enum"), \ TOKEN_KIND(Token_bit_set, "bit_set"), \ + TOKEN_KIND(Token_bit_field, "bit_field"), \ TOKEN_KIND(Token_map, "map"), \ TOKEN_KIND(Token_dynamic, "dynamic"), \ TOKEN_KIND(Token_auto_cast, "auto_cast"), \ diff --git a/src/types.cpp b/src/types.cpp index 2f1994574..78d281715 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -4114,8 +4114,10 @@ gb_internal isize check_is_assignable_to_using_subtype(Type *src, Type *dst, isi } if (allow_polymorphic && dst_is_polymorphic) { Type *fb = base_type(type_deref(f->type)); - if (fb->kind == Type_Struct && fb->Struct.polymorphic_parent == dst) { - return true; + if (fb->kind == Type_Struct) { + if (fb->Struct.polymorphic_parent == dst) { + return true; + } } } From fea38f6910f4abb037e2581f28d7592c31991efe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Feb 2024 14:01:39 +0000 Subject: [PATCH 3/5] Minor changes to futex implementation on Linux --- src/check_expr.cpp | 6 ++++-- src/threading.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 11eb4b533..685bcdd6e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1241,7 +1241,7 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T } case Type_Pointer: if (source->kind == Type_Pointer) { - isize level = check_is_assignable_to_using_subtype(source->Pointer.elem, poly->Pointer.elem); + isize level = check_is_assignable_to_using_subtype(source->Pointer.elem, poly->Pointer.elem, /*level*/0, /*src_is_ptr*/false, /*allow_polymorphic*/true); if (level > 0) { return true; } @@ -1413,7 +1413,9 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T return ok; } - // return check_is_assignable_to(c, &o, poly); + + // NOTE(bill): Check for subtypes of + // return check_is_assignable_to(c, &o, poly); // && is_type_subtype_of_and_allow_polymorphic(o.type, poly); } return false; case Type_Tuple: diff --git a/src/threading.cpp b/src/threading.cpp index 725b58c89..684b13bc3 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -656,7 +656,7 @@ gb_internal void futex_wait(Futex *addr, Footex val) { for (;;) { int ret = syscall(SYS_futex, addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, NULL, NULL, 0); if (ret == -1) { - if (errno != EAGAIN) { + if (errno != EAGAIN && errno != EINTR) { perror("Futex wait"); GB_PANIC("Failed in futex wait!\n"); } else { From f3b0b82461f45ca6e0bb5e9a06e67cb02662053c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Feb 2024 14:04:31 +0000 Subject: [PATCH 4/5] Fix futex --- src/threading.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threading.cpp b/src/threading.cpp index 684b13bc3..725b58c89 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -656,7 +656,7 @@ gb_internal void futex_wait(Futex *addr, Footex val) { for (;;) { int ret = syscall(SYS_futex, addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, NULL, NULL, 0); if (ret == -1) { - if (errno != EAGAIN && errno != EINTR) { + if (errno != EAGAIN) { perror("Futex wait"); GB_PANIC("Failed in futex wait!\n"); } else { From b12ba1508eb5d7f53f0952e0267eb7b5b3dce463 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 22 Feb 2024 14:09:12 +0000 Subject: [PATCH 5/5] Update vulkan bindings for to work with the new keyword `bit_field` --- .../vulkan/_gen/create_vulkan_odin_wrapper.py | 2 +- vendor/vulkan/structs.odin | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py index 531460af2..65f53758f 100644 --- a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py +++ b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py @@ -565,7 +565,7 @@ def parse_structs(f): # The second way has many fields that are each 1 bit elif int(fname) == 1: bit_field_type = do_type(bit_field[0], prev_name, fname) - ffields.append(tuple(["bit_field", bit_field_type, comment])) + ffields.append(tuple(["bitfield", bit_field_type, comment])) break diff --git a/vendor/vulkan/structs.odin b/vendor/vulkan/structs.odin index 33613947e..e16a49dc3 100644 --- a/vendor/vulkan/structs.odin +++ b/vendor/vulkan/structs.odin @@ -7032,7 +7032,7 @@ WaylandSurfaceCreateInfoKHR :: struct { } VideoH264SpsVuiFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH264HrdParameters :: struct { @@ -7069,7 +7069,7 @@ VideoH264SequenceParameterSetVui :: struct { } VideoH264SpsFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH264ScalingLists :: struct { @@ -7108,7 +7108,7 @@ VideoH264SequenceParameterSet :: struct { } VideoH264PpsFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH264PictureParameterSet :: struct { @@ -7140,7 +7140,7 @@ VideoH265SubLayerHrdParameters :: struct { } VideoH265HrdFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265HrdParameters :: struct { @@ -7162,11 +7162,11 @@ VideoH265HrdParameters :: struct { } VideoH265VpsFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265ProfileTierLevelFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265ProfileTierLevel :: struct { @@ -7200,7 +7200,7 @@ VideoH265ScalingLists :: struct { } VideoH265SpsVuiFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265SequenceParameterSetVui :: struct { @@ -7237,11 +7237,11 @@ VideoH265PredictorPaletteEntries :: struct { } VideoH265SpsFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265ShortTermRefPicSetFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265ShortTermRefPicSet :: struct { @@ -7309,7 +7309,7 @@ VideoH265SequenceParameterSet :: struct { } VideoH265PpsFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoH265PictureParameterSet :: struct { @@ -7352,7 +7352,7 @@ VideoH265PictureParameterSet :: struct { } VideoDecodeH264PictureInfoFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoDecodeH264PictureInfo :: struct { @@ -7367,7 +7367,7 @@ VideoDecodeH264PictureInfo :: struct { } VideoDecodeH264ReferenceInfoFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoDecodeH264ReferenceInfo :: struct { @@ -7378,7 +7378,7 @@ VideoDecodeH264ReferenceInfo :: struct { } VideoDecodeH265PictureInfoFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoDecodeH265PictureInfo :: struct { @@ -7396,7 +7396,7 @@ VideoDecodeH265PictureInfo :: struct { } VideoDecodeH265ReferenceInfoFlags :: struct { - bit_field: u32, + bitfield: u32, } VideoDecodeH265ReferenceInfo :: struct {