Browse Source

refactor: gc守护器移动到runtime中

SongZihuan 3 năm trước cách đây
mục cha
commit
591234a92d

+ 2 - 1
include/core/env.h

@@ -98,10 +98,11 @@ AFUN_CORE_EXPORT void fprintfErrorInfoStdout(af_ErrorInfo *ei);
 AFUN_CORE_EXPORT void pushErrorBacktracking(FileLine line, FilePath file, char *note, af_ErrorInfo *ei);
 
 /* GuardianList 相关操作 */
-af_GuardianList **pushGuardianList(af_Object *obj, af_Object *func, af_GuardianList **pgl, af_Environment *env);
+AFUN_CORE_EXPORT af_GuardianList **pushGuardianList(af_Object *obj, af_Object *func, af_GuardianList **pgl, af_Environment *env);
 
 /* 环境变量 属性访问 */
 AFUN_CORE_EXPORT char *findEnvVarData(char *name, af_Environment *env);
+AFUN_CORE_EXPORT int32_t *findEnvVarNumber(char *name, af_Environment *env);
 
 /* 运行环境 属性访问 */
 AFUN_CORE_EXPORT char getPrefix(size_t name, af_Environment *env);

+ 4 - 4
include/core/func.h

@@ -73,10 +73,10 @@ AFUN_CORE_EXPORT af_ArgList **pushArgList(af_ArgList **base, af_ArgList *new);
 AFUN_CORE_EXPORT void pushFuncBody(af_FuncBody **base, af_FuncBody *body);
 
 /* FuncInfo 相关操作 */
-AFUN_CORE_EXPORT void makeCFuncBodyToFuncInfo(DLC_SYMBOL(callFuncBody) c_func, char **msg_type, af_FuncInfo *fi);
-AFUN_CORE_EXPORT void makeCodeFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi);
-AFUN_CORE_EXPORT void makeImportFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi);
-AFUN_CORE_EXPORT void makeDynamicFuncBodyToFuncInfo(af_FuncInfo *fi);
+AFUN_CORE_EXPORT af_FuncBody *makeCFuncBodyToFuncInfo(DLC_SYMBOL(callFuncBody) c_func, char **msg_type, af_FuncInfo *fi);
+AFUN_CORE_EXPORT af_FuncBody *makeCodeFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi);
+AFUN_CORE_EXPORT af_FuncBody *makeImportFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi);
+AFUN_CORE_EXPORT af_FuncBody *makeDynamicFuncBodyToFuncInfo(af_FuncInfo *fi);
 
 /* af_ArgCodeList 属性获取 */
 AFUN_CORE_EXPORT void *getArgCodeListData(af_ArgCodeList *acl);

+ 3 - 0
include/core/gc.h

