mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Merge branch 'master' into bigint
This commit is contained in:
@@ -0,0 +1,143 @@
|
|||||||
|
//+build darwin
|
||||||
|
//+private
|
||||||
|
package sync2
|
||||||
|
|
||||||
|
import "core:time"
|
||||||
|
import "core:c"
|
||||||
|
import "intrinsics"
|
||||||
|
|
||||||
|
foreign import pthread "System.framework"
|
||||||
|
|
||||||
|
_current_thread_id :: proc "contextless" () -> int {
|
||||||
|
tid: u64;
|
||||||
|
// NOTE(Oskar): available from OSX 10.6 and iOS 3.2.
|
||||||
|
// For older versions there is `syscall(SYS_thread_selfid)`, but not really
|
||||||
|
// the same thing apparently.
|
||||||
|
foreign pthread { pthread_threadid_np :: proc "c" (rawptr, ^u64) -> c.int ---; }
|
||||||
|
pthread_threadid_np(nil, &tid);
|
||||||
|
return int(tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign {
|
||||||
|
@(link_name="usleep")
|
||||||
|
_darwin_usleep :: proc "c" (us: uint) -> i32 ---
|
||||||
|
@(link_name="sched_yield")
|
||||||
|
_darwin_sched_yield :: proc "c" () -> i32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
_atomic_try_wait_slow :: proc(ptr: ^u32, val: u32) {
|
||||||
|
history: uint = 10;
|
||||||
|
for {
|
||||||
|
// Exponential wait
|
||||||
|
_darwin_usleep(history >> 2);
|
||||||
|
history += history >> 2;
|
||||||
|
if history > (1 << 10) {
|
||||||
|
history = 1 << 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if atomic_load(ptr) != val {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_atomic_wait :: proc(ptr: ^u32, val: u32) {
|
||||||
|
if intrinsics.expect(atomic_load(ptr) != val, true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for i in 0..<16 {
|
||||||
|
if atomic_load(ptr) != val {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if i < 12 {
|
||||||
|
intrinsics.cpu_relax();
|
||||||
|
} else {
|
||||||
|
_darwin_sched_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for val == atomic_load(ptr) {
|
||||||
|
_atomic_try_wait_slow(ptr, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_Mutex :: struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_mutex_lock :: proc(m: ^Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_mutex_unlock :: proc(m: ^Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_RW_Mutex :: struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
_rw_mutex_lock :: proc(rw: ^RW_Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_rw_mutex_unlock :: proc(rw: ^RW_Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_Recursive_Mutex :: struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_Cond :: struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
_cond_wait :: proc(c: ^Cond, m: ^Mutex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cond_signal :: proc(c: ^Cond) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_cond_broadcast :: proc(c: ^Cond) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_Sema :: struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_wait :: proc(s: ^Sema) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_post :: proc(s: ^Sema, count := 1) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
//+build linux
|
||||||
|
//+private
|
||||||
|
package sync2
|
||||||
|
|
||||||
|
// TODO(bill): remove libc
|
||||||
|
foreign import libc "system:c"
|
||||||
|
|
||||||
|
_current_thread_id :: proc "contextless" () -> int {
|
||||||
|
foreign libc {
|
||||||
|
syscall :: proc(number: i32, #c_vararg args: ..any) -> i32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_GETTID :: 186;
|
||||||
|
return int(syscall(SYS_GETTID));
|
||||||
|
}
|
||||||
@@ -139,7 +139,7 @@ _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||||
tid := runtime.current_thread_id();
|
tid := _current_thread_id();
|
||||||
assert(tid == m.impl.owner);
|
assert(tid == m.impl.owner);
|
||||||
m.impl.recursion -= 1;
|
m.impl.recursion -= 1;
|
||||||
recursion := m.impl.recursion;
|
recursion := m.impl.recursion;
|
||||||
@@ -154,7 +154,7 @@ _recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||||
tid := runtime.current_thread_id();
|
tid := _current_thread_id();
|
||||||
if m.impl.owner == tid {
|
if m.impl.owner == tid {
|
||||||
return mutex_try_lock(&m.impl.mutex);
|
return mutex_try_lock(&m.impl.mutex);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -923,7 +923,7 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
|
|||||||
poly->kind = Type_EnumeratedArray;
|
poly->kind = Type_EnumeratedArray;
|
||||||
poly->cached_size = -1;
|
poly->cached_size = -1;
|
||||||
poly->cached_align = -1;
|
poly->cached_align = -1;
|
||||||
poly->flags = source->flags;
|
poly->flags.exchange(source->flags);
|
||||||
poly->failure = false;
|
poly->failure = false;
|
||||||
poly->EnumeratedArray.elem = source->EnumeratedArray.elem;
|
poly->EnumeratedArray.elem = source->EnumeratedArray.elem;
|
||||||
poly->EnumeratedArray.index = source->EnumeratedArray.index;
|
poly->EnumeratedArray.index = source->EnumeratedArray.index;
|
||||||
@@ -4117,20 +4117,23 @@ bool check_identifier_exists(Scope *s, Ast *node, bool nested = false, Scope **o
|
|||||||
}
|
}
|
||||||
|
|
||||||
isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) {
|
isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) {
|
||||||
if (lhs != nullptr) {
|
if (lhs != nullptr && c->decl != nullptr) {
|
||||||
|
mutex_lock(&c->info->deps_mutex);
|
||||||
|
|
||||||
for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) {
|
for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) {
|
||||||
Entity *e = lhs[tuple_index + j];
|
Entity *e = lhs[tuple_index + j];
|
||||||
if (e != nullptr) {
|
if (e != nullptr) {
|
||||||
DeclInfo *decl = decl_info_of_entity(e);
|
DeclInfo *decl = decl_info_of_entity(e);
|
||||||
if (decl != nullptr) {
|
if (decl != nullptr) {
|
||||||
c->decl = decl; // will be reset by the 'defer' any way
|
|
||||||
for_array(k, decl->deps.entries) {
|
for_array(k, decl->deps.entries) {
|
||||||
Entity *dep = decl->deps.entries[k].ptr;
|
Entity *dep = decl->deps.entries[k].ptr;
|
||||||
add_declaration_dependency(c, dep); // TODO(bill): Should this be here?
|
ptr_set_add(&c->decl->deps, dep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&c->info->deps_mutex);
|
||||||
}
|
}
|
||||||
return tuple_count;
|
return tuple_count;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -159,7 +159,12 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields
|
|||||||
Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
|
Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
|
||||||
add_entity(ctx, ctx->scope, name, field);
|
add_entity(ctx, ctx->scope, name, field);
|
||||||
array_add(fields, field);
|
array_add(fields, field);
|
||||||
array_add(tags, p->tag.string);
|
String tag = p->tag.string;
|
||||||
|
if (tag.len != 0 && !unquote_string(permanent_allocator(), &tag, 0, tag.text[0] == '`')) {
|
||||||
|
error(p->tag, "Invalid string literal");
|
||||||
|
tag = {};
|
||||||
|
}
|
||||||
|
array_add(tags, tag);
|
||||||
|
|
||||||
field_src_index += 1;
|
field_src_index += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -629,14 +629,16 @@ void check_scope_usage(Checker *c, Scope *scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_dependency(DeclInfo *d, Entity *e) {
|
void add_dependency(CheckerInfo *info, DeclInfo *d, Entity *e) {
|
||||||
|
mutex_lock(&info->deps_mutex);
|
||||||
ptr_set_add(&d->deps, e);
|
ptr_set_add(&d->deps, e);
|
||||||
|
mutex_unlock(&info->deps_mutex);
|
||||||
}
|
}
|
||||||
void add_type_info_dependency(DeclInfo *d, Type *type) {
|
void add_type_info_dependency(DeclInfo *d, Type *type) {
|
||||||
if (d == nullptr) {
|
if (d == nullptr) {
|
||||||
// GB_ASSERT(type == t_invalid);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// NOTE(bill): no mutex is required here because the only procedure calling it is wrapped in a mutex already
|
||||||
ptr_set_add(&d->type_info_deps, type);
|
ptr_set_add(&d->type_info_deps, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,7 +659,7 @@ void add_package_dependency(CheckerContext *c, char const *package_name, char co
|
|||||||
e->flags |= EntityFlag_Used;
|
e->flags |= EntityFlag_Used;
|
||||||
GB_ASSERT_MSG(e != nullptr, "%s", name);
|
GB_ASSERT_MSG(e != nullptr, "%s", name);
|
||||||
GB_ASSERT(c->decl != nullptr);
|
GB_ASSERT(c->decl != nullptr);
|
||||||
ptr_set_add(&c->decl->deps, e);
|
add_dependency(c->info, c->decl, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_declaration_dependency(CheckerContext *c, Entity *e) {
|
void add_declaration_dependency(CheckerContext *c, Entity *e) {
|
||||||
@@ -665,7 +667,7 @@ void add_declaration_dependency(CheckerContext *c, Entity *e) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c->decl != nullptr) {
|
if (c->decl != nullptr) {
|
||||||
add_dependency(c->decl, e);
|
add_dependency(c->info, c->decl, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -300,7 +300,8 @@ struct CheckerInfo {
|
|||||||
BlockingMutex global_untyped_mutex;
|
BlockingMutex global_untyped_mutex;
|
||||||
BlockingMutex builtin_mutex;
|
BlockingMutex builtin_mutex;
|
||||||
|
|
||||||
// NOT recursive & Only used at the end of `check_proc_body`
|
// NOT recursive & only used at the end of `check_proc_body`
|
||||||
|
// and in `add_dependency`.
|
||||||
// This is a possible source of contention but probably not
|
// This is a possible source of contention but probably not
|
||||||
// too much of a problem in practice
|
// too much of a problem in practice
|
||||||
BlockingMutex deps_mutex;
|
BlockingMutex deps_mutex;
|
||||||
|
|||||||
+2
-2
@@ -115,8 +115,8 @@ enum ProcedureOptimizationMode : u32 {
|
|||||||
struct Entity {
|
struct Entity {
|
||||||
EntityKind kind;
|
EntityKind kind;
|
||||||
u64 id;
|
u64 id;
|
||||||
u64 flags;
|
std::atomic<u64> flags;
|
||||||
EntityState state;
|
std::atomic<EntityState> state;
|
||||||
Token token;
|
Token token;
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
Type * type;
|
Type * type;
|
||||||
|
|||||||
+1
-2
@@ -5018,10 +5018,9 @@ AstPackage *try_add_import_path(Parser *p, String const &path, String const &rel
|
|||||||
|
|
||||||
gb_global Rune illegal_import_runes[] = {
|
gb_global Rune illegal_import_runes[] = {
|
||||||
'"', '\'', '`',
|
'"', '\'', '`',
|
||||||
// ' ',
|
|
||||||
'\t', '\r', '\n', '\v', '\f',
|
'\t', '\r', '\n', '\v', '\f',
|
||||||
'\\', // NOTE(bill): Disallow windows style filepaths
|
'\\', // NOTE(bill): Disallow windows style filepaths
|
||||||
'!', '$', '%', '^', '&', '*', '(', ')', '=', '+',
|
'!', '$', '%', '^', '&', '*', '(', ')', '=',
|
||||||
'[', ']', '{', '}',
|
'[', ']', '{', '}',
|
||||||
';',
|
';',
|
||||||
':', // NOTE(bill): Disallow windows style absolute filepaths
|
':', // NOTE(bill): Disallow windows style absolute filepaths
|
||||||
|
|||||||
+3
-3
@@ -306,9 +306,9 @@ struct Type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(bill): These need to be at the end to not affect the unionized data
|
// NOTE(bill): These need to be at the end to not affect the unionized data
|
||||||
i64 cached_size;
|
std::atomic<i64> cached_size;
|
||||||
i64 cached_align;
|
std::atomic<i64> cached_align;
|
||||||
u32 flags; // TypeFlag
|
std::atomic<u32> flags; // TypeFlag
|
||||||
bool failure;
|
bool failure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user