diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..600d2d33badf45cc068e01d2e3c837e11c417bc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file diff --git a/Include/KernelInc/ExecutorInc/KrlExecutor.h b/Include/KernelInc/ExecutorInc/KrlExecutor.h index 69cb0f18c31ecfb002f47aac083f193548c4c398..9a0c578cc9e6b0c25675bd24bf839cd7f7504804 100644 --- a/Include/KernelInc/ExecutorInc/KrlExecutor.h +++ b/Include/KernelInc/ExecutorInc/KrlExecutor.h @@ -8,49 +8,64 @@ #include "KrlExecutorManage.h" +// 执行体状态 +// 初始状态 #define EXECUTOR_INIT_STATUS (0) +// 新建状态 #define EXECUTOR_NEW_STATUS (2) +// 运行状态 #define EXECUTOR_RUN_STATUS (4) +// 休眠状态 #define EXECUTOR_SLEEP_STATUS (8) +// 阻塞状态 #define EXECUTOR_BLOCK_STATUS (16) +// 等待状态 #define EXECUTOR_WAIT_STATUS (32) +// 死亡状态 #define EXECUTOR_DEAD_STATUS (64) +// 缓存状态 #define EXECUTOR_CACHE_STATUS (128) +// 执行体名称最大长度 #define EXNAME_CHARS_MAX (64) +// 执行体名称 typedef struct EXNAME { - Char* NamePtr; - Char NameArr[EXNAME_CHARS_MAX]; -}ExName; + Char *NamePtr; // 名称指针 + Char NameArr[EXNAME_CHARS_MAX]; // 名称字符数组 +} ExName; +// 执行体资源集合 typedef struct EXRESOURCEBOX { - ExecutorRes* Res; -}ExResourceBox; + ExecutorRes *Res; +} ExResourceBox; +// 执行体隶属关系 typedef struct EXAFFILIATION { - UInt CPUID; - UInt MNodeID; - ExecutorBox* ExecutorBoxPtr; - ExecutorNode* ExecutorNodePtr; + UInt CPUID; // CPU ID + UInt MNodeID; // machine node ID + ExecutorBox *ExecutorBoxPtr; // 执行组 + ExecutorNode *ExecutorNodePtr; // 执行节点 //User //Transfer //Group -}ExAffiliation; +} ExAffiliation; +// 线程头 typedef struct THREADHEAD { - UInt ThreadNR; - List ThreadLists; -}ThreadHead; + UInt ThreadNR; + List ThreadLists; +} ThreadHead; +// 线程集合 typedef struct THREADBOX { ELock Lock; - U64 Status; - U64 Flags; + U64 Status; + U64 Flags; UInt ThreadSumNR; ThreadHead NewHead; ThreadHead RunHead; @@ -59,50 +74,122 @@ typedef struct THREADBOX ThreadHead WaitHead; ThreadHead DeadHead; ThreadHead CacheHead; -}ThreadBox; +} ThreadBox; +// 执行体 typedef struct EXECUTOR { - List Lists; - ELock Lock; - U64 Status; - U64 Flags; - UInt Type; - UInt RunStatus; - ExName Name; - ExAffiliation Affiliation; - ThreadBox ExThreadBox; - VMS ExVMS; - ExResourceBox ResourceBox; - void* Priv; - void* Ext; -}Executor; - -private void ExNameInit(ExName* init); -private void ExResourceBoxInit(ExResourceBox* init); -private void ExAffiliationInit(ExAffiliation* init); -private void ThreadHeadInit(ThreadHead* init); -private void ThreadBoxInit(ThreadBox* init); -private void ExecutorInit(Executor* init); -private Executor* NewExecutor(); -private Bool DelExecutor(Executor* executor); -private Executor* KrlExCreateExecutorRealizeCore(Executor* executor); -private Executor* KrlExCreateExecutorRealize(); -public Executor* KrlExCreateExecutor(); -private Bool KrlExDestroyExecutorRealizeCore(Executor* executor); -private Bool KrlExDestroyExecutorRealize(Executor* executor); -public Bool KrlExDestroyExecutor(Executor* executor); -public Bool KrlExSetAffiliationExNode(Executor* executor, ExecutorNode* exnode); -public Bool KrlExSetAffiliationExBox(Executor* executor, ExecutorBox* exbox); -public Executor* KrlExGetCPUIdleExecutor(); -public Executor* KrlExGetCurrentRunExecutor(); -public Bool KrlExSetCurrentRunExecutor(Executor* executor); -private Bool KrlExThreadAddToThreadBoxHead(Executor* executor, ThreadBox* box, ThreadHead* head, Thread* thread); -private Bool KrlExThreadDelOnThreadBoxHead(Executor* executor, ThreadBox* box, ThreadHead* head, Thread* thread); -private Bool KrlExThreadDelOnExecutorRealizeCore(Executor* executor, Thread* thread); -private Bool KrlExThreadAddToExecutorRealizeCore(Executor* executor, Thread* thread); -private Bool KrlExThreadAddToExecutorRealize(Executor* executor, Thread* thread); -private Bool KrlExThreadDelOnExecutorRealize(Executor* executor, Thread* thread); -public Bool KrlExThreadDelOnExecutor(Executor* executor, Thread* thread); -public Bool KrlExThreadAddToExecutor(Executor* executor, Thread* thread); + List Lists; // 列表 + ELock Lock; // 锁 + U64 Status; // 状态 + U64 Flags; // 标志位 + UInt Type; // 类型 + UInt RunStatus; // 运行状态 + ExName Name; // 名称 + ExAffiliation Affiliation; // 隶属关系 + ThreadBox ExThreadBox; // 线程集合 + VMS ExVMS; // VMS + ExResourceBox ResourceBox; // 资源集合 + void *Priv; // 上一个 + void *Ext; // 下一个 +} Executor; + +// 执行体名称初始化 +// param@init 名称实例 +private +void ExNameInit(ExName *init); + +// 执行体资源集合初始化 +// param@init 实例 +private +void ExResourceBoxInit(ExResourceBox *init); + +// 执行隶属关系初始化 +// param@init 实例 +private +void ExAffiliationInit(ExAffiliation *init); + +// 线程头初始化 +// param@init 实例 +private +void ThreadHeadInit(ThreadHead *init); + +// 线程集合初始化 +// param@init 实例 +private +void ThreadBoxInit(ThreadBox *init); + +// 执行体初始化 +// param@init 实例 +private +void ExecutorInit(Executor *init); + +// 新建执行体 +// @return 执行体实例 +private +Executor *NewExecutor(); + +// 删除执行体 +// @param executor 执行体 +// @return 是否删除成功 +private +Bool DelExecutor(Executor *executor); + +// TODO +private +Executor *KrlExCreateExecutorRealizeCore(Executor *executor); + +private +Executor *KrlExCreateExecutorRealize(); + +public +Executor *KrlExCreateExecutor(); + +private +Bool KrlExDestroyExecutorRealizeCore(Executor *executor); + +private +Bool KrlExDestroyExecutorRealize(Executor *executor); + +public +Bool KrlExDestroyExecutor(Executor *executor); + +public +Bool KrlExSetAffiliationExNode(Executor *executor, ExecutorNode *exnode); + +public +Bool KrlExSetAffiliationExBox(Executor *executor, ExecutorBox *exbox); + +public +Executor *KrlExGetCPUIdleExecutor(); + +public +Executor *KrlExGetCurrentRunExecutor(); + +public +Bool KrlExSetCurrentRunExecutor(Executor *executor); + +private +Bool KrlExThreadAddToThreadBoxHead(Executor *executor, ThreadBox *box, ThreadHead *head, Thread *thread); + +private +Bool KrlExThreadDelOnThreadBoxHead(Executor *executor, ThreadBox *box, ThreadHead *head, Thread *thread); + +private +Bool KrlExThreadDelOnExecutorRealizeCore(Executor *executor, Thread *thread); + +private +Bool KrlExThreadAddToExecutorRealizeCore(Executor *executor, Thread *thread); + +private +Bool KrlExThreadAddToExecutorRealize(Executor *executor, Thread *thread); + +private +Bool KrlExThreadDelOnExecutorRealize(Executor *executor, Thread *thread); + +public +Bool KrlExThreadDelOnExecutor(Executor *executor, Thread *thread); + +public +Bool KrlExThreadAddToExecutor(Executor *executor, Thread *thread); #endif \ No newline at end of file diff --git a/Include/KernelInc/ExecutorInc/KrlExecutorManage.h b/Include/KernelInc/ExecutorInc/KrlExecutorManage.h index 7d28b81a49adc81ef16af60fe8b76deaa3a920d6..868a6ea72ae08739aa27c2423c5f815eb18ab52c 100644 --- a/Include/KernelInc/ExecutorInc/KrlExecutorManage.h +++ b/Include/KernelInc/ExecutorInc/KrlExecutorManage.h @@ -7,83 +7,125 @@ #define _KRLEXECUTORMANAGEHEAD #include "HalSync.h" #include "KrlExecutor.h" + +// 最大执行体个数 #define EXECUTORNODE_MAX (64) +// 执行体只读数据段 #define EXECUTORDATA_SECTION __attribute__((section(".executor.data"))) +// 定义全局执行体变量 #define DefinedExecutorData(vartype,varname) EXECUTORDATA_SECTION vartype varname +// 执行体锁 typedef struct ELOCK { SPinLock Locks; // SEM }ELock; +// 执行体头部信息 typedef struct EXECUTORHEAD { - UInt ExecutorNR; - List ExecutorLists; + UInt ExecutorNR; // TODO + List ExecutorLists; // 执行列表 }ExecutorHead; +// 执行体集合 typedef struct EXECUTORBOX { - ELock Lock; - U64 Status; - U64 Flags; - UInt ExecutorSumNR; - ExecutorHead NewHead; - ExecutorHead RunHead; - ExecutorHead SleepHead; - ExecutorHead BlockHead; - ExecutorHead WaitHead; - ExecutorHead DeadHead; - ExecutorHead CacheHead; + ELock Lock; // 锁 + U64 Status; // 状态 + U64 Flags; // 标志位 + UInt ExecutorSumNR; // TODO + ExecutorHead NewHead; // 新建状态执行体头部 + ExecutorHead RunHead; // 运行状态执行体头部 + ExecutorHead SleepHead; // 休眠状态执行体头部 + ExecutorHead BlockHead; // 阻塞状态执行体头部 + ExecutorHead WaitHead; // 等待状态执行体头部 + ExecutorHead DeadHead; // 死亡状态执行体头部 + ExecutorHead CacheHead; // 缓存状态执行体头部 }ExecutorBox; +// 执行体节点 typedef struct EXECUTORNODE { - ELock Lock; - U64 Status; - U64 Flags; - UInt ExecutorNR; - Executor* CurrRunExecutor; - Executor* CPUIdleExecutor; - ExecutorBox ExecutorBoxor; + ELock Lock; // 锁 + U64 Status; // 状态 + U64 Flags; // 标志位 + UInt ExecutorNR; // TODO + Executor* CurrRunExecutor; // 正在运行执行体 + Executor* CPUIdleExecutor; // CPU常驻执行体 + ExecutorBox ExecutorBoxor; // 执行体集合 }ExecutorNode; +// 执行体管理器 typedef struct GEXECUTORMANAGE { - ELock Lock; - U64 Status; - U64 Flags; - ExecutorNode* DefaultExecutorNode; - ExecutorNode* ExecutorNodePtrArr[EXECUTORNODE_MAX]; + ELock Lock; // 锁 + U64 Status; // 状态 + U64 Flags; // 标志位 + ExecutorNode* DefaultExecutorNode; // 默认执行节点 + ExecutorNode* ExecutorNodePtrArr[EXECUTORNODE_MAX]; // 执行体数组 }GExecutorManage; +// 定义全局执行体管理器 DefinedExecutorData(GExecutorManage, GExecutorManageData); +// 定义全局默认执行体 DefinedExecutorData(ExecutorNode, DefaultExecutorNode); +// 返回全局执行体管理器 KLINE GExecutorManage* KrlExGetGExecutorManageDataAddr() { return &GExecutorManageData; } +// 返回全局默认执行体 KLINE ExecutorNode* KrlExGetDefaultExecutorNodeAddr() { return &DefaultExecutorNode; } +// 锁初始化 +// @param init 实例 private void ELockInit(ELock* init); + +// 执行体头初始化 +// @param init 实例 private void ExecutorHeadInit(ExecutorHead* init); + +// 执行体集合初始化 +// @param init 实例 private void ExecutorBoxInit(ExecutorBox* init); + +// 执行体节点初始化 +// @param init 实例 private void ExecutorNodeInit(ExecutorNode* init); + +// 执行体管理器初始化 +// @param init 实例 private void GExecutorManageInit(GExecutorManage* init); + +// 加锁 +// @param lock 锁实例 public void KrlExLocked(ELock* lock); + +// 解锁 +// @param lock 锁实例 public void KrlExUnLock(ELock* lock); + +// TODO private Bool KrlExAddExecutorToExecutorHead(GExecutorManage* gexem, ExecutorNode* exnode, ExecutorBox* box, ExecutorHead* exhead, Executor* executor); + private Bool KrlExDefaultAddExecutorRealizeCore(GExecutorManage* gexem, ExecutorNode* exnode, Executor* executor); + private Bool KrlExDefaultAddExecutorRealize(Executor* executor); + public Bool KrlExDefaultAddExecutor(Executor* executor); + private Bool KrlExAddCPUIdleExecutorRealizeCore(GExecutorManage* gexem, ExecutorNode* exnode, Executor* executor); + private Bool KrlExAddCPUIdleExecutorRealize(Executor* executor); + public Bool KrlExAddCPUIdleExecutor(Executor* executor); + public Bool KrlExecutorManageInit(); #endif diff --git a/Include/KernelInc/ExecutorInc/KrlThread.h b/Include/KernelInc/ExecutorInc/KrlThread.h index e5deaf048a676d54a898c39498f29eac609d605b..f595d508ba690aa9286abc068fb494f4db91372e 100644 --- a/Include/KernelInc/ExecutorInc/KrlThread.h +++ b/Include/KernelInc/ExecutorInc/KrlThread.h @@ -6,116 +6,193 @@ #ifndef _KRLTHREADHEAD #define _KRLTHREADHEAD +// 线程栈大小 #define THREAD_KERNELSTACK_SIZE (0x2000) +// TODO #define THREAD_KERNELSTACK_PMSADNR (THREAD_KERNELSTACK_SIZE >> MSAD_PADR_SLBITS) +// 线程状态 +// 初始状态 #define THREAD_INIT_STATUS (0) +// 新建状态 #define THREAD_NEW_STATUS (2) +// 运行状态 #define THREAD_RUN_STATUS (4) +// 休眠状态 #define THREAD_SLEEP_STATUS (8) +// 阻塞状态 #define THREAD_BLOCK_STATUS (16) +// 等待状态 #define THREAD_WAIT_STATUS (32) +// 死亡状态 #define THREAD_DEAD_STATUS (64) +// 线程隶属关系 typedef struct TAFFILIATION { - UInt CPUID; - UInt MNodeID; - Executor* ExecutorPtr; - EWaitList WaitList; + UInt CPUID; // CPU ID + UInt MNodeID; // machine Node ID + Executor* ExecutorPtr; // 执行体指针 + EWaitList WaitList; // 等待列表 //User //Transfer //Group }TAffiliation; +// 线程上下文 typedef struct TCONTEXT { - Addr KrlStackAddr; - Addr KrlStackTop; - Size KrlStackSize; - PMSAD* KrlStackPmsad; - Addr FunStartAddr; - Addr NextStartAddr; - Addr NextStackAddr; - X64TSS* Tss; + Addr KrlStackAddr; // 栈地址 + Addr KrlStackTop; // 栈顶地址 + Size KrlStackSize; // 栈大小 + PMSAD* KrlStackPmsad; // TODO + Addr FunStartAddr; // 运行函数地址 + Addr NextStartAddr; // 下一个运行地址 + Addr NextStackAddr; // 下一个栈地址 + X64TSS* Tss; // TSS }TContext; +// 线程 typedef struct THREAD { - List Lists; - ELock Lock; - U64 Status; - U64 Flags; - U64 ID; - UInt RunStatus; - UInt RunMode; - TAffiliation Affiliation; - Transfer ThreadTransfer; - TContext ThreadContext; - void* Priv; - void* Ext; + List Lists; // 线程列表 + ELock Lock; // 锁 + U64 Status; // 状态 + U64 Flags; // 标志位 + U64 ID; // ID + UInt RunStatus; // 运行状态 + UInt RunMode; // 运行模式 + TAffiliation Affiliation; // 隶属关系 + Transfer ThreadTransfer; // 调度转移 + TContext ThreadContext; // 上下文 + void* Priv; // 前一个线程 + void* Ext; // 后一个线程 }Thread; +// 线程运行环境变量 typedef struct TRUNENV { - UInt Status; - UInt Flags; - Executor* AffiExecutor; - Addr RunStart; - U64 CPUMode; - UInt Authority; - UInt Priority; + UInt Status; // 状态 + UInt Flags; // 标志位 + Executor* AffiExecutor; // 隶属关系 + Addr RunStart; // 运行地址 + U64 CPUMode; // CPU模式 + UInt Authority; // 授权 + UInt Priority; // 优先级 }TRunEnv; +// 隶属关系初始化 +// @param init 实例 private void TAffiliationInit(TAffiliation* init); + +// 上下文初始化 +// @param init 实例 private void TContextInit(TContext* init); + +// 线程初始化 +// @param init 实例 private void ThreadInit(Thread* init); + +// 运行环境初始化 +// @param init 实例 public void TRunEnvInit(TRunEnv* init); + +// 删除线程 +// @param thread 线程 +// @return 是否删除成功 private Bool DelThread(Thread* thread); + +// 新建线程 +// @return 线程 private Thread* NewThread(); + +// TODO private Bool KrlExNewThreadKernelStack(Thread* thread); + private Bool KrlExDelThreadKernelStack(Thread* thread); + private Thread* KrlExCreateThreadRealizeCore(); + private Bool KrlExDestroyThreadRealizeCore(Thread* thread); + private Thread* KrlExCreateThreadRealize(); + private Bool KrlExDestroyThreadRealize(Thread* thread); + public Thread* KrlExCreateThread(); + public Bool KrlExDestroyThread(Thread* thread); + public Thread* KrlExGetCurrentThread(); + private Bool KrlExThreadInitKernelStackRealizeCore(Thread* thread, TRunEnv* env); + private Bool KrlExThreadInitKernelStackRealize(Thread* thread, TRunEnv* env); + public Bool KrlExThreadInitKernelStack(Thread* thread, TRunEnv* env); + private Bool KrlExThreadInitRunEnvRealizeCore(Thread* thread, TRunEnv* env); + private Bool KrlExThreadInitRunEnvRealize(Thread* thread, TRunEnv* env); + public Bool KrlExThreadInitRunEnv(Thread* thread, TRunEnv* env); + private Bool KrlExCreateThreadInitRunEnvRealizeCore(TRunEnv* env); + private Bool KrlExCreateThreadInitRunEnvRealize(TRunEnv* env); + public Bool KrlExCreateThreadInitRunEnv(TRunEnv* env); + private void KrlExAfterThreadDoTransfer(Thread* curr, Thread* next); + private Bool KrlExThreadDoTransferRealizeCore(Thread* curr, Thread* next); + private Bool KrlExThreadDoTransferRealize(Thread* curr, Thread* next); + public Bool KrlExThreadDoTransfer(Thread* curr, Thread* next); + private Bool KrlExThreadSetRunStatusRealizeCore(Thread* thread, UInt status); + private Bool KrlExThreadSetRunStatusRealize(Thread* thread, UInt status); + public Bool KrlExThreadSetRunStatus(Thread* thread, UInt status); + private Bool KrlExSetThreadStatusAndTransfer(Thread* thread, UInt status); + private Bool KrlExThreadWaitRealizeCore(Thread* thread); + private Bool KrlExThreadWaitRealize(Thread* thread); + public Bool KrlExThreadWait(Thread* thread); + private Bool KrlExThreadSleepRealizeCore(Thread* thread); + private Bool KrlExThreadSleepRealize(Thread* thread); + public Bool KrlExThreadSleep(Thread* thread); + private Bool KrlExThreadBlockRealizeCore(Thread* thread); + private Bool KrlExThreadBlockRealize(Thread* thread); + public Bool KrlExThreadBlock(Thread* thread); + private Bool KrlExThreadDeadRealizeCore(Thread* thread); + private Bool KrlExThreadDeadRealize(Thread* thread); + public Bool KrlExThreadDead(Thread* thread); + private Bool KrlExThreadRunRealizeCore(Thread* thread); + private Bool KrlExThreadRunRealize(Thread* thread); + public Bool KrlExThreadRun(Thread* thread); + private Bool KrlExThreadAwakenRealizeCore(Thread* thread); + private Bool KrlExThreadAwakenRealize(Thread* thread); + public Bool KrlExThreadAwaken(Thread* thread); #endif \ No newline at end of file diff --git a/Include/KernelInc/ExecutorInc/KrlTransfer.h b/Include/KernelInc/ExecutorInc/KrlTransfer.h index 421651cea48af78c6cdecb056611fec209f00422..9e741f60188aae9809832d34c2a35b572cc3f088 100644 --- a/Include/KernelInc/ExecutorInc/KrlTransfer.h +++ b/Include/KernelInc/ExecutorInc/KrlTransfer.h @@ -6,52 +6,61 @@ #ifndef _KRLTRANSFERHEAD #define _KRLTRANSFERHEAD +// TODO #define TRANSFER_NR_MAX (64) +// 需要调度 #define NEED_TRANSFER_STATUS (1) +// 不需要调度 #define NONEED_TRANSFER_STATUS (0) +// 全局调度节点 typedef struct TRANSFERNODE{}TransferNode; +// 调度转移关系 typedef struct TRANSFER { - List Lists; - UInt Status; - UInt Flags; - RBTree Node; - TransferNode* ParentNode; - Thread* Thread; + List Lists; // 列表 + UInt Status; // 状态 + UInt Flags; // 标志位 + RBTree Node; // 红黑树节点 + TransferNode* ParentNode; // 父节点 + Thread* Thread; // 线程 }Transfer; +// 转移节点 typedef struct TRANSFERNODE { - List Lists; - ELock Lock; - UInt Status; - UInt Flags; - UInt TransferNR; - List TransferLists; - RBRoot Root; - Transfer* CurrTransfer; - Transfer* CPUIdleTransfer; - void* Priv; - void* Ext; + List Lists; // 列表 + ELock Lock; // 锁 + UInt Status; // 状态 + UInt Flags; // 标志位 + UInt TransferNR; // TODO + List TransferLists; // 转移列表 + RBRoot Root; // 根节点 + Transfer* CurrTransfer; // 当前转移 + Transfer* CPUIdleTransfer; // CPU空闲转移 + void* Priv; // 上一个 + void* Ext; // 下一个 }TransferNode; +// 调度转移管理 typedef struct TRANSFERMANAGE { - ELock Lock; - UInt Status; - UInt Flags; - TransferNode DefaultTransferNode; - TransferNode* TransferNodeArr[TRANSFER_NR_MAX]; + ELock Lock; // 锁 + UInt Status; // 状态 + UInt Flags; // 标志位 + TransferNode DefaultTransferNode; // 默认转移节点 + TransferNode* TransferNodeArr[TRANSFER_NR_MAX]; // 转移节点数组 }TransferManage; +// 返回默认调度转移管理器 KLINE TransferManage* KrlTrGetTransferManageDataAddr() { return &TransferManageData; } +// 返回默认转移节点 KLINE TransferNode* KrlTrGetDefaultTransferNodeAddr() { TransferManage* tmd = NULL; @@ -60,6 +69,9 @@ KLINE TransferNode* KrlTrGetDefaultTransferNodeAddr() return &tmd->DefaultTransferNode; } +// 返回调度转移线程 +// @param transfer 调度转移 +// @return 线程 KLINE Thread* KrlTrGetThreadForTransfer(Transfer* transfer) { IF_NULL_RETURN_NULL(transfer); @@ -67,9 +79,18 @@ KLINE Thread* KrlTrGetThreadForTransfer(Transfer* transfer) return transfer->Thread; } +// 调度转移初始化 +// @param init 实例 private void TransferInit(Transfer* init); + +// 调度转移节点初始化 +// @param init 实例 private void TransferNodeInit(TransferNode* init); + +// 调度转移管理器初始化 +// @param init 实例 private void TransferManageInit(TransferManage* init); + private Bool KrlTransferDelRealizeCore(TransferNode* node, Transfer* transfer); private Bool KrlTransferAddRealizeCore(TransferNode* node, Transfer* transfer); private Bool KrlTransferDelDefaultRealize(Transfer* transfer);