@@ -40,4 +40,7 @@ AFUN_CORE_EXPORT void gc_delObjectReference(af_Object *obj, af_Environment *base
 AFUN_CORE_EXPORT void gc_delVarReference(af_Var *obj, af_Environment *base);
 AFUN_CORE_EXPORT void gc_delVarSpaceReference(af_VarSpace *obj, af_Environment *base);
 AFUN_CORE_EXPORT void gc_delVarListReference(af_VarList *vsl, af_Environment *base);
+
+/* gc 操控函数 : gc的启动由解释器完全管理 */
+AFUN_CORE_EXPORT af_GuardianList *gc_RunGC(af_Environment *env);
 #endif //AFUN_GC

+ 0 - 1
include/core/global_obj.h

@@ -4,5 +4,4 @@
 #include "object.h"
 
 AFUN_CORE_EXPORT af_Object *makeGlobalObject(af_Environment *env);
-AFUN_CORE_EXPORT af_Object *makeCycleObject(af_Environment *env);
 #endif //AFUN_GLOBAL_OBJ_H

+ 1 - 2
src/core/__gc.h

@@ -109,8 +109,7 @@ AFUN_CORE_NO_EXPORT void gc_delObjectData(struct af_ObjectData *obj, af_Environm
 AFUN_CORE_NO_EXPORT void gc_addObjectDataReference(af_ObjectData *obj, af_Environment *base);
 AFUN_CORE_NO_EXPORT void gc_delObjectDataReference(af_ObjectData *obj, af_Environment *base);
 
-/* gc 操控函数 : gc的启动由解释器完全管理 */
-AFUN_CORE_NO_EXPORT af_GuardianList *gc_RunGC(af_Environment *env);
+/* gc 操控函数 */
 AFUN_CORE_NO_EXPORT paf_GuardianList checkAllDestruct(af_Environment *env, paf_GuardianList pgl);
 AFUN_CORE_NO_EXPORT void gc_freeAllValueData(af_Environment *env);
 AFUN_CORE_NO_EXPORT void gc_freeAllValue(af_Environment *env);

+ 0 - 108
src/core/env.c

@@ -89,16 +89,6 @@ static void mp_NORMAL(af_Message *msg, bool is_top, af_Environment *env);
 static void mp_ERROR(af_Message *msg, bool is_top, af_Environment *env);
 static void mp_IMPORT(af_Message *msg, bool is_top, af_Environment *env);
 
-typedef struct guardian_GC_data guardian_GC_data;
-struct guardian_GC_data{
-    time_t last_time;
-};
-
-/* 内置守护器 */
-static bool checkSignal(int signum, char *sig, char *sigcfg, char *sigerr, char err[], af_Environment *env);
-static af_GuardianList *guardian_GC(char *type, bool is_guard, guardian_GC_data *data, af_Environment *env);
-static af_GuardianList *guardian_Signal(char *type, bool is_guard, void *data, af_Environment *env);
-
 /* 变量检查函数 */
 static bool isInfixFunc(af_Code *code, af_Environment *env);
 
@@ -830,78 +820,6 @@ static void mp_IMPORT(af_Message *msg, bool is_top, af_Environment *env) {
     freeImportInfo(ii, env);
 }
 
-static bool checkSignal(int signum, char *sig, char *sigcfg, char *sigerr, char err[], af_Environment *env) {
-    bool re = aFunGetSignal(signum);
-    if (!re)
-        return false;
-    int32_t *p_cfg = findEnvVarNumber(sigcfg, env);
-    int32_t cfg = 0;
-    if (p_cfg != NULL)
-        cfg = *p_cfg;
-
-    if (cfg == 0) {  // 诱发错误
-        strncat(err, sigerr, 218);
-        setEnvVarNumber(sig, 0, env);
-    } else if (cfg == 1) {  // 设置环境变量
-        setEnvVarNumber(sig, 1, env);
-    } else  // 忽略
-        setEnvVarNumber(sig, 0, env);
-
-    writeDebugLog(aFunCoreLogger, "Get %s as cfg %d", sig, cfg);
-    return true;
-}
-
-/*
- * 函数名: checkRunGC
- * 目标: 检查是否该运行gc, 若是则返回true并运行gc, 否则返回false
- */
-static af_GuardianList *guardian_GC(char *type, bool is_guard, guardian_GC_data *data, af_Environment *env) {
-    time_t now = clock();
-    if ((now - data->last_time) < 1 * CLOCKS_PER_SEC)  // 间隔 1s 再执行
-        return NULL;
-    data->last_time = now;
-
-    af_GuardianList *gl = NULL;
-    enum GcRunTime grt = getGcRun(env);
-    if (grt == grt_always || grt == grt_count && getGcCount(env) >= getGcMax(env)) {
-        GcCountToZero(env);  // 清零
-
-        gl = gc_RunGC(env);
-        if (gl != NULL)
-            writeDebugLog(aFunCoreLogger, "GC run destruct function");
-    }
-    return gl;
-}
-
-static af_GuardianList *guardian_Signal(char *type, bool is_guard, void *data, af_Environment *env) {
-    char error_msg[218] = {NUL};
-    checkSignal(SIGINT, ev_sigint, ev_sigint_cfg, SIGNAL_INT, error_msg, env);
-    checkSignal(SIGTERM, ev_sigterm, ev_sigterm_cfg, SIGNAL_TERM, error_msg, env);
-#if (defined SIGUSR1 && defined SIGUSR2)
-    checkSignal(SIGUSR1, ev_sigu1, ev_sigu1_cfg, SIGNAL_U1, error_msg, env);
-    checkSignal(SIGUSR2, ev_sigu2, ev_sigu2_cfg, SIGNAL_U2, error_msg, env);
-#endif
-
-    if (*error_msg != NUL) {
-        // error_msg 有内容写入, 需要处理
-        if (env->activity->msg_down != NULL) {
-            af_Message *msg;
-            if (EQ_STR("NORMAL", env->activity->msg_down->type)) {
-                msg = getFirstMessage(env);
-                gc_delReference(*(af_Object **)msg->msg, env);
-                freeMessage(msg);
-            } else if (EQ_STR("ERROR", env->activity->msg_down->type)) {
-                msg = getFirstMessage(env);
-                freeErrorInfo(*(af_ErrorInfo **) msg->msg, env);
-                freeMessage(msg);
-            }
-        }
-
-        pushMessageDown(makeERRORMessage(SIGNAL_EXCEPTION, error_msg, env), env);
-    }
-    return NULL;
-}
-
 af_Environment *makeEnvironment(enum GcRunTime grt) {
     af_Environment *env = calloc(1, sizeof(af_Environment));
 
@@ -957,12 +875,8 @@ af_Environment *makeEnvironment(enum GcRunTime grt) {
 
     makeVarToProtectVarSpace("global", 3, 3, 3, env->global, env);
 
-    af_Object *cycle = makeCycleObject(env);  // gc 使用的函数 TODO-szh 移动到 runtime-tool 上
-    makeVarToProtectVarSpace(mg_sys_cycle, 3, 3, 3, cycle, env);
-
     gc_delReference(env->protect, env);
     gc_delReference(env->global, env);
-    gc_delReference(cycle, env);
     return env;
 }
 
@@ -1035,28 +949,6 @@ af_Environment *deriveEnvironment(bool derive_tmp, bool derive_guardian, bool de
 
 void enableEnvironment(af_Environment *env) {
     env->status = core_normal;
-    if (!env->is_derive) {  // 派生 gc 线程
-        setVarSpaceProtect(NULL, env->protect, true);
-
-        af_Environment *gc_env = startRunThread(env, NULL, NULL, true,
-                                                true, false, true, false);
-
-        /* 设置守护器 */
-        DLC_SYMBOL(GuardianFunc) func1 = MAKE_SYMBOL(guardian_Signal, GuardianFunc);
-        addGuardian("SIGNAL", false, false, 0, func1, NULL, NULL, gc_env);
-        FREE_SYMBOL(func1);
-
-        DLC_SYMBOL(GuardianFunc) func2 = MAKE_SYMBOL(guardian_GC, GuardianFunc);
-        addGuardian("GC", true, false, sizeof(guardian_GC_data),
-                    func2, NULL, NULL, gc_env);
-        FREE_SYMBOL(func2);
-
-        gc_env->status = core_normal;  // 手动启动env
-        af_Code *bt1 = makeElementCode(mg_sys_cycle, NUL, 1, "gc.aun.sys");
-        af_Code *bt2 = makeBlockCode(curly, bt1, NUL, 1, "gc.aun.sys", NULL);
-        startRunThread_(gc_env, bt2, true);
-        env->gc_env = gc_env;
-    }
 }
 
 bool freeEnvironment(af_Environment *env) {

+ 16 - 8
src/core/func.c

@@ -182,20 +182,28 @@ void freeFuncInfo(af_FuncInfo *fi) {  // vsl是不释放的
     free(fi);
 }
 
-void makeCFuncBodyToFuncInfo(DLC_SYMBOL(callFuncBody) c_func, char **msg_type, af_FuncInfo *fi) {
-    pushFuncBody(&fi->body, makeCFuncBody(c_func, msg_type));
+af_FuncBody *makeCFuncBodyToFuncInfo(DLC_SYMBOL(callFuncBody) c_func, char **msg_type, af_FuncInfo *fi) {
+    af_FuncBody *fb = makeCFuncBody(c_func, msg_type);
+    pushFuncBody(&fi->body, fb);
+    return fb;
 }
 
-void makeCodeFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi) {
-    pushFuncBody(&fi->body, makeCodeFuncBody(code, free_code, msg_type));
+af_FuncBody *makeCodeFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi) {
+    af_FuncBody *fb = makeCodeFuncBody(code, free_code, msg_type);
+    pushFuncBody(&fi->body, fb);
+    return fb;
 }
 
-void makeImportFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi) {
-    pushFuncBody(&fi->body, makeImportFuncBody(code, free_code, msg_type));
+af_FuncBody *makeImportFuncBodyToFuncInfo(af_Code *code, bool free_code, char **msg_type, af_FuncInfo *fi) {
+    af_FuncBody *fb = makeImportFuncBody(code, free_code, msg_type);
+    pushFuncBody(&fi->body, fb);
+    return fb;
 }
 
-void makeDynamicFuncBodyToFuncInfo(af_FuncInfo *fi) {
-    pushFuncBody(&fi->body, makeDynamicFuncBody());
+af_FuncBody *makeDynamicFuncBodyToFuncInfo(af_FuncInfo *fi) {
+    af_FuncBody *fb = makeDynamicFuncBody();
+    pushFuncBody(&fi->body, fb);
+    return fb;
 }
 
 bool pushDynamicFuncBody(af_FuncBody *new, af_FuncBody *body) {

+ 0 - 4
src/core/gc.c

@@ -15,7 +15,6 @@ void gc_addObjectData(af_ObjectData *od, af_Environment *base){
         base->gc_factory->gc_ObjectData->gc.prev = od;
     od->gc.next = base->gc_factory->gc_ObjectData;
     base->gc_factory->gc_ObjectData = od;
-    GcCountAdd1(base);
     pthread_mutex_unlock(&base->gc_factory->mutex);
 }
 
@@ -58,7 +57,6 @@ void gc_addObject(af_Object *obj, af_Environment *base){
         base->gc_factory->gc_Object->gc.prev = obj;
     obj->gc.next = base->gc_factory->gc_Object;
     base->gc_factory->gc_Object = obj;
-    GcCountAdd1(base);
     pthread_mutex_unlock(&base->gc_factory->mutex);
 }
 
@@ -101,7 +99,6 @@ void gc_addVar(af_Var *var, af_Environment *base) {
         base->gc_factory->gc_Var->gc.prev = var;
     var->gc.next = base->gc_factory->gc_Var;
     base->gc_factory->gc_Var = var;
-    GcCountAdd1(base);
     pthread_mutex_unlock(&base->gc_factory->mutex);
 }
 
@@ -152,7 +149,6 @@ void gc_addVarSpace(af_VarSpace *vs, af_Environment *base){
         base->gc_factory->gc_VarSpace->gc.prev = vs;
     vs->gc.next = base->gc_factory->gc_VarSpace;
     base->gc_factory->gc_VarSpace = vs;
-    GcCountAdd1(base);
     pthread_mutex_unlock(&base->gc_factory->mutex);
 }
 

+ 0 - 106
src/core/global_obj.c

@@ -74,109 +74,3 @@ af_Object *makeGlobalObject(af_Environment *env) {
 
     return makeObject(global_id, true, api, true, NULL, true, NULL, env);
 }
-
-size_t getSizec_Cycle(char *id, af_Object *obj) {
-    return sizeof(af_VarList *);
-}
-
-void initDatac_Cycle(char *id, af_Object *obj, af_VarList **data, af_Environment *env) {
-    *data = pushProtectVarList(NULL, env);
-}
-
-void freeDatac_Cycle(char *id, af_Object *obj, af_VarList **data, af_Environment *env) {
-    freeAllVarSpaceList(*data);
-}
-
-typedef struct CycleMark CycleMark;
-struct CycleMark {
-    af_FuncInfo *fi;
-    af_FuncBody *body;
-};
-
-af_FuncBody *func_Cycle(af_CallFuncInfo *cfi, af_Environment *env) {  // 测试用函数
-    CycleMark *mark = cfi->mark;
-    cfi->body_next = mark->body;
-    pushMessageDown(makeNORMALMessage(getGlobal(env), env), env);
-    return NULL;
-}
-
-bool getInfoc_Cycle(char *id, af_Object *obj, af_FuncInfo **fi, af_Code *code, CycleMark *mark, af_Environment *env) {
-    mark->fi = makeFuncInfo(normal_scope, not_embedded, false, false, false);
-    *fi = mark->fi;
-    
-    DLC_SYMBOL(callFuncBody) func = MAKE_SYMBOL(func_Cycle, callFuncBody);
-    makeCFuncBodyToFuncInfo(func, NULL, mark->fi);  // 压入两个相同的 body
-    makeCFuncBodyToFuncInfo(func, NULL, mark->fi);
-    mark->body = mark->fi->body;
-    FREE_SYMBOL(func);
-    
-    return true;
-}
-
-bool getAclc_Cycle(char *id, af_Object *obj, af_ArgCodeList **acl, af_Code *code, CycleMark **mark, af_Environment *env) {
-    *acl = NULL;
-    *mark = calloc(1, sizeof(CycleMark));
-    return true;
-}
-
-bool getVslc_Cycle(char *id, af_Object *obj, af_VarList **vsl, CycleMark *mark, af_Environment *env) {
-    *vsl = *(af_VarList **)getObjectData(obj);
-    return true;
-}
-
-af_GcList *getGcListc_Cycle(char *id, af_Object *obj, void *data) {
-    af_GcList *gl = pushGcList(glt_vsl, *(af_VarList **)data, NULL);
-    return gl;
-}
-
-bool getAlc_Cycle(char *id, af_Object *obj, af_ArgList **al, af_ArgCodeList *acl, CycleMark *mark, af_Environment *env) {
-    *al = NULL;
-    return true;
-}
-
-void freeMarkc_Cycle(char *id, af_Object *obj, CycleMark *mark) {
-    free(mark);
-}
-
-af_Object *makeCycleObject(af_Environment *env) {
-    af_ObjectAPI *api = makeObjectAPI();
-    DLC_SYMBOL(objectAPIFunc) get_alc = MAKE_SYMBOL(getAclc_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) get_vsl = MAKE_SYMBOL(getVslc_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) get_al = MAKE_SYMBOL(getAlc_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) get_info = MAKE_SYMBOL(getInfoc_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) free_mark = MAKE_SYMBOL(freeMarkc_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) get_gl = MAKE_SYMBOL(getGcListc_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) get_size = MAKE_SYMBOL(getSizec_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) init_data = MAKE_SYMBOL(initDatac_Cycle, objectAPIFunc);
-    DLC_SYMBOL(objectAPIFunc) free_data = MAKE_SYMBOL(freeDatac_Cycle, objectAPIFunc);
-    if (addAPI(get_size, "obj_getDataSize", api) != 1)
-        return NULL;
-    if (addAPI(init_data, "obj_initData", api) != 1)
-        return NULL;
-    if (addAPI(free_data, "obj_destructData", api) != 1)
-        return NULL;
-    if (addAPI(get_alc, "obj_funcGetArgCodeList", api) != 1)
-        return NULL;
-    if (addAPI(get_vsl, "obj_funcGetVarList", api) != 1)
-        return NULL;
-    if (addAPI(get_al, "obj_funcGetArgList", api) != 1)
-        return NULL;
-    if (addAPI(get_info, "obj_funcGetInfo", api) != 1)
-        return NULL;
-    if (addAPI(free_mark, "obj_funcFreeMask", api) != 1)
-        return NULL;
-    if (addAPI(get_gl, "obj_getGcList", api) != 1)
-        return NULL;
-
-    FREE_SYMBOL(get_alc);
-    FREE_SYMBOL(get_vsl);
-    FREE_SYMBOL(get_al);
-    FREE_SYMBOL(get_info);
-    FREE_SYMBOL(free_mark);
-    FREE_SYMBOL(get_gl);
-    FREE_SYMBOL(get_size);
-    FREE_SYMBOL(init_data);
-    FREE_SYMBOL(free_data);
-
-    return makeObject("func", true, api, true, NULL, true, NULL, env);
-}

+ 6 - 0
src/runtime/__cycle_obj.h

@@ -0,0 +1,6 @@
+#ifndef AFUN___CYCLE_OBJ_H
+#define AFUN___CYCLE_OBJ_H
+#include "aFunlangExport.h"
+
+AFUN_LANG_NO_EXPORT af_Object *makeCycleObject(af_Environment *env);
+#endif //AFUN___CYCLE_OBJ_H

+ 104 - 0
src/runtime/aFunlang.c

@@ -1,6 +1,7 @@
 #include "aFunCore.h"
 #include "__aFunlang.h"
 #include "__env.h"
+#include "__cycle_obj.h"
 
 #ifdef aFunWIN32_NO_CYGWIN
 #include <io.h>
@@ -13,6 +14,16 @@
 static int runCode_(af_Parser *parser, int mode, FilePath save_path, af_Environment *env);
 static bool aFunInit_mark = false;
 
+typedef struct guardian_GC_data guardian_GC_data;
+struct guardian_GC_data{
+    time_t last_time;
+};
+
+/* 内置守护器 */
+static bool checkSignal(int signum, char *sig, char *sigcfg, char *sigerr, char err[], af_Environment *env);
+static af_GuardianList *guardian_GC(char *type, bool is_guard, guardian_GC_data *data, af_Environment *env);
+static af_GuardianList *guardian_Signal(char *type, bool is_guard, void *data, af_Environment *env);
+
 bool aFunInit(aFunInitInfo *info) {
     if (aFunInit_mark)
         return false;
@@ -61,6 +72,73 @@ void undefRunEnv(aFunRunInfo *run_env) {
 }
 
 
+static bool checkSignal(int signum, char *sig, char *sigcfg, char *sigerr, char err[], af_Environment *env) {
+    bool re = aFunGetSignal(signum);
+    if (!re)
+        return false;
+    int32_t *p_cfg = findEnvVarNumber(sigcfg, env);
+    int32_t cfg = 0;
+    if (p_cfg != NULL)
+        cfg = *p_cfg;
+
+    if (cfg == 0) {  // 诱发错误
+        strncat(err, sigerr, 218);
+        setEnvVarNumber(sig, 0, env);
+    } else if (cfg == 1) {  // 设置环境变量
+        setEnvVarNumber(sig, 1, env);
+    } else  // 忽略
+        setEnvVarNumber(sig, 0, env);
+
+    writeDebugLog(aFunCoreLogger, "Get %s as cfg %d", sig, cfg);
+    return true;
+}
+
+/*
+ * 函数名: checkRunGC
+ * 目标: 检查是否该运行gc, 若是则返回true并运行gc, 否则返回false
+ */
+static af_GuardianList *guardian_GC(char *type, bool is_guard, guardian_GC_data *data, af_Environment *env) {
+    time_t now = clock();
+    if ((now - data->last_time) < 1 * CLOCKS_PER_SEC)  // 间隔 1s 再执行
+        return NULL;
+    data->last_time = now;
+
+    af_GuardianList *gl = gc_RunGC(env);
+    if (gl != NULL)
+        writeDebugLog(aFunCoreLogger, "GC run destruct function");
+    return gl;
+}
+
+static af_GuardianList *guardian_Signal(char *type, bool is_guard, void *data, af_Environment *env) {
+    char error_msg[218] = {NUL};
+    checkSignal(SIGINT, ev_sigint, ev_sigint_cfg, SIGNAL_INT, error_msg, env);
+    checkSignal(SIGTERM, ev_sigterm, ev_sigterm_cfg, SIGNAL_TERM, error_msg, env);
+#if (defined SIGUSR1 && defined SIGUSR2)
+    checkSignal(SIGUSR1, ev_sigu1, ev_sigu1_cfg, SIGNAL_U1, error_msg, env);
+    checkSignal(SIGUSR2, ev_sigu2, ev_sigu2_cfg, SIGNAL_U2, error_msg, env);
+#endif
+
+    if (*error_msg != NUL) {
+        // error_msg 有内容写入, 需要处理
+        if (env->activity->msg_down != NULL) {
+            af_Message *msg;
+            if (EQ_STR("NORMAL", env->activity->msg_down->type)) {
+                msg = getFirstMessage(env);
+                gc_delReference(*(af_Object **)msg->msg, env);
+                freeMessage(msg);
+            } else if (EQ_STR("ERROR", env->activity->msg_down->type)) {
+                msg = getFirstMessage(env);
+                freeErrorInfo(*(af_ErrorInfo **) msg->msg, env);
+                freeMessage(msg);
+            }
+        }
+
+        pushMessageDown(makeERRORMessage(SIGNAL_EXCEPTION, error_msg, env), env);
+    }
+    return NULL;
+}
+
+
 af_Environment *creatAFunEnvironment(int argc, char **argv){
     if (!aFunInit_mark)
         return NULL;
@@ -89,7 +167,33 @@ af_Environment *creatAFunEnvironment(int argc, char **argv){
         }
     }
 
+    af_Object *cycle = makeCycleObject(env);  // gc 使用的函数
+    makeVarToProtectVarSpace(mg_sys_cycle, 3, 3, 3, cycle, env);
+    gc_delReference(cycle, env);
+
     enableEnvironment(env);
+    if (!env->is_derive) {  // 派生 gc 线程
+        setVarSpaceProtect(NULL, env->protect, true);
+
+        af_Environment *gc_env = startRunThread(env, NULL, NULL, true, true, false, true, false);
+
+        /* 设置守护器 */
+        DLC_SYMBOL(GuardianFunc) func1 = MAKE_SYMBOL(guardian_Signal, GuardianFunc);
+        addGuardian("SIGNAL", false, false, 0, func1, NULL, NULL, gc_env);
+        FREE_SYMBOL(func1);
+
+        DLC_SYMBOL(GuardianFunc) func2 = MAKE_SYMBOL(guardian_GC, GuardianFunc);
+        addGuardian("GC", true, false, sizeof(guardian_GC_data),
+                    func2, NULL, NULL, gc_env);
+        FREE_SYMBOL(func2);
+
+        gc_env->status = core_normal;  // 手动启动env
+        af_Code *bt1 = makeElementCode(mg_sys_cycle, NUL, 1, "gc.aun.sys");
+        af_Code *bt2 = makeBlockCode(curly, bt1, NUL, 1, "gc.aun.sys", NULL);
+        startRunThread_(gc_env, bt2, true);
+        env->gc_env = gc_env;
+    }
+
     return env;
 }
 

+ 106 - 0
src/runtime/cycle_obj.c

@@ -0,0 +1,106 @@
+#include "aFunlang.h"
+#include "__cycle_obj.h"
+
+size_t getSizec_Cycle(char *id, af_Object *obj) {
+    return sizeof(af_VarList *);
+}
+
+void initDatac_Cycle(char *id, af_Object *obj, af_VarList **data, af_Environment *env) {
+    *data = pushProtectVarList(NULL, env);
+}
+
+void freeDatac_Cycle(char *id, af_Object *obj, af_VarList **data, af_Environment *env) {
+    freeAllVarSpaceList(*data);
+}
+
+typedef struct CycleMark CycleMark;
+struct CycleMark {
+    af_FuncInfo *fi;
+    af_FuncBody *body;
+};
+
+af_FuncBody *func_Cycle(af_CallFuncInfo *cfi, af_Environment *env) {  // 测试用函数
+    CycleMark *mark = cfi->mark;
+    cfi->body_next = mark->body;
+    pushMessageDown(makeNORMALMessage(getGlobal(env), env), env);
+    return NULL;
+}
+
+bool getInfoc_Cycle(char *id, af_Object *obj, af_FuncInfo **fi, af_Code *code, CycleMark *mark, af_Environment *env) {
+    mark->fi = makeFuncInfo(normal_scope, not_embedded, false, false, false);
+    *fi = mark->fi;
+
+    DLC_SYMBOL(callFuncBody) func = MAKE_SYMBOL(func_Cycle, callFuncBody);
+    mark->body = makeCFuncBodyToFuncInfo(func, NULL, mark->fi);  // 压入两个相同的 body
+    FREE_SYMBOL(func);
+
+    return true;
+}
+
+bool getAclc_Cycle(char *id, af_Object *obj, af_ArgCodeList **acl, af_Code *code, CycleMark **mark, af_Environment *env) {
+    *acl = NULL;
+    *mark = calloc(1, sizeof(CycleMark));
+    return true;
+}
+
+bool getVslc_Cycle(char *id, af_Object *obj, af_VarList **vsl, CycleMark *mark, af_Environment *env) {
+    *vsl = *(af_VarList **)getObjectData(obj);
+    return true;
+}
+
+af_GcList *getGcListc_Cycle(char *id, af_Object *obj, void *data) {
+    af_GcList *gl = pushGcList(glt_vsl, *(af_VarList **)data, NULL);
+    return gl;
+}
+
+bool getAlc_Cycle(char *id, af_Object *obj, af_ArgList **al, af_ArgCodeList *acl, CycleMark *mark, af_Environment *env) {
+    *al = NULL;
+    return true;
+}
+
+void freeMarkc_Cycle(char *id, af_Object *obj, CycleMark *mark) {
+    free(mark);
+}
+
+af_Object *makeCycleObject(af_Environment *env) {
+    af_ObjectAPI *api = makeObjectAPI();
+    DLC_SYMBOL(objectAPIFunc) get_alc = MAKE_SYMBOL(getAclc_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) get_vsl = MAKE_SYMBOL(getVslc_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) get_al = MAKE_SYMBOL(getAlc_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) get_info = MAKE_SYMBOL(getInfoc_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) free_mark = MAKE_SYMBOL(freeMarkc_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) get_gl = MAKE_SYMBOL(getGcListc_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) get_size = MAKE_SYMBOL(getSizec_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) init_data = MAKE_SYMBOL(initDatac_Cycle, objectAPIFunc);
+    DLC_SYMBOL(objectAPIFunc) free_data = MAKE_SYMBOL(freeDatac_Cycle, objectAPIFunc);
+    if (addAPI(get_size, "obj_getDataSize", api) != 1)
+        return NULL;
+    if (addAPI(init_data, "obj_initData", api) != 1)
+        return NULL;
+    if (addAPI(free_data, "obj_destructData", api) != 1)
+        return NULL;
+    if (addAPI(get_alc, "obj_funcGetArgCodeList", api) != 1)
+        return NULL;
+    if (addAPI(get_vsl, "obj_funcGetVarList", api) != 1)
+        return NULL;
+    if (addAPI(get_al, "obj_funcGetArgList", api) != 1)
+        return NULL;
+    if (addAPI(get_info, "obj_funcGetInfo", api) != 1)
+        return NULL;
+    if (addAPI(free_mark, "obj_funcFreeMask", api) != 1)
+        return NULL;
+    if (addAPI(get_gl, "obj_getGcList", api) != 1)
+        return NULL;
+
+    FREE_SYMBOL(get_alc);
+    FREE_SYMBOL(get_vsl);
+    FREE_SYMBOL(get_al);
+    FREE_SYMBOL(get_info);
+    FREE_SYMBOL(free_mark);
+    FREE_SYMBOL(get_gl);
+    FREE_SYMBOL(get_size);
+    FREE_SYMBOL(init_data);
+    FREE_SYMBOL(free_data);
+
+    return makeObject("func", true, api, true, NULL, true, NULL, env);
+}

+ 9 - 9
test/src/run_code.c

@@ -1137,15 +1137,15 @@ INIT_ERROR:
         printf("popGuardian: %d\n\n", re);
     }
 
-    {
-        printf("TAG V: [Thread]\n");
-        af_Code *bt1 = makeElementCode("object", 0, 1, "Tagv.aun");
-
-        startRunThread(env, NULL, bt1, false, true, true, true, true);
-        runCodeFromMemory(bt1, 0, env);
-        freeAllCode(bt1);
-        printf("\n");
-    }
+//    {  // TODO-szh 设置 多线程 code 的释放模式
+//        printf("TAG V: [Thread]\n");
+//        af_Code *bt1 = makeElementCode("object", 0, 1, "Tagv.aun");
+//
+//        startRunThread(env, NULL, bt1, false, true, true, true, true);
+//        runCodeFromMemory(bt1, 0, env);
+//        freeAllCode(bt1);
+//        printf("\n");
+//    }
 
     // 错误用例