소스 검색

Merge branch 'master' into bigint

Jeroen van Rijn 4 년 전
부모
커밋
3af078e941
10개의 변경된 파일187개의 추가작업 그리고 19개의 파일을 삭제
  1. 143 0
      core/sync/sync2/primitives_darwin.odin
  2. 15 0
      core/sync/sync2/primitives_linux.odin
  3. 2 2
      core/sync/sync2/primitives_pthreads.odin
  4. 7 4
      src/check_expr.cpp
  5. 6 1
      src/check_type.cpp
  6. 6 4
      src/checker.cpp
  7. 2 1
      src/checker.hpp
  8. 2 2
      src/entity.cpp
  9. 1 2
      src/parser.cpp
  10. 3 3
      src/types.cpp

+ 143 - 0
core/sync/sync2/primitives_darwin.odin

@@ -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) {
+}

+ 15 - 0
core/sync/sync2/primitives_linux.odin

@@ -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));
+}

+ 2 - 2
core/sync/sync2/primitives_pthreads.odin

@@ -139,7 +139,7 @@ _recursive_mutex_lock :: 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);
 	m.impl.recursion -= 1;
 	recursion := m.impl.recursion;
@@ -154,7 +154,7 @@ _recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
 }
 
 _recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
-	tid := runtime.current_thread_id();
+	tid := _current_thread_id();
 	if m.impl.owner == tid {
 		return mutex_try_lock(&m.impl.mutex);
 	}

+ 7 - 4
src/check_expr.cpp

@@ -923,7 +923,7 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
 					poly->kind = Type_EnumeratedArray;
 					poly->cached_size  = -1;
 					poly->cached_align = -1;
-					poly->flags        = source->flags;
+					poly->flags.exchange(source->flags);
 					poly->failure      = false;
 					poly->EnumeratedArray.elem      = source->EnumeratedArray.elem;
 					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) {
-	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++) {
 			Entity *e = lhs[tuple_index + j];
 			if (e != nullptr) {
 				DeclInfo *decl = decl_info_of_entity(e);
 				if (decl != nullptr) {
-					c->decl = decl; // will be reset by the 'defer' any way
 					for_array(k, decl->deps.entries) {
 						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;
 }

+ 6 - 1
src/check_type.cpp

@@ -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);
 			add_entity(ctx, ctx->scope, name, 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;
 		}

+ 6 - 4
src/checker.cpp

@@ -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);
+	mutex_unlock(&info->deps_mutex);
 }
 void add_type_info_dependency(DeclInfo *d, Type *type) {
 	if (d == nullptr) {
-		// GB_ASSERT(type == t_invalid);
 		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);
 }
 
@@ -657,7 +659,7 @@ void add_package_dependency(CheckerContext *c, char const *package_name, char co
 	e->flags |= EntityFlag_Used;
 	GB_ASSERT_MSG(e != nullptr, "%s", name);
 	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) {
@@ -665,7 +667,7 @@ void add_declaration_dependency(CheckerContext *c, Entity *e) {
 		return;
 	}
 	if (c->decl != nullptr) {
-		add_dependency(c->decl, e);
+		add_dependency(c->info, c->decl, e);
 	}
 }
 

+ 2 - 1
src/checker.hpp

@@ -300,7 +300,8 @@ struct CheckerInfo {
 	BlockingMutex global_untyped_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
 	// too much of a problem in practice
 	BlockingMutex deps_mutex;

+ 2 - 2
src/entity.cpp

@@ -115,8 +115,8 @@ enum ProcedureOptimizationMode : u32 {
 struct Entity {
 	EntityKind  kind;
 	u64         id;
-	u64         flags;
-	EntityState state;
+	std::atomic<u64>         flags;
+	std::atomic<EntityState> state;
 	Token       token;
 	Scope *     scope;
 	Type *      type;

+ 1 - 2
src/parser.cpp

@@ -5018,10 +5018,9 @@ AstPackage *try_add_import_path(Parser *p, String const &path, String const &rel
 
 gb_global Rune illegal_import_runes[] = {
 	'"', '\'', '`',
-	// ' ',
 	'\t', '\r', '\n', '\v', '\f',
 	'\\', // NOTE(bill): Disallow windows style filepaths
-	'!', '$', '%', '^', '&', '*', '(', ')', '=', '+',
+	'!', '$', '%', '^', '&', '*', '(', ')', '=',
 	'[', ']', '{', '}',
 	';',
 	':', // NOTE(bill): Disallow windows style absolute filepaths

+ 3 - 3
src/types.cpp

@@ -306,9 +306,9 @@ struct Type {
 	};
 
 	// NOTE(bill): These need to be at the end to not affect the unionized data
-	i64  cached_size;
-	i64  cached_align;
-	u32  flags; // TypeFlag
+	std::atomic<i64> cached_size;
+	std::atomic<i64> cached_align;
+	std::atomic<u32> flags; // TypeFlag
 	bool failure;
 };