浏览代码

started working on multithread support

Nicolas Cannasse 7 年之前
父节点
当前提交
e57154c2d0
共有 7 个文件被更改,包括 96 次插入58 次删除
  1. 3 6
      src/debugger.c
  2. 4 1
      src/hl.h
  3. 1 2
      src/hlmodule.h
  4. 16 23
      src/main.c
  5. 2 7
      src/module.c
  6. 29 0
      src/std/fun.c
  7. 41 19
      src/std/thread.c

+ 3 - 6
src/debugger.c

@@ -35,11 +35,11 @@ HL_API int hl_socket_recv( hl_socket *s, vbyte *buf, int pos, int len );
 HL_API void hl_sys_sleep( double t );
 HL_API int hl_thread_id();
 HL_API vdynamic **hl_debug_exc;
+HL_API void *hl_gc_thread_info();
 
 static hl_socket *debug_socket = NULL;
 static hl_socket *client_socket = NULL;
 static bool debugger_connected = false;
-static int main_thread_id = 0;
 
 #define send hl_send_data
 static void send( void *ptr, int size ) {
@@ -47,8 +47,8 @@ static void send( void *ptr, int size ) {
 }
 
 static void hl_debug_loop( hl_module *m ) {
-	void *stack_top = hl_module_stack_top();
 	void *dbg_addr = &hl_debug_exc;
+	void *inf_addr = hl_gc_thread_info();
 	int flags = 0;
 #	ifdef HL_64
 	flags |= 1;
@@ -60,11 +60,9 @@ static void hl_debug_loop( hl_module *m ) {
 		hl_socket *s = hl_socket_accept(debug_socket);
 		client_socket = s;
 		send("HLD0",4);
-		send(&flags,4);
-		send(&main_thread_id,4);
 		send(&m->globals_data,sizeof(void*));
+		send(&inf_addr,sizeof(void*));
 		send(&dbg_addr,sizeof(void*));
-		send(&stack_top,sizeof(void*));
 		send(&m->jit_code,sizeof(void*));
 		send(&m->codesize,4);
 		send(&m->code->types,sizeof(void*));
@@ -110,7 +108,6 @@ bool hl_module_debug( hl_module *m, int port, bool wait ) {
 	}
 	hl_add_root(&debug_socket);
 	hl_add_root(&client_socket);
-	main_thread_id = hl_thread_id();
 	debug_socket = s;
 	if( !hl_thread_start(hl_debug_loop, m, false) ) {
 		hl_socket_close(s);

+ 4 - 1
src/hl.h

@@ -575,6 +575,7 @@ HL_API vclosure *hl_make_fun_wrapper( vclosure *c, hl_type *to );
 HL_API void *hl_wrapper_call( void *value, void **args, vdynamic *ret );
 HL_API void *hl_dyn_call_obj( vdynamic *obj, hl_type *ft, int hfield, void **args, vdynamic *ret );
 HL_API vdynamic *hl_dyn_call( vclosure *c, vdynamic **args, int nargs );
+HL_API vdynamic *hl_dyn_call_safe( vclosure *c, vdynamic **args, int nargs, bool *isException );
 
 // ----------------------- THREADS --------------------------------------------------
 
@@ -583,7 +584,9 @@ typedef struct _hl_thread hl_thread;
 
 HL_API hl_thread *hl_thread_start( void *callback, void *param, bool withGC );
 HL_API hl_thread *hl_thread_current();
-HL_API bool hl_thread_pause( hl_thread *t, bool pause );
+HL_API void hl_register_thread( void *stack_top );
+HL_API void hl_unregister_thread();
+HL_API void *hl_gc_stack_top();
 
 // ----------------------- ALLOC --------------------------------------------------
 

+ 1 - 2
src/hlmodule.h

@@ -103,10 +103,9 @@ const uchar *hl_get_ustring( hl_code *c, int index );
 const char* hl_op_name( int op );
 
 hl_module *hl_module_alloc( hl_code *code );
-int hl_module_init( hl_module *m, void *stack_top );
+int hl_module_init( hl_module *m );
 void hl_module_free( hl_module *m );
 bool hl_module_debug( hl_module *m, int port, bool wait );
-void *hl_module_stack_top();
 
 jit_ctx *hl_jit_alloc();
 void hl_jit_free( jit_ctx *ctx );

+ 16 - 23
src/main.c

@@ -94,9 +94,10 @@ int main(int argc, pchar *argv[]) {
 	struct {
 		hl_code *code;
 		hl_module *m;
-		vdynamic *exc;
+		vdynamic *ret;
+		vclosure c;
 	} ctx;
-	hl_trap_ctx trap;
+	bool isExc = false;
 	int first_boot_arg = -1;
 	argv++;
 	argc--;
@@ -143,13 +144,14 @@ int main(int argc, pchar *argv[]) {
 #	endif
 	hl_global_init(&ctx);
 	hl_sys_init((void**)argv,argc,file);
+	hl_register_thread(&argc);
 	ctx.code = load_code(file);
 	if( ctx.code == NULL )
 		return 1;
 	ctx.m = hl_module_alloc(ctx.code);
 	if( ctx.m == NULL )
 		return 2;
-	if( !hl_module_init(ctx.m, &argc) )
+	if( !hl_module_init(ctx.m) )
 		return 3;
 	hl_code_free(ctx.code);
 	if( debug_port > 0 )
@@ -158,32 +160,23 @@ int main(int argc, pchar *argv[]) {
 		fprintf(stderr,"Could not start debugger on port %d",debug_port);
 		return 4;
 	}
-	hl_trap(trap, ctx.exc, on_exception);
-#	ifdef HL_VCC
-	__try {
-#	endif
-		vclosure c;
-		c.t = ctx.code->functions[ctx.m->functions_indexes[ctx.m->code->entrypoint]].type;
-		c.fun = ctx.m->functions_ptrs[ctx.m->code->entrypoint];
-		c.hasValue = 0;
-		hl_dyn_call(&c,NULL,0);
-#	ifdef HL_VCC
-	} __except( throw_handler(GetExceptionCode()) ) {}
-#	endif
-	hl_module_free(ctx.m);
-	hl_free(&ctx.code->alloc);
-	hl_global_free();
-	return 0;
-on_exception:
-	{
+	ctx.c.t = ctx.code->functions[ctx.m->functions_indexes[ctx.m->code->entrypoint]].type;
+	ctx.c.fun = ctx.m->functions_ptrs[ctx.m->code->entrypoint];
+	ctx.c.hasValue = 0;
+	ctx.ret = hl_dyn_call_safe(&ctx.c,NULL,0,&isExc);
+	if( isExc ) {
 		varray *a = hl_exception_stack();
 		int i;
-		uprintf(USTR("Uncaught exception: %s\n"), hl_to_string(ctx.exc));
+		uprintf(USTR("Uncaught exception: %s\n"), hl_to_string(ctx.ret));
 		for(i=0;i<a->size;i++)
 			uprintf(USTR("Called from %s\n"), hl_aptr(a,uchar*)[i]);
 		hl_debug_break();
+		hl_global_free();
+		return 1;
 	}
+	hl_module_free(ctx.m);
+	hl_free(&ctx.code->alloc);
 	hl_global_free();
-	return 1;
+	return 0;
 }
 

+ 2 - 7
src/module.c

@@ -30,11 +30,6 @@
 #endif
 
 static hl_module *cur_module;
-static void *stack_top;
-
-void *hl_module_stack_top() {
-	return stack_top;
-}
 
 static bool module_resolve_pos( void *addr, int *fidx, int *fpos ) {
 	int code_pos = ((int)(int_val)((unsigned char*)addr - (unsigned char*)cur_module->jit_code));
@@ -104,6 +99,7 @@ static uchar *module_resolve_symbol( void *addr, uchar *out, int *outSize ) {
 static int module_capture_stack( void **stack, int size ) {
 	void **stack_ptr = (void**)&stack;
 	void *stack_bottom = stack_ptr;
+	void *stack_top = hl_gc_stack_top();
 	int count = 0;
 	unsigned char *code = cur_module->jit_code;
 	int code_size = cur_module->codesize;
@@ -257,7 +253,7 @@ static void *resolve_library( const char *lib ) {
 	return h;
 }
 
-int hl_module_init( hl_module *m, void *stack_top_val ) {
+int hl_module_init( hl_module *m ) {
 	int i;
 	jit_ctx *ctx;
 	// RESET globals
@@ -371,7 +367,6 @@ int hl_module_init( hl_module *m, void *stack_top_val ) {
 		m->functions_ptrs[f->findex] = ((unsigned char*)m->jit_code) + ((int_val)m->functions_ptrs[f->findex]);
 	}
 	cur_module = m;
-	stack_top = stack_top_val;
 	hl_setup_exception(module_resolve_symbol, module_capture_stack);
 	hl_gc_set_dump_types(hl_module_types_dump);
 	hl_jit_free(ctx);

+ 29 - 0
src/std/fun.c

@@ -360,3 +360,32 @@ DEFINE_PRIM(_DYN, get_closure_value, _DYN);
 DEFINE_PRIM(_BOOL, fun_compare, _DYN _DYN);
 DEFINE_PRIM(_DYN, make_var_args, _FUN(_DYN,_ARR));
 DEFINE_PRIM(_DYN, call_method, _DYN _ARR);
+
+
+#ifdef HL_VCC
+static int throw_handler( int code ) {
+	switch( code ) {
+	case EXCEPTION_ACCESS_VIOLATION: hl_error("Access violation");
+	case EXCEPTION_STACK_OVERFLOW: hl_error("Stack overflow");
+	default: hl_error("Unknown runtime error");
+	}
+	return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
+HL_PRIM vdynamic *hl_dyn_call_safe( vclosure *c, vdynamic **args, int nargs, bool *isException ) {
+	hl_trap_ctx trap;
+	vdynamic *exc;
+	*isException = false;
+	hl_trap(trap, exc, on_exception);
+#	ifdef HL_VCC
+	__try {
+#	endif
+		return hl_dyn_call(c,args,nargs);
+#	ifdef HL_VCC
+	} __except( throw_handler(GetExceptionCode()) ) {}
+#	endif
+on_exception:
+	*isException = true;
+	return exc;
+}

+ 41 - 19
src/std/thread.c

@@ -48,8 +48,29 @@ HL_PRIM int hl_thread_id() {
 #	endif
 }
 
+typedef struct {
+	void (*callb)( void *);
+	void *param;
+} thread_start;
+
+static void gc_thread_entry( thread_start *_s ) {
+	thread_start s = *_s;
+	hl_register_thread(&s);
+	free(_s);
+	hl_remove_root(&_s->param);
+	s.callb(s.param);
+	hl_unregister_thread(&s);
+}
+
 HL_PRIM hl_thread *hl_thread_start( void *callback, void *param, bool withGC ) {
-	if( withGC ) hl_error("Threads with garbage collector are currently not supported");
+	if( withGC ) {
+		thread_start *s = (thread_start*)malloc(sizeof(thread_start));
+		s->callb = callback;
+		s->param = param;
+		hl_add_root(&s->param);
+		callback = gc_thread_entry;
+		param = s;
+	}
 #	ifdef HL_WIN
 	DWORD tid;
 	HANDLE h = CreateThread(NULL,0,callback,param,0,&tid);
@@ -71,22 +92,23 @@ HL_PRIM hl_thread *hl_thread_start( void *callback, void *param, bool withGC ) {
 #	endif
 }
 
-HL_PRIM bool hl_thread_pause( hl_thread *t, bool pause ) {
-#	ifdef HL_WIN
-	bool ret;
-	HANDLE h = OpenThread(THREAD_ALL_ACCESS,FALSE,(DWORD)(int_val)t);
-	if( pause )
-		ret = ((int)SuspendThread(h)) >= 0;
-	else {
-		int r;
-		while( (r = (int)ResumeThread(h)) > 0 ) {
-		}
-		ret = r == 0;
-	}
-	CloseHandle(h);
-	return ret;
-#	else
-	// TODO : use libthread_db
-	return false;
-#	endif
+static void hl_run_thread( vclosure *c ) {
+	bool isExc;
+	varray *a;
+	int i;
+	vdynamic *exc = hl_dyn_call_safe(c,NULL,0,&isExc);
+	if( !isExc )
+		return;
+	a = hl_exception_stack();
+	uprintf(USTR("Uncaught exception: %s\n"), hl_to_string(exc));
+	for(i=0;i<a->size;i++)
+		uprintf(USTR("Called from %s\n"), hl_aptr(a,uchar*)[i]);
 }
+
+HL_PRIM hl_thread *hl_thread_create( vclosure *c ) {
+	return hl_thread_start(hl_run_thread,c,true);
+}
+
+#define _THREAD _ABSTRACT(hl_thread)
+DEFINE_PRIM(_THREAD, thread_current, _NO_ARG);
+DEFINE_PRIM(_THREAD, thread_create, _FUN(_VOID,_NO_ARG));