同步官方源码,对调度,任务模块有很大的调整

    百图画鸿蒙 + 百文说内核 + 百万注源码  => 挖透鸿蒙内核源码
    鸿蒙研究站 | http://weharmonyos.com (国内)
              | https://weharmony.github.io (国外)
    oschina | https://my.oschina.net/weharmony
    博客园 | https://www.cnblogs.com/weharmony/
    知乎 | https://www.zhihu.com/people/weharmonyos
    csdn | https://blog.csdn.net/kuangyufei
    51cto | https://harmonyos.51cto.com/column/34
    掘金 | https://juejin.cn/user/756888642000808
    公众号 | 鸿蒙研究站 (weharmonyos)
上级 4493e78c
......@@ -29,13 +29,14 @@
import("//build/lite/config/component/lite_component.gni")
import("//kernel/liteos_a/liteos.gni")
import("//third_party/mksh/mksh.gni")
group("mksh") {
deps = [ ":build_mksh" ]
}
copy("copy_mksh_src") {
sources = [ "$LITEOSTHIRDPARTY/mksh" ]
sources = MKSH_SRC_DIR
outputs = [ "$target_out_dir/mksh_build" ]
}
......
......@@ -29,13 +29,14 @@
import("//build/lite/config/component/lite_component.gni")
import("//kernel/liteos_a/liteos.gni")
import("//third_party/toybox/toybox.gni")
group("toybox") {
deps = [ ":build_toybox" ]
}
copy("copy_toybox_src") {
sources = [ "$LITEOSTHIRDPARTY/toybox" ]
sources = TOYBOX_SRC_DIR
outputs = [ "$target_out_dir/toybox_build" ]
}
......
......@@ -83,6 +83,7 @@
#include "los_memory_pri.h"
#include "los_printf_pri.h"
#include "los_task_pri.h"
#include "los_percpu_pri.h"
#include "los_hw_pri.h"
#ifdef LOSCFG_SAVE_EXCINFO
#include "los_excinfo_pri.h"
......@@ -108,10 +109,10 @@
#include "los_bitmap.h"
#include "los_process_pri.h"
#include "los_exc_pri.h"
#include "los_sched_pri.h"
#ifdef LOSCFG_FS_VFS
#include "console.h"
#endif
#ifdef LOSCFG_BLACKBOX
#include "los_blackbox.h"
#endif
......@@ -269,7 +270,7 @@ UINT32 OsArmSharedPageFault(UINT32 excType, ExcContext *frame, UINT32 far, UINT3
return LOS_ERRNO_VM_NOT_FOUND;
}
#if defined(LOSCFG_KERNEL_SMP) && defined(LOSCFG_DEBUG_VERSION)
BOOL irqEnable = !(LOS_SpinHeld(&g_taskSpin) && (OsPercpuGet()->taskLockCnt != 0));
BOOL irqEnable = !(LOS_SpinHeld(&g_taskSpin) && OsSchedIsLock());
if (irqEnable) {
ArchIrqEnable();
} else {
......@@ -632,9 +633,9 @@ STATIC VOID OsExcRestore(VOID)
g_intCount[currCpuID] = 0; //CPU对应的中断数量清0
g_curNestCount[currCpuID] = 0;
#ifdef LOSCFG_KERNEL_SMP
OsPercpuGet()->excFlag = CPU_RUNNING;
OsCpuStatusSet(CPU_RUNNING);
#endif
OsPercpuGet()->taskLockCnt = 0;
OsSchedLockSet(0);
}
///用户态异常处理函数
STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
......@@ -684,7 +685,7 @@ STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
SCHEDULER_UNLOCK(intSave);
/* Exception handling All operations should be kept prior to that operation */
OsExcRestore();
OsTaskToExit(runTask, OS_PRO_EXIT_OK);
OsRunningTaskToExit(runTask, OS_PRO_EXIT_OK);
} else {
SCHEDULER_UNLOCK(intSave);
......@@ -1081,28 +1082,7 @@ VOID OsDataAbortExcHandleEntry(ExcContext *excBufAddr)
#ifdef LOSCFG_KERNEL_SMP
#define EXC_WAIT_INTER 50U //异常等待间隔时间
#define EXC_WAIT_TIME 2000U //异常等待时间
//打印所有CPU的状态信息
STATIC VOID OsAllCpuStatusOutput(VOID)
{
UINT32 i;
for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
switch (g_percpu[i].excFlag) {
case CPU_RUNNING: //处于运行状态
PrintExcInfo("cpu%u is running.\n", i);
break;
case CPU_HALT: //处于停止状态
PrintExcInfo("cpu%u is halted.\n", i);
break;
case CPU_EXC: //处于异常接管状态
PrintExcInfo("cpu%u is in exc.\n", i);
break;
default:
break;
}
}
PrintExcInfo("The current handling the exception is cpu%u !\n", ArchCurrCpuid()); //当前正在处理异常的CPU是:
}
///等待所有CPU停止
STATIC VOID WaitAllCpuStop(UINT32 cpuID)
{
......@@ -1111,7 +1091,7 @@ STATIC VOID WaitAllCpuStop(UINT32 cpuID)
while (time < EXC_WAIT_TIME) {
for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
if ((i != cpuID) && (g_percpu[i].excFlag != CPU_HALT)) {
if ((i != cpuID) && !OsCpuStatusIsHalt(i)) {
LOS_Mdelay(EXC_WAIT_INTER);
time += EXC_WAIT_INTER;
break;
......@@ -1149,7 +1129,7 @@ STATIC VOID OsCheckAllCpuStatus(VOID)
UINT32 currCpuID = ArchCurrCpuid();
UINT32 ret, target;
OsPercpuGet()->excFlag = CPU_EXC; //CPU处于异常接管状态
OsCpuStatusSet(CPU_EXC);
LOCKDEP_CLEAR_LOCKS();
LOS_SpinLock(&g_excSerializerSpin);
......@@ -1257,15 +1237,15 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsPrintExcHead(UINT32 far)
STATIC VOID OsSysStateSave(UINT32 *intCount, UINT32 *lockCount)
{
*intCount = g_intCount[ArchCurrCpuid()];
*lockCount = OsPercpuGet()->taskLockCnt;
*lockCount = OsSchedLockCountGet();
g_intCount[ArchCurrCpuid()] = 0;
OsPercpuGet()->taskLockCnt = 0;
OsSchedLockSet(0);
}
STATIC VOID OsSysStateRestore(UINT32 intCount, UINT32 lockCount)
{
g_intCount[ArchCurrCpuid()] = intCount;
OsPercpuGet()->taskLockCnt = lockCount;
OsSchedLockSet(lockCount);
}
#endif
......@@ -1281,7 +1261,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAd
UINT32 lockCount;
#endif
/* Task scheduling is not allowed during exception handling */
OsPercpuGet()->taskLockCnt++;
OsSchedLock();
g_curNestCount[ArchCurrCpuid()]++;
......
......@@ -28,21 +28,12 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_FS_VFS_BLOCK_DEVICE)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchdev_driver.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchdev_register.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchdev_unregister.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchlib_cache.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchlib_read.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchlib_sem.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchlib_setup.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchlib_teardown.c",
"$LITEOSTHIRDPARTY/NuttX/drivers/bch/bchlib_write.c",
]
sources = NUTTX_DRIVERS_BCH_SRC_FILES
public_configs = [ ":public" ]
}
......
......@@ -28,15 +28,16 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_DRIVERS_VIDEO)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [ "$LITEOSTHIRDPARTY/NuttX/drivers/video/fb.c" ]
sources = NUTTX_DRIVERS_VIDEO_SRC_FILES
public_configs = [ ":public" ]
}
config("public") {
include_dirs = [ "$LITEOSTHIRDPARTY/NuttX/include/nuttx/video" ]
include_dirs = NUTTX_DRIVERS_VIDEO_INCLUDE_DIRS
}
......@@ -28,6 +28,7 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/FatFs/FatFs.gni")
module_switch = defined(LOSCFG_FS_FAT)
module_name = get_path_info(rebase_path("."), "name")
......@@ -38,12 +39,7 @@ kernel_module(module_name) {
"os_adapt/format.c",
]
sources += [
"$LITEOSTHIRDPARTY/FatFs/source/diskio.c",
"$LITEOSTHIRDPARTY/FatFs/source/ff.c",
"$LITEOSTHIRDPARTY/FatFs/source/ffsystem.c",
"$LITEOSTHIRDPARTY/FatFs/source/ffunicode.c",
]
sources += FATFS_SRC_FILES
include_dirs = [ "os_adapt" ]
......@@ -51,5 +47,5 @@ kernel_module(module_name) {
}
config("public") {
include_dirs = [ "$LITEOSTHIRDPARTY/FatFs/source" ]
include_dirs = FATFS_INCLUDE_DIRS
}
......@@ -28,6 +28,7 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/Linux_Kernel/Linux_Kernel.gni")
module_switch = defined(LOSCFG_FS_JFFS)
module_name = get_path_info(rebase_path("."), "name")
......@@ -37,35 +38,9 @@ kernel_module(module_name) {
"src/vfs_jffs2.c",
]
sources += [
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/background.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/build.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/compr.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/compr_rtime.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/compr_rubin.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/compr_zlib.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/debug.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/dir.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/erase.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/file.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/fs.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/gc.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/malloc.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/nodelist.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/nodemgmt.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/read.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/readinode.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/scan.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/summary.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/super.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/write.c",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2/writev.c",
]
sources += LINUX_KERNEL_FS_JFFS2_SRC_FILES
include_dirs = [
"$LITEOSTHIRDPARTY/Linux_Kernel/fs/jffs2",
"$LITEOSTHIRDPARTY/Linux_Kernel/fs",
]
include_dirs = LINUX_KERNEL_FS_JFFS2_INCLUDE_DIRS
public_configs = [ ":public" ]
}
......
......@@ -28,13 +28,10 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_FS_NFS)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"$LITEOSTHIRDPARTY/NuttX/fs/nfs/nfs_adapter.c",
"$LITEOSTHIRDPARTY/NuttX/fs/nfs/nfs_util.c",
"$LITEOSTHIRDPARTY/NuttX/fs/nfs/rpc_clnt.c",
]
sources = NUTTX_FS_NFS_SRC_FILES
}
......@@ -28,9 +28,10 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_FS_RAMFS)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [ "$LITEOSTHIRDPARTY/NuttX/fs/tmpfs/fs_tmpfs.c" ]
sources = NUTTX_FS_TMPFS_SRC_FILES
}
......@@ -28,12 +28,10 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_FS_ROMFS)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"$LITEOSTHIRDPARTY/NuttX/fs/romfs/fs_romfs.c",
"$LITEOSTHIRDPARTY/NuttX/fs/romfs/fs_romfsutil.c",
]
sources = NUTTX_FS_ROMFS_SRC_FILES
}
......@@ -28,11 +28,17 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_FS_VFS)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"$LITEOSTOPDIR/fs/vfs/epoll/fs_epoll.c",
"$LITEOSTOPDIR/fs/vfs/mount.c",
"$LITEOSTOPDIR/fs/vfs/path_cache.c",
"$LITEOSTOPDIR/fs/vfs/vnode.c",
"$LITEOSTOPDIR/fs/vfs/vnode_hash.c",
"operation/fullpath.c",
"operation/vfs_chattr.c",
"operation/vfs_check.c",
......@@ -51,65 +57,11 @@ kernel_module(module_name) {
"operation/vfs_writev.c",
"vfs_cmd/vfs_shellcmd.c",
]
sources += [
"$LITEOSTHIRDPARTY/NuttX/fs/dirent/fs_closedir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/dirent/fs_opendir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/dirent/fs_readdir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/dirent/fs_rewinddir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/dirent/fs_seekdir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/dirent/fs_telldir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_blockproxy.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_closeblockdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_findblockdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_openblockdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_registerblockdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_registerdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_unregisterblockdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/driver/fs_unregisterdriver.c",
"$LITEOSTHIRDPARTY/NuttX/fs/inode/fs_files.c",
"$LITEOSTHIRDPARTY/NuttX/fs/mount/fs_foreachmountpoint.c",
"$LITEOSTHIRDPARTY/NuttX/fs/mount/fs_mount.c",
"$LITEOSTHIRDPARTY/NuttX/fs/mount/fs_sync.c",
"$LITEOSTHIRDPARTY/NuttX/fs/mount/fs_umount.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_close.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_dup.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_dup2.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_dupfd.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_dupfd2.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_fcntl.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_fsync.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_getfilep.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_ioctl.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_link.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_lseek.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_lseek64.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_mkdir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_open.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_poll.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_pread.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_pread64.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_pwrite.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_pwrite64.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_read.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_readlink.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_rename.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_rmdir.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_select.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_sendfile.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_stat.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_statfs.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_symlink.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_truncate.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_truncate64.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_unlink.c",
"$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_write.c",
"$LITEOSTOPDIR/fs/vfs/epoll/fs_epoll.c",
"$LITEOSTOPDIR/fs/vfs/mount.c",
"$LITEOSTOPDIR/fs/vfs/path_cache.c",
"$LITEOSTOPDIR/fs/vfs/vnode.c",
"$LITEOSTOPDIR/fs/vfs/vnode_hash.c",
]
sources += NUTTX_FS_DIRENT_SRC_FILES
sources += NUTTX_FS_DRIVER_SRC_FILES
sources += NUTTX_FS_INODE_SRC_FILES
sources += NUTTX_FS_MOUNT_SRC_FILES
sources += NUTTX_FS_VFS_SRC_FILES
include_dirs = [
"$LITEOSTOPDIR/syscall",
......
......@@ -69,6 +69,9 @@
#ifdef LOSCFG_SECURITY_CAPABILITY
#include "capability_api.h"
#endif
#ifdef LOSCFG_KERNEL_DYNLOAD
#include "los_load_elf.h"
#endif
#include "los_swtmr_pri.h"
#include "los_vm_map.h"
#include "los_vm_phys.h"
......@@ -100,6 +103,50 @@ STATIC INLINE VOID OsInsertPCBToFreeList(LosProcessCB *processCB)
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;//timeID初始化值
LOS_ListTailInsert(&g_freeProcess, &processCB->pendList);//进程节点挂入g_freeProcess以分配给后续进程使用
}
VOID OsDeleteTaskFromProcess(LosTaskCB *taskCB)
{
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
LOS_ListDelete(&taskCB->threadList);
processCB->threadNumber--;
OsTaskInsertToRecycleList(taskCB);
}
UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB)
{
UINT32 intSave;
UINT16 numCount;
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
SCHEDULER_LOCK(intSave);
taskCB->processID = pid;
LOS_ListTailInsert(&(processCB->threadSiblingList), &(taskCB->threadList));
if (OsProcessIsUserMode(processCB)) {
taskCB->taskStatus |= OS_TASK_FLAG_USER_MODE;
if (processCB->threadNumber > 0) {
taskCB->basePrio = OS_TCB_FROM_TID(processCB->threadGroupID)->basePrio;
} else {
taskCB->basePrio = OS_USER_PROCESS_PRIORITY_HIGHEST;
}
} else {
taskCB->basePrio = OsCurrTaskGet()->basePrio;
}
#ifdef LOSCFG_KERNEL_VM
taskCB->archMmu = (UINTPTR)&processCB->vmSpace->archMmu;
#endif
if (!processCB->threadNumber) {
processCB->threadGroupID = taskCB->taskID;
}
processCB->threadNumber++;
numCount = processCB->threadCount;
processCB->threadCount++;
SCHEDULER_UNLOCK(intSave);
return numCount;
}
/**
* @brief 创建进程组
* @details
......@@ -381,11 +428,6 @@ STATIC VOID OsWaitCheckAndWakeParentProcess(LosProcessCB *parentCB, const LosPro
/*! 回收指定进程的资源 */
LITE_OS_SEC_TEXT VOID OsProcessResourcesToFree(LosProcessCB *processCB)
{
if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {//初始化和正在运行的进程,不用/能回收
PRINT_ERR("The process(%d) has no permission to release process(%d) resources!\n",// @note_thinking 此处应该直接 return回去吧 !
OsCurrProcessGet()->processID, processCB->processID);
}
#ifdef LOSCFG_KERNEL_VM
if (OsProcessIsUserMode(processCB)) {
(VOID)OsVmSpaceRegionFree(processCB->vmSpace);
......@@ -440,6 +482,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsRecycleZombiesProcess(LosProcessCB *childCB, Proc
OsExitProcessGroup(childCB, group);//退出进程组
LOS_ListDelete(&childCB->siblingList);//从父亲大人的子孙链表上摘除
if (childCB->processStatus & OS_PROCESS_STATUS_ZOMBIES) {//如果身上僵死状态的标签
OsDeleteTaskFromProcess(OS_TCB_FROM_TID(childCB->threadGroupID));
childCB->processStatus &= ~OS_PROCESS_STATUS_ZOMBIES;//去掉僵死标签
childCB->processStatus |= OS_PROCESS_FLAG_UNUSED;//贴上没使用标签,进程由进程池分配,进程退出后重新回到空闲进程池
}
......@@ -502,13 +545,10 @@ STATIC VOID OsChildProcessResourcesFree(const LosProcessCB *processCB)
}
/*! 一个进程的自然消亡过程,参数是当前运行的任务*/
STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
VOID OsProcessNaturalExit(LosProcessCB *processCB, UINT32 status)
{
LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID);//通过task找到所属PCB
LosProcessCB *parentCB = NULL;
LOS_ASSERT(processCB->processStatus & OS_PROCESS_STATUS_RUNNING);//断言必须为正在运行的进程
OsChildProcessResourcesFree(processCB);//释放孩子进程的资源
......@@ -533,7 +573,6 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
(VOID)OsKill(processCB->parentProcessID, SIGCHLD, OS_KERNEL_KILL_PERMISSION);//以内核权限发送SIGCHLD(子进程退出)信号.
#endif
LOS_ListHeadInsert(&g_processRecycleList, &processCB->pendList);//将进程通过其阻塞节点挂入全局进程回收链表
OsRunTaskToDelete(runTask);//删除正在运行的任务
return;
}
......@@ -693,13 +732,12 @@ UINT32 OsSetProcessName(LosProcessCB *processCB, const CHAR *name)
}
/*! 初始化PCB(进程控制块)*/
STATIC UINT32 OsInitPCB(LosProcessCB *processCB, UINT32 mode, UINT16 priority, const CHAR *name)
STATIC UINT32 OsInitPCB(LosProcessCB *processCB, UINT32 mode, const CHAR *name)
{
processCB->processMode = mode; //用户态进程还是内核态进程
processCB->processStatus = OS_PROCESS_STATUS_INIT; //进程初始状态
processCB->parentProcessID = OS_INVALID_VALUE; //爸爸进程,外面指定
processCB->threadGroupID = OS_INVALID_VALUE; //所属线程组
processCB->priority = priority; //进程优先级
processCB->umask = OS_PROCESS_DEFAULT_UMASK; //掩码
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;
......@@ -816,10 +854,10 @@ LITE_OS_SEC_TEXT INT32 LOS_GetGroupID(VOID)
}
/*! 进程创建初始化*/
STATIC UINT32 OsProcessCreateInit(LosProcessCB *processCB, UINT32 flags, const CHAR *name, UINT16 priority)
STATIC UINT32 OsProcessCreateInit(LosProcessCB *processCB, UINT32 flags, const CHAR *name)
{
ProcessGroup *group = NULL;
UINT32 ret = OsInitPCB(processCB, flags, priority, name);//初始化进程控制块
UINT32 ret = OsInitPCB(processCB, flags, name);
if (ret != LOS_OK) {
goto EXIT;
}
......@@ -861,7 +899,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
}
LosProcessCB *kerInitProcess = OS_PCB_FROM_PID(g_kernelInitProcess);//获取进程池中2号实体
ret = OsProcessCreateInit(kerInitProcess, OS_KERNEL_MODE, "KProcess", 0);//创建内核态祖宗进程
ret = OsProcessCreateInit(kerInitProcess, OS_KERNEL_MODE, "KProcess");//创建内核态祖宗进程
if (ret != LOS_OK) {
return ret;
}
......@@ -869,10 +907,9 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
kerInitProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;//去掉初始化标签
g_processGroup = kerInitProcess->group;//进程组ID就是2号进程本身
LOS_ListInit(&g_processGroup->groupList);//初始化进程组链表
OsCurrProcessSet(kerInitProcess);//设置为当前进程,注意当前进程是内核的视角,并不代表一旦设置就必须执行进程的任务.
LosProcessCB *idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess);//获取进程池中0号实体
ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, OS_TASK_PRIORITY_LOWEST, "KIdle");//创建内核态0号进程
ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, "KIdle");//创建内核态0号进程
if (ret != LOS_OK) {
return ret;
}
......@@ -886,12 +923,13 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
#ifdef LOSCFG_FS_VFS
idleProcess->files = kerInitProcess->files;//共享文件
#endif
idleProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;
ret = OsIdleTaskCreate();//创建cpu的idle任务,从此当前CPU OsPercpuGet()->idleTaskID 有了休息的地方.
if (ret != LOS_OK) {
return ret;
}
idleProcess->threadGroupID = OsPercpuGet()->idleTaskID;//设置进程的多线程组长
idleProcess->threadGroupID = OsGetIdleTaskId();
return LOS_OK;
}
......@@ -928,7 +966,7 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio)
}
/* user mode process can reduce the priority of itself */
if ((runProcess->processID == processCB->processID) && (prio > processCB->priority)) {//用户模式下进程阔以降低自己的优先级
if ((runProcess->processID == processCB->processID) && (prio > OsCurrTaskGet()->basePrio)) {
return TRUE;
}
......@@ -966,7 +1004,7 @@ LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio
}
#endif
needSched = OsSchedModifyProcessSchedParam(processCB, policy, prio);
needSched = OsSchedModifyProcessSchedParam(pid, policy, prio);
SCHEDULER_UNLOCK(intSave);//还锁
LOS_MpSchedule(OS_MP_CPU_ALL);//核间中断
......@@ -1012,7 +1050,6 @@ LITE_OS_SEC_TEXT INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio)
/// 接口封装 - 获取进程优先级 which:标识进程,进程组,用户
LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
{
LosProcessCB *processCB = NULL;
INT32 prio;
UINT32 intSave;
(VOID)which;
......@@ -1025,14 +1062,14 @@ LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
return -LOS_EINVAL;
}
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
SCHEDULER_LOCK(intSave);
processCB = OS_PCB_FROM_PID(pid);
if (OsProcessIsUnused(processCB)) {
prio = -LOS_ESRCH;
goto OUT;
}
prio = (INT32)processCB->priority;
prio = (INT32)OS_TCB_FROM_TID(processCB->threadGroupID)->basePrio;
OUT:
SCHEDULER_UNLOCK(intSave);
......@@ -1490,6 +1527,36 @@ STATIC VOID *OsUserInitStackAlloc(LosProcessCB *processCB, UINT32 *size)
return (VOID *)(UINTPTR)region->range.base;
}
#ifdef LOSCFG_KERNEL_DYNLOAD
LITE_OS_SEC_TEXT VOID OsExecProcessVmSpaceRestore(LosVmSpace *oldSpace)
{
LosProcessCB *processCB = OsCurrProcessGet();
LosTaskCB *runTask = OsCurrTaskGet();
processCB->vmSpace = oldSpace;
runTask->archMmu = (UINTPTR)&processCB->vmSpace->archMmu;
LOS_ArchMmuContextSwitch((LosArchMmu *)runTask->archMmu);
}
LITE_OS_SEC_TEXT LosVmSpace *OsExecProcessVmSpaceReplace(LosVmSpace *newSpace, UINTPTR stackBase, INT32 randomDevFD)
{
LosProcessCB *processCB = OsCurrProcessGet();
LosTaskCB *runTask = OsCurrTaskGet();
OsProcessThreadGroupDestroy();
OsTaskCBRecycleToFree();
LosVmSpace *oldSpace = processCB->vmSpace;
processCB->vmSpace = newSpace;
processCB->vmSpace->heapBase += OsGetRndOffset(randomDevFD);
processCB->vmSpace->heapNow = processCB->vmSpace->heapBase;
processCB->vmSpace->mapBase += OsGetRndOffset(randomDevFD);
processCB->vmSpace->mapSize = stackBase - processCB->vmSpace->mapBase;
runTask->archMmu = (UINTPTR)&processCB->vmSpace->archMmu;
LOS_ArchMmuContextSwitch((LosArchMmu *)runTask->archMmu);
return oldSpace;
}
/**
* @brief 进程的回收再利用,被LOS_DoExecveFile调用
* @param processCB
......@@ -1576,27 +1643,39 @@ LITE_OS_SEC_TEXT UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINT
SCHEDULER_UNLOCK(intSave);//解锁
return LOS_OK;
}
#endif
/// 用户进程开始初始化
STATIC UINT32 OsUserInitProcessStart(UINT32 processID, TSK_INIT_PARAM_S *param)
STATIC UINT32 OsUserInitProcessStart(LosProcessCB *processCB, TSK_INIT_PARAM_S *param)
{
UINT32 intSave;
UINT32 taskID;
INT32 ret;
taskID = OsCreateUserTask(processID, param);//创建一个用户态任务
UINT32 taskID = OsCreateUserTask(processCB->processID, param);
if (taskID == OS_INVALID_VALUE) {
return LOS_NOK;
}
ret = LOS_SetProcessPriority(processCB->processID, OS_PROCESS_USERINIT_PRIORITY);
if (ret != LOS_OK) {
PRINT_ERR("User init process set priority failed! ERROR:%d \n", ret);
goto EXIT;
}
SCHEDULER_LOCK(intSave);
processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;
SCHEDULER_UNLOCK(intSave);
ret = LOS_SetTaskScheduler(taskID, LOS_SCHED_RR, OS_TASK_PRIORITY_LOWEST);//调度器:设置为抢占式调度和最低任务优先级(31级)
if (ret != LOS_OK) {
PRINT_ERR("User init process set scheduler failed! ERROR:%d \n", ret);
SCHEDULER_LOCK(intSave);
(VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(taskID), OS_PRO_EXIT_OK, intSave);
return LOS_NOK;
goto EXIT;
}
return LOS_OK;
EXIT:
(VOID)LOS_TaskDelete(taskID);
return ret;
}
STATIC UINT32 OsLoadUserInit(LosProcessCB *processCB)
......@@ -1672,7 +1751,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
VOID *stack = NULL;
LosProcessCB *processCB = OS_PCB_FROM_PID(g_userInitProcess);
ret = OsProcessCreateInit(processCB, OS_USER_MODE, "Init", OS_PROCESS_USERINIT_PRIORITY);
ret = OsProcessCreateInit(processCB, OS_USER_MODE, "Init");
if (ret != LOS_OK) {
return ret;
}
......@@ -1693,7 +1772,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
param.userParam.userMapBase = (UINTPTR)stack;
param.userParam.userMapSize = size;
param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
ret = OsUserInitProcessStart(g_userInitProcess, &param);
ret = OsUserInitProcessStart(processCB, &param);
if (ret != LOS_OK) {
(VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize);
goto ERROR;
......@@ -1770,6 +1849,7 @@ STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR
LosTaskCB *childTaskCB = OS_TCB_FROM_TID(taskID);
childTaskCB->taskStatus = runTask->taskStatus;//任务状态先同步,注意这里是赋值操作. ...01101001
childTaskCB->basePrio = runTask->basePrio;
if (childTaskCB->taskStatus & OS_TASK_STATUS_RUNNING) {//因只能有一个运行的task,所以如果一样要改4号位
childTaskCB->taskStatus &= ~OS_TASK_STATUS_RUNNING;//将四号位清0 ,变成 ...01100001
} else {//非运行状态下会发生什么?
......@@ -1777,7 +1857,6 @@ STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR
LOS_Panic("Clone thread status not running error status: 0x%x\n", childTaskCB->taskStatus);
}
childTaskCB->taskStatus &= ~OS_TASK_STATUS_UNUSED;//干净的Task
childProcessCB->priority = OS_PROCESS_PRIORITY_LOWEST;//进程设为最低优先级
}
if (OsProcessIsUserMode(childProcessCB)) {//是否是用户进程
......@@ -1795,7 +1874,6 @@ STATIC UINT32 OsCopyParent(UINT32 flags, LosProcessCB *childProcessCB, LosProces
LosProcessCB *parentProcessCB = NULL;
SCHEDULER_LOCK(intSave);
childProcessCB->priority = runProcessCB->priority; //当前进程所处阶级
if (flags & CLONE_PARENT) { //这里指明 childProcessCB 和 runProcessCB 有同一个父亲,是兄弟关系
parentProcessCB = OS_PCB_FROM_PID(runProcessCB->parentProcessID);//找出当前进程的父亲大人
......@@ -1860,7 +1938,7 @@ STATIC UINT32 OsForkInitPCB(UINT32 flags, LosProcessCB *child, const CHAR *name,
UINT32 ret;
LosProcessCB *run = OsCurrProcessGet();//获取当前进程
ret = OsInitPCB(child, run->processMode, OS_PROCESS_PRIORITY_LOWEST, name);
ret = OsInitPCB(child, run->processMode, name);
if (ret != LOS_OK) {
return ret;
}
......@@ -1888,6 +1966,7 @@ STATIC UINT32 OsChildSetProcessGroupAndSched(LosProcessCB *child, LosProcessCB *
}
}
child->processStatus &= ~OS_PROCESS_STATUS_INIT;
OsSchedTaskEnQueue(OS_TCB_FROM_TID(child->threadGroupID));
SCHEDULER_UNLOCK(intSave);
......@@ -1927,7 +2006,7 @@ STATIC UINT32 OsCopyProcessResources(UINT32 flags, LosProcessCB *child, LosProce
/// 拷贝进程
STATIC INT32 OsCopyProcess(UINT32 flags, const CHAR *name, UINTPTR sp, UINT32 size)
{
UINT32 intSave, ret, processID;
UINT32 ret, processID;
LosProcessCB *run = OsCurrProcessGet();//获取当前进程
LosProcessCB *child = OsGetFreePCB();//从进程池中申请一个进程控制块,鸿蒙进程池默认64
......@@ -1959,8 +2038,7 @@ STATIC INT32 OsCopyProcess(UINT32 flags, const CHAR *name, UINTPTR sp, UINT32 si
return processID;
ERROR_TASK:
SCHEDULER_LOCK(intSave);
(VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(child->threadGroupID), OS_PRO_EXIT_OK, intSave);
(VOID)LOS_TaskDelete(child->threadGroupID);
ERROR_INIT:
OsDeInitPCB(child);
return -ret;
......@@ -2026,8 +2104,9 @@ LITE_OS_SEC_TEXT VOID LOS_Exit(INT32 status)
return;
}
SCHEDULER_UNLOCK(intSave);
OsTaskExitGroup((UINT32)status);//退出进程组
OsProcessExit(OsCurrTaskGet(), (UINT32)status);//进程退出
OsProcessThreadGroupDestroy();
OsRunningTaskToExit(OsCurrTaskGet(), OS_PRO_EXIT_OK);
}
......@@ -2091,17 +2170,77 @@ LITE_OS_SEC_TEXT UINT32 LOS_GetCurrProcessID(VOID)
return OsCurrProcessGet()->processID;
}
/// 按指定状态退出指定进程
LITE_OS_SEC_TEXT VOID OsProcessExit(LosTaskCB *runTask, INT32 status)
#ifdef LOSCFG_KERNEL_VM
STATIC VOID ThreadGroupActiveTaskKilled(LosTaskCB *taskCB)
{
UINT32 intSave;
LOS_ASSERT(runTask == OsCurrTaskGet());//只有当前进程才能调用这个函数,即进程最后的退出不假手他人
INT32 ret;
OsTaskResourcesToFree(runTask);//释放任务资源
OsProcessResourcesToFree(OsCurrProcessGet());//释放进程资源
taskCB->taskStatus |= OS_TASK_FLAG_EXIT_KILL;
#ifdef LOSCFG_KERNEL_SMP
/** The other core that the thread is running on and is currently running in a non-system call */
if (!taskCB->sig.sigIntLock && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
taskCB->signal = SIGNAL_KILL;
LOS_MpSchedule(taskCB->currCpu);
} else
#endif
{
ret = OsTaskKillUnsafe(taskCB->taskID, SIGKILL);
if (ret != LOS_OK) {
PRINT_ERR("pid %u exit, Exit task group %u kill %u failed! ERROR: %d\n",
taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, ret);
}
}
if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
LOS_ListInit(&taskCB->joinList);
}
ret = OsTaskJoinPendUnsafe(taskCB);
if (ret != LOS_OK) {
PRINT_ERR("pid %u exit, Exit task group %u to wait others task %u(0x%x) exit failed! ERROR: %d\n",
taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, taskCB->taskStatus, ret);
}
}
#endif
LITE_OS_SEC_TEXT VOID OsProcessThreadGroupDestroy(VOID)
{
#ifdef LOSCFG_KERNEL_VM
UINT32 intSave;
LosProcessCB *processCB = OsCurrProcessGet();
LosTaskCB *currTask = OsCurrTaskGet();
SCHEDULER_LOCK(intSave);
OsProcessNaturalExit(runTask, status);//进程自然退出
if ((processCB->processStatus & OS_PROCESS_FLAG_EXIT) || !OsProcessIsUserMode(processCB)) {
SCHEDULER_UNLOCK(intSave);
return;
}
processCB->processStatus |= OS_PROCESS_FLAG_EXIT;
processCB->threadGroupID = currTask->taskID;
LOS_DL_LIST *list = &processCB->threadSiblingList;
LOS_DL_LIST *head = list;
do {
LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList);
if ((OsTaskIsInactive(taskCB) ||
((taskCB->taskStatus & OS_TASK_STATUS_READY) && !taskCB->sig.sigIntLock)) &&
!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
OsInactiveTaskDelete(taskCB);
} else if (taskCB != currTask) {
ThreadGroupActiveTaskKilled(taskCB);
} else {
/* Skip the current task */
list = list->pstNext;
}
} while (head != list->pstNext);
SCHEDULER_UNLOCK(intSave);
LOS_ASSERT(processCB->threadNumber == 1);
#endif
return;
}
/// 获取系统支持的最大进程数目
LITE_OS_SEC_TEXT UINT32 LOS_GetSystemProcessMaximum(VOID)
......
......@@ -45,8 +45,6 @@ STATIC VOID OsSmpSecondaryInit(VOID *arg)
{
UNUSED(arg);
OsCurrProcessSet(OS_PCB_FROM_PID(OsGetKernelInitProcessID()));
#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
OsSwtmrInit();
#endif
......
此差异已折叠。
此差异已折叠。
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
......@@ -34,8 +34,6 @@
#include "los_base.h"
#include "los_hw_cpu.h"
#include "los_spinlock.h"
#include "los_sortlink_pri.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -44,38 +42,16 @@ extern "C" {
#endif /* __cplusplus */
#ifdef LOSCFG_KERNEL_SMP
/*! \enum
*/
typedef enum {
CPU_RUNNING = 0, ///< cpu is running | CPU正在运行状态
CPU_HALT, ///< cpu in the halt | CPU处于暂停状态
CPU_EXC ///< cpu in the exc | CPU处于异常状态
} ExcFlag;
#endif
/*! \struct 内核对cpu的描述, per-CPU变量是linux系统一个非常有趣的特性,它为系统中的每个处理器都分配了该变量的副本。
* 这样做的好处是,在多处理器系统中,当处理器操作属于它的变量副本时,不需要考虑与其他处理器的竞争的问题,
*/
typedef struct {
SortLinkAttribute taskSortLink; /*! task sort link | 挂等待和延时的任务,这些任务从任务就绪队列中来,等待最后CPU执行 */
SPIN_LOCK_S taskSortLinkSpin; ///< task sort link spin lock | 操作taskSortLink链表的自旋锁
SortLinkAttribute swtmrSortLink; ///< swtmr sort link | 挂还没到时间的定时器
SPIN_LOCK_S swtmrSortLinkSpin; ///< swtmr sort link spin lock |* 操作swtmrSortLink链表的自旋锁
UINT64 responseTime; ///< Response time for current nuclear Tick interrupts | 当前CPU核 Tick 中断的响应时间
UINT64 tickStartTime; ///< The time when the tick interrupt starts processing | 开始处理tick中断的时间
UINT32 responseID; ///< The response ID of the current nuclear TICK interrupt | 当前CPU核TICK中断的响应任务ID
UINTPTR runProcess; ///< The address of the process control block pointer to which the current kernel is running | 当前进程控制块地址
UINT32 idleTaskID; ///< idle task id | 每个CPU都有一个空闲任务 见于 OsIdleTaskCreate
UINT32 taskLockCnt; ///< task lock flag | 任务锁的数量,当 > 0 的时候,需要重新调度了
UINT32 swtmrHandlerQueue; ///< software timer timeout queue id | 软时钟超时队列句柄
UINT32 swtmrTaskID; ///< software timer task id | 软时钟任务ID
UINT32 schedFlag; ///< pending scheduler flag | 调度标识 INT_NO_RESCH INT_PEND_RESCH
#ifdef LOSCFG_KERNEL_SMP
UINT32 excFlag; ///< cpu halt or exc flag | cpu 停止或 异常 标志
UINT32 excFlag; /* cpu halt or exc flag */
#ifdef LOSCFG_KERNEL_SMP_CALL
LOS_DL_LIST funcLink; ///< mp function call link | 回调函数链表,由 LOS_MP_IPI_FUNC_CALL 触发
#endif
LOS_DL_LIST funcLink; /* mp function call link */
#endif
} Percpu;
......@@ -92,6 +68,19 @@ STATIC INLINE Percpu *OsPercpuGetByID(UINT32 cpuid)
return &g_percpu[cpuid];
}
STATIC INLINE UINT32 OsCpuStatusIsHalt(UINT16 cpuid)
{
return (OsPercpuGetByID(cpuid)->excFlag == CPU_HALT);
}
STATIC INLINE VOID OsCpuStatusSet(ExcFlag flag)
{
OsPercpuGet()->excFlag = flag;
}
VOID OsAllCpuStatusOutput(VOID);
#endif
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -84,10 +84,8 @@ typedef struct ProcessCB {
UINT32 processID; /**< Process ID = leader thread ID | 进程ID,由进程池分配,范围[0,64] */
UINT16 processStatus; /**< [15:4] Process Status; [3:0] The number of threads currently
running in the process | 这里设计很巧妙.用一个变量表示了两层逻辑 数量和状态,点赞! @note_good 从这里也可以看出一个进程可以有多个正在运行的任务*/
UINT16 priority; /**< Process priority | 进程优先级*/
UINT16 consoleID; /**< The console id of task belongs | 任务的控制台id归属 */
UINT16 processMode; /**< Kernel Mode:0; User Mode:1; | 模式指定为内核还是用户进程 */
UINT16 readyTaskNum; /**< The number of ready tasks in the current process */
UINT32 parentProcessID; /**< Parent process ID | 父进程ID*/
UINT32 exitCode; /**< Process exit status | 进程退出状态码*/
LOS_DL_LIST pendList; /**< Block list to which the process belongs | 进程所在的阻塞列表,进程因阻塞挂入相应的链表.*/
......@@ -154,7 +152,7 @@ typedef struct ProcessCB {
*
* The process is created but does not participate in scheduling.
*/
#define OS_PROCESS_STATUS_INIT 0x0010U ///< 进程初始状态
#define OS_PROCESS_STATUS_INIT OS_TASK_STATUS_INIT
/**
* @ingroup los_process
......@@ -162,7 +160,7 @@ typedef struct ProcessCB {
*
* The process is ready.
*/
#define OS_PROCESS_STATUS_READY 0x0020U ///< 进程就绪状态
#define OS_PROCESS_STATUS_READY OS_TASK_STATUS_READY
/**
* @ingroup los_process
......@@ -170,7 +168,7 @@ typedef struct ProcessCB {
*
* The process is running.
*/
#define OS_PROCESS_STATUS_RUNNING 0x0040U ///< 进程状态: 运行中...
#define OS_PROCESS_STATUS_RUNNING OS_TASK_STATUS_RUNNING
/**
* @ingroup los_process
......@@ -178,7 +176,7 @@ typedef struct ProcessCB {
*
* The process is pending
*/
#define OS_PROCESS_STATUS_PENDING 0x0080U ///< 进程状态: 挂起中... ,意思是进程还没开始,在等待其他条件成熟
#define OS_PROCESS_STATUS_PENDING (OS_TASK_STATUS_PENDING | OS_TASK_STATUS_DELAY | OS_TASK_STATUS_SUSPENDED)
/**
* @ingroup los_process
......@@ -186,23 +184,7 @@ typedef struct ProcessCB {
*
* The process is run out but the resources occupied by the process are not recovered.
*/
#define OS_PROCESS_STATUS_ZOMBIES 0x100U ///< 进程状态: 僵死
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The number of task currently running under the process, it only works with multiple cores.
*/
#define OS_PROCESS_RUNTASK_COUNT_MASK 0x000FU ///< 进程处于运行状态的数量掩码
//进程当前运行的任务数,它只适用于多个内核,这里注意 一个进程的多个任务是可以同时给多个内核运行的.
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process status mask.
*/
#define OS_PROCESS_STATUS_MASK 0xFFF0U ///< 进程状态掩码
#define OS_PROCESS_STATUS_ZOMBIES 0x0100U ///< 进程状态: 僵死
/**
* @ingroup los_process
......@@ -272,6 +254,11 @@ STATIC INLINE BOOL OsProcessIsDead(const LosProcessCB *processCB)//查下进程
return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_ZOMBIES)) != 0);
}
STATIC INLINE BOOL OsProcessIsInit(const LosProcessCB *processCB)
{
return (processCB->processStatus & OS_PROCESS_STATUS_INIT);
}
/**
* @ingroup los_process
* The highest priority of a kernel mode process.
......@@ -302,16 +289,6 @@ STATIC INLINE BOOL OsProcessIsDead(const LosProcessCB *processCB)//查下进程
*/
#define OS_PROCESS_USERINIT_PRIORITY 28 ///< 用户进程默认的优先级,28级好低啊
#define OS_GET_PROCESS_STATUS(status) ((UINT16)((UINT16)(status) & OS_PROCESS_STATUS_MASK))
/// 获取进程处于运行中的任务数量
#define OS_PROCESS_GET_RUNTASK_COUNT(status) ((UINT16)(((UINT16)(status)) & OS_PROCESS_RUNTASK_COUNT_MASK))
/// 进程运行中的任务数量加1
#define OS_PROCESS_RUNTASK_COUNT_ADD(status) ((UINT16)(((UINT16)(status)) & OS_PROCESS_STATUS_MASK) | \
((OS_PROCESS_GET_RUNTASK_COUNT(status) + 1) & OS_PROCESS_RUNTASK_COUNT_MASK))
/// 进程运行中的任务数量减1
#define OS_PROCESS_RUNTASK_COUNT_DEC(status) ((UINT16)(((UINT16)(status)) & OS_PROCESS_STATUS_MASK) | \
((OS_PROCESS_GET_RUNTASK_COUNT(status) - 1) & OS_PROCESS_RUNTASK_COUNT_MASK))
#define OS_TASK_DEFAULT_STACK_SIZE 0x2000 ///< task默认栈大小 8K
#define OS_USER_TASK_SYSCALL_STACK_SIZE 0x3000 ///< 用户通过系统调用的栈大小 12K ,这时是运行在内核模式下
#define OS_USER_TASK_STACK_SIZE 0x100000 ///< 用户任务运行在用户空间的栈大小 1M
......@@ -383,15 +360,10 @@ STATIC INLINE LosProcessCB *OsCurrProcessGet(VOID)
UINT32 intSave;
intSave = LOS_IntLock();
LosProcessCB *runProcess = (LosProcessCB *)OsPercpuGet()->runProcess;//当前CPU正在运行的进程
LosProcessCB *runProcess = OS_PCB_FROM_PID(OsCurrTaskGet()->processID);
LOS_IntRestore(intSave);
return runProcess;
}
/// 设置当前进程
STATIC INLINE VOID OsCurrProcessSet(const LosProcessCB *process)
{
OsPercpuGet()->runProcess = (UINTPTR)process;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
/*! 获取当前进程的所属用户 */
......@@ -405,8 +377,44 @@ STATIC INLINE User *OsCurrUserGet(VOID)
LOS_IntRestore(intSave);
return user;
}
STATIC INLINE UINT32 OsProcessUserIDGet(const LosTaskCB *taskCB)
{
UINT32 intSave = LOS_IntLock();
UINT32 uid = OS_INVALID;
LosProcessCB *process = OS_PCB_FROM_PID(taskCB->processID);
if (process->user != NULL) {
uid = process->user->userID;
}
LOS_IntRestore(intSave);
return uid;
}
#endif
STATIC INLINE UINT32 OsProcessThreadGroupIDGet(const LosTaskCB *taskCB)
{
return OS_PCB_FROM_PID(taskCB->processID)->threadGroupID;
}
STATIC INLINE UINT32 OsProcessThreadNumberGet(const LosTaskCB *taskCB)
{
return OS_PCB_FROM_PID(taskCB->processID)->threadNumber;
}
#ifdef LOSCFG_KERNEL_VM
STATIC INLINE LosVmSpace *OsProcessVmSpaceGet(const LosProcessCB *processCB)
{
return processCB->vmSpace;
}
#endif
#ifdef LOSCFG_DRIVERS_TZDRIVER
STATIC INLINE struct Vnode *OsProcessExecVnodeGet(const LosProcessCB *processCB)
{
return processCB->execVnode;
}
#endif
/*
* return immediately if no child has exited.
*/
......@@ -465,15 +473,14 @@ extern UINTPTR __user_init_bss; ///< 查看 LITE_USER_SEC_BSS ,赋值由liteos
extern UINTPTR __user_init_end; ///< init 进程的用户空间初始化结束地址
extern UINTPTR __user_init_load_addr;///< init进程的加载地址
extern UINT32 OsSystemProcessCreate(VOID);
extern VOID OsProcessNaturalExit(LosProcessCB *processCB, UINT32 status);
extern VOID OsProcessCBRecycleToFree(VOID);
extern VOID OsProcessResourcesToFree(LosProcessCB *processCB);
extern VOID OsProcessExit(LosTaskCB *runTask, INT32 status);
extern UINT32 OsUserInitProcess(VOID);
extern VOID OsTaskSchedQueueDequeue(LosTaskCB *taskCB, UINT16 status);
extern VOID OsTaskSchedQueueEnqueue(LosTaskCB *taskCB, UINT16 status);
extern INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size);
extern UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR *name,
LosVmSpace *oldAspace, UINTPTR oldFiles);
extern VOID OsExecProcessVmSpaceRestore(LosVmSpace *oldSpace);
extern LosVmSpace *OsExecProcessVmSpaceReplace(LosVmSpace *newSpace, UINTPTR stackBase, INT32 randomDevFD);
extern UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR *name, LosVmSpace *oldAspace, UINTPTR oldFiles);
extern UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBase, UINT32 mapSize);
extern UINT32 OsSetProcessName(LosProcessCB *processCB, const CHAR *name);
extern INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy);
......@@ -488,6 +495,9 @@ extern UINTPTR OsGetSigHandler(VOID);
extern VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID);
extern INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission);
extern INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission);
extern UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB);
extern VOID OsDeleteTaskFromProcess(LosTaskCB *taskCB);
extern VOID OsProcessThreadGroupDestroy(VOID);
#ifdef __cplusplus
#if __cplusplus
......
此差异已折叠。
......@@ -34,7 +34,7 @@
#include "los_typedef.h"
#include "los_list.h"
#include "los_sys_pri.h"
#include "los_spinlock.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -42,13 +42,6 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*! \enum SortLinkType
* @brief 因为任务和定时器都是吃CPU的,让CPU不停工作的主要就是这两宝贝.
*/
typedef enum {
OS_SORT_LINK_TASK = 1, ///< 任务
OS_SORT_LINK_SWTMR = 2, ///< 定时器
} SortLinkType;
/*! \struct SortLinkList
*
......@@ -67,6 +60,7 @@ typedef struct {
typedef struct {
LOS_DL_LIST sortLink; ///< 排序链表,上面挂的任务/软件定时器
UINT32 nodeNum; ///< 链表结点数量
SPIN_LOCK_S spinLock; /* swtmr sort link spin lock */
} SortLinkAttribute;
#define OS_SORT_LINK_INVALID_TIME ((UINT64)-1)
......@@ -97,11 +91,16 @@ STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader,
return listSorted->responseTime;
}
extern UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader);
extern VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type);
extern VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type);
extern UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList);
extern UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader);
STATIC INLINE UINT32 OsGetSortLinkNodeNum(SortLinkAttribute *head)
{
return head->nodeNum;
}
VOID OsSortLinkInit(SortLinkAttribute *sortLinkHeader);
VOID OsAdd2SortLink(SortLinkAttribute *head, SortLinkList *node, UINT64 responseTime, UINT16 idleCpu);
VOID OsDeleteFromSortLink(SortLinkAttribute *head, SortLinkList *node);
UINT64 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *targetSortList);
UINT64 OsSortLinkGetNextExpireTime(UINT64 currTime, const SortLinkAttribute *sortLinkHeader);
#ifdef __cplusplus
#if __cplusplus
......
......@@ -34,6 +34,7 @@
#include "los_swtmr.h"
#include "los_spinlock.h"
#include "los_sched_pri.h"
#ifdef LOSCFG_SECURITY_VID
#include "vid_api.h"
......@@ -75,7 +76,6 @@ typedef SwtmrHandlerItem *SwtmrHandlerItemPtr;
extern SWTMR_CTRL_S *g_swtmrCBArray;//软件定时器数组,后续统一注解为定时器池
extern SortLinkAttribute g_swtmrSortLink; /* The software timer count list */ //软件计时器计数链表
//通过参数ID找到对应定时器描述体
#define OS_SWT_FROM_SID(swtmrID) ((SWTMR_CTRL_S *)g_swtmrCBArray + ((swtmrID) % LOSCFG_BASE_CORE_SWTMR_LIMIT))
......@@ -100,11 +100,13 @@ extern SortLinkAttribute g_swtmrSortLink; /* The software timer count list */ //
* <ul><li>los_swtmr_pri.h: the header file that contains the API declaration.</li></ul>
* @see LOS_SwtmrStop
*/
extern VOID OsSwtmrScan(VOID);
extern BOOL OsIsSwtmrTask(const LosTaskCB *taskCB);
extern VOID OsSwtmrRestart(UINT64 startTime, SortLinkList *sortList);
extern VOID OsSwtmrWake(SchedRunQue *rq, UINT64 currTime, SortLinkList *sortList);
extern UINT32 OsSwtmrInit(VOID);
extern VOID OsSwtmrTask(VOID);
extern VOID OsSwtmrRecycle(UINT32 processID);
extern VOID OsSwtmrResponseTimeReset(UINT64 startTime);
extern BOOL OsSwtmrWorkQueueFind(SCHED_TL_FIND_FUNC checkFunc, UINTPTR arg);
extern SPIN_LOCK_S g_swtmrSpin;
#ifdef __cplusplus
#if __cplusplus
......
......@@ -33,20 +33,8 @@
#define _LOS_TASK_PRI_H
#include "los_task.h"
#include "los_percpu_pri.h"
#include "los_spinlock.h"
#ifdef LOSCFG_SCHED_DEBUG
#include "los_stat_pri.h"
#endif
#include "los_stackinfo_pri.h"
#include "los_futex_pri.h"
#include "los_signal.h"
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
#ifdef LOSCFG_KERNEL_LITEIPC
#include "hm_liteipc.h"
#endif
#include "los_sched_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
......@@ -79,112 +67,29 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*/
#define OS_TASK_ERRORID 0xFFFFFFFF
/**
* @ingroup los_task
* Define a usable task priority.
*
* Highest task priority.
*/
#define OS_TASK_PRIORITY_HIGHEST 0 //任务最高优先级,软时钟任务就是最高级任务,见于 OsSwtmrTaskCreate
/**
* @ingroup los_task
* Define a usable task priority.
*
* Lowest task priority.
*/
#define OS_TASK_PRIORITY_LOWEST 31 ///< 任务最低优先级
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is init.
*/
#define OS_TASK_STATUS_INIT 0x0001U ///< 初始化状态
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is ready.
*/
#define OS_TASK_STATUS_READY 0x0002U ///< 就绪状态的任务都将插入就绪队列,注意就绪队列的本质是个双向链表
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is running.
*/
#define OS_TASK_STATUS_RUNNING 0x0004U ///< 任务状态: 运行中
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is suspended.
*/
#define OS_TASK_STATUS_SUSPENDED 0x0008U ///< 任务状态: 暂停, 意思是发生了不需要等待资源的暂停,例如中断来了
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is blocked.
*/
#define OS_TASK_STATUS_PENDING 0x0010U ///< 任务状态: 挂起/待办 ,意思在需等待其他外在资源引起的停止,例如互斥锁/信号量 ==
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is delayed.
*/
#define OS_TASK_STATUS_DELAY 0x0020U ///< 延迟状态 ,例如 delay(100),因内部原因引起的等待 见于 OsSchedDelay 延期调度
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The time for waiting for an event to occur expires.
*/
#define OS_TASK_STATUS_TIMEOUT 0x0040U ///< 任务等待事件发生超时
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is pend for a period of time.
*/
#define OS_TASK_STATUS_PEND_TIME 0x0080U ///< 任务状态: 有时间限制的挂起/待办,例如等待某个事件时设置为时间到了就不等了
#define OS_TASK_STATUS_BLOCKED (OS_TASK_STATUS_INIT | OS_TASK_STATUS_PENDING | \
OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME) ///< 任务状态: 阻塞
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is exit.
* The task control block is unused.
*/
#define OS_TASK_STATUS_EXIT 0x0100U ///< 任务状态:退出
#define OS_TASK_STATUS_UNUSED 0x0200U ///< 任务状态:未使用
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task control block is unused.
* The task is joinable.
*/
#define OS_TASK_STATUS_UNUSED 0x0200U ///< 任务状态:未使用
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U ///< 主task和子task连在一块不分离
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is joinable.
* The task is user mode task.
*/
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U ///< 主task和子task连在一块不分离
#define OS_TASK_FLAG_USER_MODE 0x0800U
/**
* @ingroup los_task
......@@ -306,73 +211,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
#define OS_RESOURCE_EVENT_MASK 0xFF ///< 资源事件的掩码
#define OS_RESOURCE_EVENT_OOM 0x02 ///< 内存溢出事件
#define OS_RESOURCE_EVENT_FREE 0x04 ///< 资源释放事件
#define OS_TCB_NAME_LEN 32 ///< 任务名称长度上限
typedef struct {
VOID *stackPointer; /**< Task stack pointer | 内核栈指针位置(SP) */
UINT16 taskStatus; /**< Task status | 各种状态标签,可以拥有多种标签,按位标识 */
UINT16 priority; /**< Task priority | 任务优先级[0:31],默认是31级 */
UINT16 policy; ///< 任务的调度方式(三种 .. LOS_SCHED_RR LOS_SCHED_FIFO .. )
UINT64 startTime; /**< The start time of each phase of task | 任务开始时间 */
UINT64 irqStartTime; /**< Interrupt start time | 任务中断开始时间 */
UINT32 irqUsedTime; /**< Interrupt consumption time | 任务中断消耗时间 */
UINT32 initTimeSlice; /**< Task init time slice | 任务初始的时间片 */
INT32 timeSlice; /**< Task remaining time slice | 任务剩余时间片 */
UINT32 waitTimes; /**< Task delay time, tick number | 设置任务调度延期时间 */
SortLinkList sortList; /**< Task sortlink node | 跟CPU捆绑的任务排序链表节点,上面挂的是就绪队列的下一个阶段,进入CPU要执行的任务队列 */
UINT32 stackSize; /**< Task stack size | 内核态栈大小,内存来自内核空间 */
UINTPTR topOfStack; /**< Task stack top | 内核态栈顶 bottom = top + size */
UINT32 taskID; /**< Task ID | 任务ID,任务池本质是一个大数组,ID就是数组的索引,默认 < 128 */
TSK_ENTRY_FUNC taskEntry; /**< Task entrance function | 任务执行入口地址 */
VOID *joinRetval; /**< pthread adaption | 用来存储join线程的入口地址 */
VOID *taskMux; /**< Task-held mutex | task在等哪把锁 */
VOID *taskEvent; /**< Task-held event | task在等哪个事件 */
UINTPTR args[4]; /**< Parameter, of which the maximum number is 4 | 入口函数的参数 例如 main (int argc,char *argv[]) */
CHAR taskName[OS_TCB_NAME_LEN]; /**< Task name | 任务的名称 */
LOS_DL_LIST pendList; /**< Task pend node | 如果任务阻塞时就通过它挂到各种阻塞情况的链表上,比如OsTaskWait时 */
LOS_DL_LIST threadList; /**< thread list | 挂到所属进程的线程链表上 */
UINT32 eventMask; /**< Event mask | 任务对哪些事件进行屏蔽 */
UINT32 eventMode; /**< Event mode | 事件三种模式(LOS_WAITMODE_AND,LOS_WAITMODE_OR,LOS_WAITMODE_CLR) */
UINT32 priBitMap; /**< BitMap for recording the change of task priority,the priority can not be greater than 31
| 任务在执行过程中优先级会经常变化,这个变量用来记录所有曾经变化过的优先级,例如 ..01001011 曾经有过 0,1,3,6 优先级 */
#ifdef LOSCFG_KERNEL_CPUP
OsCpupBase taskCpup; /**< task cpu usage | CPU 使用统计 */
#endif
INT32 errorNo; /**< Error Num | 错误序号 */
UINT32 signal; /**< Task signal | 任务信号类型,(SIGNAL_NONE,SIGNAL_KILL,SIGNAL_SUSPEND,SIGNAL_AFFI) */
sig_cb sig; ///< 信号控制块,用于异步通信,类似于 linux singal模块
#ifdef LOSCFG_KERNEL_SMP
UINT16 currCpu; /**< CPU core number of this task is running on | 正在运行此任务的CPU内核号 */
UINT16 lastCpu; /**< CPU core number of this task is running on last time | 上次运行此任务的CPU内核号 */
UINT16 cpuAffiMask; /**< CPU affinity mask, support up to 16 cores | CPU亲和力掩码,最多支持16核,亲和力很重要,多核情况下尽量一个任务在一个CPU核上运行,提高效率 */
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC //多核情况下的任务同步开关,采用信号量实现
UINT32 syncSignal; /**< Synchronization for signal handling | 用于CPU之间同步信号量 */
#endif
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP //SMP死锁检测开关
LockDep lockDep; ///< 死锁依赖检测
#endif
#endif
#ifdef LOSCFG_SCHED_DEBUG //调试调度开关
SchedStat schedStat; /**< Schedule statistics | 调度统计 */
#endif
UINTPTR userArea; ///< 用户空间的堆区开始位置
UINTPTR userMapBase; ///< 用户空间的栈顶位置,内存来自用户空间,和topOfStack有本质的区别.
UINT32 userMapSize; /**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE | 用户栈大小 */
UINT32 processID; /**< Which belong process | 所属进程ID */
FutexNode futex; ///< 实现快锁功能
LOS_DL_LIST joinList; /**< join list | 联结链表,允许任务之间相互释放彼此 */
LOS_DL_LIST lockList; /**< Hold the lock list | 该链表上挂的都是已持有的锁 */
UINTPTR waitID; /**< Wait for the PID or GID of the child process | 等待子进程的PID或GID */
UINT16 waitFlag; /**< The type of child process that is waiting, belonging to a group or parent,
a specific child process, or any child process | 等待的子进程以什么样的方式结束(OS_TASK_WAIT_PROCESS | OS_TASK_WAIT_GID | ..) */
#ifdef LOSCFG_KERNEL_LITEIPC //轻量级进程间通信开关
IpcTaskInfo *ipcTaskInfo; ///< 任务间通讯信息结构体
#endif
#ifdef LOSCFG_KERNEL_PERF
UINTPTR pc; ///< pc寄存器
UINTPTR fp; ///< fp寄存器
#endif
} LosTaskCB;
///< LosTask结构体是给外部使用的
typedef struct {
LosTaskCB *runTask;
......@@ -414,21 +253,7 @@ typedef struct {//时间片结构体,任务轮询
UINT16 time; /**< Expiration time point | 到期时间点*/
UINT16 timeout; /**< Expiration duration | 有效期*/
} OsTaskRobin;
/// 获取当前CPU core运行的任务
STATIC INLINE LosTaskCB *OsCurrTaskGet(VOID)
{
return (LosTaskCB *)ArchCurrTaskGet();
}
/// 告诉协处理器当前任务使用范围为内核空间
STATIC INLINE VOID OsCurrTaskSet(LosTaskCB *task)
{
ArchCurrTaskSet(task);
}
/// 告诉协处理器当前任务使用范围为 用户空间
STATIC INLINE VOID OsCurrUserTaskSet(UINTPTR thread)
{
ArchCurrUserTaskSet(thread);
}
/// 通过任务ID获取任务实体,task由任务池分配,本质是个数组,彼此都挨在一块
STATIC INLINE LosTaskCB *OsGetTaskCB(UINT32 taskID)
{
......@@ -437,47 +262,17 @@ STATIC INLINE LosTaskCB *OsGetTaskCB(UINT32 taskID)
/// 任务是否在使用
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {//在freelist中的任务都是 OS_TASK_STATUS_UNUSED 状态
return TRUE;
}
return FALSE;
return ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED) != 0);
}
/// 任务是否在运行
STATIC INLINE BOOL OsTaskIsRunning(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {//一个CPU core 只能有一个 OS_TASK_STATUS_RUNNING task
return TRUE;
}
return FALSE;
}
/// 任务是否不再活跃
STATIC INLINE BOOL OsTaskIsInactive(const LosTaskCB *taskCB)
STATIC INLINE BOOL OsTaskIsKilled(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & (OS_TASK_STATUS_UNUSED | OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT)) {//三个标签有一个 代表不在活动
return TRUE;
}
return FALSE;
return ((taskCB->taskStatus & OS_TASK_FLAG_EXIT_KILL) != 0);
}
/// 任务是否挂起
STATIC INLINE BOOL OsTaskIsPending(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
return TRUE;
}
return FALSE;
}
/// 任务是否被干掉
STATIC INLINE BOOL OsTaskIsKilled(const LosTaskCB *taskCB)
STATIC INLINE BOOL OsTaskIsUserMode(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_FLAG_EXIT_KILL) {
return TRUE;
}
return FALSE;
return ((taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) != 0);
}
#define OS_TID_CHECK_INVALID(taskID) ((UINT32)(taskID) >= g_taskMaxNum)//是否有无效的任务 > 128
......@@ -529,23 +324,19 @@ extern LosTaskCB *OsGetMainTask(VOID);
extern VOID OsSetMainTask(VOID);
extern UINT32 OsGetIdleTaskId(VOID);
extern VOID OsTaskEntry(UINT32 taskID);
extern SortLinkAttribute *OsTaskSortLinkGet(VOID);
extern VOID OsTaskProcSignal(VOID);
extern UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UINT32 intSave);
extern VOID OsTaskResourcesToFree(LosTaskCB *taskCB);
extern VOID OsRunTaskToDelete(LosTaskCB *taskCB);
extern UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam);
extern INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName);
extern VOID OsTaskCBRecycleToFree(VOID);
extern VOID OsTaskExitGroup(UINT32 status);
extern VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status);
extern VOID OsExecDestroyTaskGroup(VOID);
extern VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status);
extern UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB);
extern UINT32 OsUserProcessOperatePermissionsCheck(LosTaskCB *taskCB, UINT32 processID);
extern INT32 OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info);
extern VOID OsWriteResourceEvent(UINT32 events);
extern VOID OsWriteResourceEventUnsafe(UINT32 events);
extern UINT32 OsResourceFreeTaskCreate(VOID);
extern VOID OsTaskInsertToRecycleList(LosTaskCB *taskCB);
extern VOID OsInactiveTaskDelete(LosTaskCB *taskCB);
#ifdef __cplusplus
#if __cplusplus
......
......@@ -653,18 +653,18 @@ STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const
SCHEDULER_LOCK(intSave);
OsTaskWaitSetPendMask(OS_TASK_WAIT_FUTEX, futexKey, timeOut);
OsSchedTaskWait(&(node->pendList), timeOut, FALSE);
OsPercpuGet()->taskLockCnt++;
OsSchedLock();
LOS_SpinUnlock(&g_taskSpin);
futexRet = OsFutexUnlock(&hashNode->listLock);
if (futexRet) {
OsPercpuGet()->taskLockCnt--;
OsSchedUnlock();
LOS_IntRestore(intSave);
goto EXIT_UNLOCK_ERR;
}
LOS_SpinLock(&g_taskSpin);
OsPercpuGet()->taskLockCnt--;
OsSchedUnlock();
/*
* it will immediately do the scheduling, so there's no need to release the
......
......@@ -737,8 +737,8 @@ VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
return sp;
}
if (task->taskStatus & OS_TASK_FLAG_EXIT_KILL) {
OsTaskToExit(task, 0);
if (OsTaskIsKilled(task)) {
OsRunningTaskToExit(task, 0);
return sp;
}
......
......@@ -112,7 +112,7 @@ LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdProcessMode(UINT16 mode)
return (UINT8 *)"ERROR";
}
/// 获取调度方式的名称
/// 获取调度方式的名?
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdSchedPolicy(UINT16 policy)
{
if (policy == LOS_SCHED_RR) {
......@@ -125,10 +125,9 @@ LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdSchedPolicy(UINT16 policy)
return (UINT8 *)"ERROR";
}
/// 获取状态名称
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellProcessStatus(UINT16 status)
{
status = status & OS_PROCESS_STATUS_MASK;
if (status & OS_PROCESS_STATUS_ZOMBIES) {
return (UINT8 *)"Zombies";
} else if (status & OS_PROCESS_STATUS_INIT) {
......@@ -137,11 +136,8 @@ LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellProcessStatus(UINT16 status)
return (UINT8 *)"Running";
} else if (status & OS_PROCESS_STATUS_READY) {
return (UINT8 *)"Ready";
} else if (status & OS_PROCESS_STATUS_PENDING) {
return (UINT8 *)"Pending";
}
return (UINT8 *)"Invalid";
return (UINT8 *)"Pending";
}
STATIC VOID OsShellCmdProcessTitle(VOID *seqBuf, UINT16 flag)
......@@ -189,7 +185,7 @@ STATIC VOID OsShellCmdProcessInfoShow(const LosProcessCB *processCB, const INT32
processCpup1s[pid].usage % LOS_CPUP_PRECISION_MULT);
#endif /* LOSCFG_KERNEL_CPUP */
PROCESS_INFO_SHOW(seqBuf, "%6s%9u%5d%10u%7s ",
OsShellCmdSchedPolicy(LOS_SCHED_RR), processCB->priority,
OsShellCmdSchedPolicy(LOS_SCHED_RR), OS_TCB_FROM_TID(processCB->threadGroupID)->basePrio,
(INT32)processCB->threadGroupID, processCB->threadNumber,
OsShellCmdProcessMode(processCB->processMode));
} else {
......@@ -246,17 +242,28 @@ STATIC VOID OsProcessMemUsageGet(UINT32 *memArray)
}
#endif
STATIC UINT32 OsProcessInfoGet(LosProcessCB **pcbArray, INT32 **group, UINT32 **memArray, UINT16 flag)
#define OS_TASK_STATUS_MASK 0x00FF
STATIC VOID OsProcessInfoGet(LosProcessCB **pcbArray, INT32 **group,
UINT32 **memArray, LosTaskCB **tcbArray,
UINT16 flag)
{
UINT32 len = OS_PROCESS_ALL_INFO_LEN;
LosProcessCB *processCB = NULL;
INT32 *user = NULL;
(VOID)memcpy_s(*pcbArray, OS_PROCESS_INFO_LEN, g_processCBArray, OS_PROCESS_INFO_LEN);
*group = (INT32 *)((UINTPTR)*pcbArray + OS_PROCESS_INFO_LEN);
user = (INT32 *)((UINTPTR)*group + OS_PROCESS_GROUP_INFO_LEN);
INT32 *user = (INT32 *)((UINTPTR)*group + OS_PROCESS_GROUP_INFO_LEN);
for (UINT32 tid = 0; tid < g_taskMaxNum; tid++) {
LosTaskCB *taskCB = *tcbArray + tid;
if (OsTaskIsUnused(taskCB)) {
continue;
}
LosProcessCB *processCB = *pcbArray + taskCB->processID;
if (!OsProcessIsDead(processCB) && !OsProcessIsInit(processCB)) {
processCB->processStatus |= (taskCB->taskStatus & OS_TASK_STATUS_MASK);
}
}
for (UINT32 pid = 0; pid < g_processMaxNum; ++pid) {
processCB = *pcbArray + pid;
LosProcessCB *processCB = *pcbArray + pid;
if (OsProcessIsUnused(processCB)) {
continue;
}
......@@ -295,11 +302,8 @@ STATIC UINT32 OsProcessInfoGet(LosProcessCB **pcbArray, INT32 **group, UINT32 **
if (flag & OS_PROCESS_MEM_INFO) {
*memArray = (UINT32 *)((UINTPTR)*pcbArray + OS_PROCESS_ALL_INFO_LEN);
OsProcessMemUsageGet(*memArray);
len += OS_PROCESS_MEM_ALL_INFO_LEN;
}
#endif
return len;
}
STATIC VOID OsShellCmdProcessInfoData(const LosProcessCB *pcbArray, const INT32 *group,
......@@ -322,23 +326,23 @@ STATIC VOID OsShellCmdProcessInfoData(const LosProcessCB *pcbArray, const INT32
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdConvertTskStatus(UINT16 taskStatus)
{
if (taskStatus & OS_TASK_STATUS_INIT) {//初始化
if (taskStatus & OS_TASK_STATUS_INIT) {//初始?
return (UINT8 *)"Init";
} else if (taskStatus & OS_TASK_STATUS_RUNNING) {//运行中
} else if (taskStatus & OS_TASK_STATUS_RUNNING) {//运行?
return (UINT8 *)"Running";
} else if (taskStatus & OS_TASK_STATUS_READY) {//已就绪
} else if (taskStatus & OS_TASK_STATUS_READY) {//已就?
return (UINT8 *)"Ready";
} else if (taskStatus & OS_TASK_STATUS_SUSPENDED) {//暂停
return (UINT8 *)"Suspended";
} else if (taskStatus & OS_TASK_STATUS_DELAY) {//延迟
return (UINT8 *)"Delay";
} else if (taskStatus & OS_TASK_STATUS_PENDING) {//挂起/待办
if (taskStatus & OS_TASK_STATUS_PEND_TIME) { //挂起/待办有时间限制
if (taskStatus & OS_TASK_STATUS_PEND_TIME) { //挂起/待办有时间限?
return (UINT8 *)"PendTime";
} else {
return (UINT8 *)"Pending";//挂起/待办无时间限制
return (UINT8 *)"Pending";//挂起/待办无时间限?
}
} else if (taskStatus & OS_TASK_STATUS_EXIT) {//退出
} else if (taskStatus & OS_TASK_STATUS_EXIT) {//退?
return (UINT8 *)"Exit";
}
......@@ -363,7 +367,7 @@ STATIC VOID OsShellCmdTaskWaterLineGet(const LosTaskCB *allTaskArray)
#ifdef LOSCFG_SHELL_CMD_DEBUG
#define OS_PEND_REASON_MAX_LEN 20
//shell检查任务等待标�?
//shell检查任务等待标?
STATIC CHAR *OsShellCheckTaskWaitFlag(const LosTaskCB *taskCB, UINTPTR *lockID)
{
*lockID = taskCB->waitID;
......@@ -522,16 +526,24 @@ STATIC VOID OsProcessAndTaskInfoGet(LosProcessCB **pcbArray, INT32 **group, LosT
{
BOOL lockFlag = FALSE;
UINT32 intSave = 0;
UINT32 processInfoLen;
UINT32 processInfoLen = OS_PROCESS_ALL_INFO_LEN;
if (LOS_SpinHeld(&g_taskSpin) == FALSE) {
SCHEDULER_LOCK(intSave);
lockFlag = TRUE;
}
processInfoLen = OsProcessInfoGet(pcbArray, group, memArray, flag);
#ifdef LOSCFG_KERNEL_VM
if (flag & OS_PROCESS_MEM_INFO) {
processInfoLen += OS_PROCESS_MEM_ALL_INFO_LEN;
}
#endif
(VOID)memcpy_s(*pcbArray, OS_PROCESS_INFO_LEN, g_processCBArray, OS_PROCESS_INFO_LEN);
*tcbArray = (LosTaskCB *)((UINTPTR)*pcbArray + processInfoLen);
(VOID)memcpy_s(*tcbArray, OS_TASK_INFO_LEN, g_taskCBArray, OS_TASK_INFO_LEN);
OsProcessInfoGet(pcbArray, group, memArray, tcbArray, flag);
taskWaterLine = (UINT32 *)((UINTPTR)*tcbArray + OS_TASK_INFO_LEN);
OsShellCmdTaskWaterLineGet(*tcbArray);
if (lockFlag == TRUE) {
......
......@@ -91,7 +91,7 @@ VOID OsMpScheduleHandler(VOID)
* set schedule flag to differ from wake function,
* so that the scheduler can be triggered at the end of irq.
*/
OsPercpuGet()->schedFlag |= INT_PEND_RESCH;//贴上调度标签
OsSchedRunQuePendingSet();
}
///硬中断暂停处理函数
VOID OsMpHaltHandler(VOID)
......
......@@ -30,7 +30,30 @@
*/
#include "los_percpu_pri.h"
#include "los_printf.h"
#ifdef LOSCFG_KERNEL_SMP
Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM]; ///< CPU池,池大小由CPU核数决定
VOID OsAllCpuStatusOutput(VOID)
{
UINT32 i;
for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
switch (g_percpu[i].excFlag) {
case CPU_RUNNING:
PrintExcInfo("cpu%u is running.\n", i);
break;
case CPU_HALT:
PrintExcInfo("cpu%u is halted.\n", i);
break;
case CPU_EXC:
PrintExcInfo("cpu%u is in exc.\n", i);
break;
default:
break;
}
}
PrintExcInfo("The current handling the exception is cpu%u !\n", ArchCurrCpuid());
}
#endif
......@@ -50,7 +50,7 @@ BOOL LOS_SpinHeld(const SPIN_LOCK_S *lock)
VOID LOS_SpinLock(SPIN_LOCK_S *lock)
{
UINT32 intSave = LOS_IntLock();
OsCpuSchedLock(OsPercpuGet());
OsSchedLock();
LOS_IntRestore(intSave);
LOCKDEP_CHECK_IN(lock);
......@@ -60,17 +60,22 @@ VOID LOS_SpinLock(SPIN_LOCK_S *lock)
INT32 LOS_SpinTrylock(SPIN_LOCK_S *lock)
{
Percpu *cpu = OsPercpuGet();
UINT32 intSave = LOS_IntLock();
OsCpuSchedLock(cpu);
OsSchedLock();
LOS_IntRestore(intSave);
INT32 ret = ArchSpinTrylock(&lock->rawLock);
if (ret == LOS_OK) {
LOCKDEP_CHECK_IN(lock);
LOCKDEP_RECORD(lock);
} else {
OsCpuSchedUnlock(cpu, LOS_IntLock());
return ret;
}
intSave = LOS_IntLock();
BOOL needSched = OsSchedUnlockResch();
LOS_IntRestore(intSave);
if (needSched) {
LOS_Schedule();
}
return ret;
......@@ -78,16 +83,22 @@ INT32 LOS_SpinTrylock(SPIN_LOCK_S *lock)
VOID LOS_SpinUnlock(SPIN_LOCK_S *lock)
{
UINT32 intSave;
LOCKDEP_CHECK_OUT(lock);
ArchSpinUnlock(&lock->rawLock);
OsCpuSchedUnlock(OsPercpuGet(), LOS_IntLock());
intSave = LOS_IntLock();
BOOL needSched = OsSchedUnlockResch();
LOS_IntRestore(intSave);
if (needSched) {
LOS_Schedule();
}
}
VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
{
*intSave = LOS_IntLock();
OsCpuSchedLock(OsPercpuGet());
OsSchedLock();
LOCKDEP_CHECK_IN(lock);
ArchSpinLock(&lock->rawLock);
......@@ -99,7 +110,11 @@ VOID LOS_SpinUnlockRestore(SPIN_LOCK_S *lock, UINT32 intSave)
LOCKDEP_CHECK_OUT(lock);
ArchSpinUnlock(&lock->rawLock);
OsCpuSchedUnlock(OsPercpuGet(), intSave);
BOOL needSched = OsSchedUnlockResch();
LOS_IntRestore(intSave);
if (needSched) {
LOS_Schedule();
}
}
#endif
......@@ -30,17 +30,13 @@
*/
#include "los_sortlink_pri.h"
#include "los_memory.h"
#include "los_exc.h"
#include "los_percpu_pri.h"
#include "los_sched_pri.h"
#include "los_mp.h"
/// 排序链表初始化
UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
VOID OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
{
LOS_ListInit(&sortLinkHeader->sortLink);//初始化双向链表
sortLinkHeader->nodeNum = 0;//nodeNum背后的含义是记录需要CPU工作的数量
return LOS_OK;
LOS_ListInit(&sortLinkHeader->sortLink);
LOS_SpinInit(&sortLinkHeader->spinLock);
sortLinkHeader->nodeNum = 0;
}
/*!
......@@ -52,7 +48,7 @@ UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
*
* @see
*/
STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
STATIC INLINE VOID AddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; //获取双向链表
......@@ -86,121 +82,50 @@ STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLin
} while (1);//死循环
}
/// 根据函数的具体实现,这个函数应该是找出最空闲的CPU, 函数的实现有待优化, @note_thinking
STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID)
VOID OsAdd2SortLink(SortLinkAttribute *head, SortLinkList *node, UINT64 responseTime, UINT16 idleCpu)
{
Percpu *idleCpu = OsPercpuGetByID(0); //获取0号CPU,0号CPU也可称主核
*idleCpuID = 0;
#ifdef LOSCFG_KERNEL_SMP //多核情况下
UINT16 cpuID = 1;
UINT32 nodeNum = idleCpu->taskSortLink.nodeNum + idleCpu->swtmrSortLink.nodeNum; //获取还未跑完的工作数量
//cpu执行两种工作: 1.普通任务 2.软件定时器
do {
Percpu *cpu = OsPercpuGetByID(cpuID); //一个个cpu遍历
UINT32 temp = cpu->taskSortLink.nodeNum + cpu->swtmrSortLink.nodeNum;//获取cpu的工作量
if (nodeNum > temp) {//对工作量比较
idleCpu = cpu;//取工作量最小的cpu实体
*idleCpuID = cpuID;//获取cpu id
}
cpuID++;//下一个cpu id
} while (cpuID < LOSCFG_KERNEL_CORE_NUM);
LOS_SpinLock(&head->spinLock);
SET_SORTLIST_VALUE(node, responseTime);
AddNode2SortLink(head, node);
#ifdef LOSCFG_KERNEL_SMP
node->cpuid = idleCpu;
#endif
LOS_SpinUnlock(&head->spinLock);
return idleCpu;
}
/// 向cpu的排序链表上添加指定节点
VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type)
{
Percpu *cpu = NULL;
SortLinkAttribute *sortLinkHeader = NULL;
SPIN_LOCK_S *spinLock = NULL;
UINT16 idleCpu;
if (OS_SCHEDULER_ACTIVE) {//当前CPU正在调度
cpu = OsFindIdleCpu(&idleCpu);//找一个最空闲的CPU
} else {
idleCpu = ArchCurrCpuid();//使用当前cpu
cpu = OsPercpuGet();
}
if (type == OS_SORT_LINK_TASK) {//任务类型
sortLinkHeader = &cpu->taskSortLink; //获取任务链表
spinLock = &cpu->taskSortLinkSpin;
} else if (type == OS_SORT_LINK_SWTMR) {//软件定时器类型
sortLinkHeader = &cpu->swtmrSortLink;//获取软件定时器链表
spinLock = &cpu->swtmrSortLinkSpin;
} else {
LOS_Panic("Sort link type error : %u\n", type);
}
LOS_SpinLock(spinLock);
SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK);//设置节点响应时间
OsAddNode2SortLink(sortLinkHeader, node);//插入节点
#ifdef LOSCFG_KERNEL_SMP
node->cpuid = idleCpu;
if (idleCpu != ArchCurrCpuid()) { //如果插入的链表不是当前CPU的链表
LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu));//核间中断,对该CPU发生一次调度申请
if (idleCpu != ArchCurrCpuid()) {
LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu));
}
#endif
LOS_SpinUnlock(spinLock);
}
/// 从cpu的排序链表上摘除指定节点
VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type)
{
#ifdef LOSCFG_KERNEL_SMP
Percpu *cpu = OsPercpuGetByID(node->cpuid);//获取CPU
#else
Percpu *cpu = OsPercpuGetByID(0);
#endif
SPIN_LOCK_S *spinLock = NULL;
SortLinkAttribute *sortLinkHeader = NULL;
if (type == OS_SORT_LINK_TASK) {//当为任务时
sortLinkHeader = &cpu->taskSortLink;//获取该CPU的任务链表
spinLock = &cpu->taskSortLinkSpin;
} else if (type == OS_SORT_LINK_SWTMR) {
sortLinkHeader = &cpu->swtmrSortLink;//获取该CPU的定时器链表
spinLock = &cpu->swtmrSortLinkSpin;
} else {
LOS_Panic("Sort link type error : %u\n", type);
}
LOS_SpinLock(spinLock);
VOID OsDeleteFromSortLink(SortLinkAttribute *head, SortLinkList *node)
{
LOS_SpinLock(&head->spinLock);
if (node->responseTime != OS_SORT_LINK_INVALID_TIME) {
OsDeleteNodeSortLink(sortLinkHeader, node);//从CPU的执行链表上摘除
OsDeleteNodeSortLink(head, node);
}
LOS_SpinUnlock(spinLock);
LOS_SpinUnlock(&head->spinLock);
}
/*!
* @brief OsSortLinkGetTargetExpireTime
* 返回离触发目标时间的tick数
* @param targetSortList
* @return
*
* @see
*/
UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList)
UINT64 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *targetSortList)
{
UINT64 currTimes = OsGetCurrSchedTimeCycle();
if (currTimes >= targetSortList->responseTime) {
if (currTime >= targetSortList->responseTime) {
return 0;
}
return (UINT32)(targetSortList->responseTime - currTimes) / OS_CYCLE_PER_TICK;//响应时间减去当前时间置算出剩余tick数
return (UINT32)(targetSortList->responseTime - currTime);
}
UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader)
UINT64 OsSortLinkGetNextExpireTime(UINT64 currTime, const SortLinkAttribute *sortLinkHeader)
{
LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink;
if (LOS_ListEmpty(head)) {
return 0;
return OS_SORT_LINK_INVALID_TIME;
}
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode);
return OsSortLinkGetTargetExpireTime(listSorted);
return OsSortLinkGetTargetExpireTime(currTime, listSorted);
}
......@@ -48,6 +48,7 @@
#include "los_spinlock.h"
#include "los_swtmr_pri.h"
#include "los_task_pri.h"
#include "los_sched_pri.h"
#include "los_tick.h"
#include "los_vm_boot.h"
#include "los_smp.h"
......@@ -72,6 +73,7 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 EarliestInit(VOID)
/* Must be placed at the beginning of the boot process *///必须放在启动过程的开头
OsSetMainTask();//为每个CPU核设置临时主任务
OsCurrTaskSet(OsGetMainTask());//设置当前任务
OsSchedRunQueInit();
g_sysClock = OS_SYS_CLOCK;
g_tickPerSecond = LOSCFG_BASE_CORE_TICK_PER_SECOND;
......
......@@ -129,6 +129,7 @@ STATIC INLINE BOOL OsIsBadUserAddress(VADDR_T vaddr)
return (vaddr >= USER_STACK_TOP_MAX);
}
extern UINT32 OsGetRndOffset(INT32 randomDevFD);
extern INT32 OsLoadELFFile(ELFLoadInfo *loadInfo);
#ifdef __cplusplus
......
......@@ -716,18 +716,18 @@ STATIC INT32 OsGetParamNum(CHAR *const *argv)
return count;
}
STATIC UINT32 OsGetRndOffset(const ELFLoadInfo *loadInfo)
UINT32 OsGetRndOffset(INT32 randomDevFD)
{
UINT32 randomValue = 0;
#ifdef LOSCFG_ASLR
if (read(loadInfo->randomDevFD, &randomValue, sizeof(UINT32)) == sizeof(UINT32)) {
if (read(randomDevFD, &randomValue, sizeof(UINT32)) == sizeof(UINT32)) {
randomValue &= RANDOM_MASK;
} else {
randomValue = (UINT32)random() & RANDOM_MASK;
}
#else
(VOID)loadInfo;
(VOID)randomDevFD;
#endif
return ROUNDDOWN(randomValue, PAGE_SIZE);
......@@ -805,7 +805,7 @@ STATIC INT32 OsSetArgParams(ELFLoadInfo *loadInfo, CHAR *const *argv, CHAR *cons
if (((UINT32)loadInfo->stackProt & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)) {
return -ENOEXEC;
}
loadInfo->stackTopMax = USER_STACK_TOP_MAX - OsGetRndOffset(loadInfo);
loadInfo->stackTopMax = USER_STACK_TOP_MAX - OsGetRndOffset(loadInfo->randomDevFD);
loadInfo->stackBase = loadInfo->stackTopMax - USER_STACK_SIZE;
loadInfo->stackSize = USER_STACK_SIZE;
loadInfo->stackParamBase = loadInfo->stackTopMax - USER_PARAM_BYTE_MAX;
......@@ -963,7 +963,7 @@ STATIC INT32 OsLoadELFSegment(ELFLoadInfo *loadInfo)
loadInfo->loadAddr = 0;
if (loadInfo->execInfo.elfEhdr.elfType == LD_ET_DYN) {
loadBase = EXEC_MMAP_BASE + OsGetRndOffset(loadInfo);
loadBase = EXEC_MMAP_BASE + OsGetRndOffset(loadInfo->randomDevFD);
mapSize = OsGetAllocSize(elfPhdrTemp, loadInfo->execInfo.elfEhdr.elfPhNum);
if (mapSize == 0) {
PRINT_ERR("%s[%d], Failed to get allocation size of file: %s!\n", __FUNCTION__, __LINE__,
......@@ -1009,17 +1009,7 @@ STATIC INT32 OsLoadELFSegment(ELFLoadInfo *loadInfo)
STATIC VOID OsFlushAspace(ELFLoadInfo *loadInfo)
{
LosProcessCB *processCB = OsCurrProcessGet();
OsExecDestroyTaskGroup();
loadInfo->oldSpace = processCB->vmSpace;
processCB->vmSpace = loadInfo->newSpace;
processCB->vmSpace->heapBase += OsGetRndOffset(loadInfo);
processCB->vmSpace->heapNow = processCB->vmSpace->heapBase;
processCB->vmSpace->mapBase += OsGetRndOffset(loadInfo);
processCB->vmSpace->mapSize = loadInfo->stackBase - processCB->vmSpace->mapBase;
LOS_ArchMmuContextSwitch(&OsCurrProcessGet()->vmSpace->archMmu);
loadInfo->oldSpace = OsExecProcessVmSpaceReplace(loadInfo->newSpace, loadInfo->stackBase, loadInfo->randomDevFD);
}
STATIC VOID OsDeInitLoadInfo(ELFLoadInfo *loadInfo)
......@@ -1079,8 +1069,7 @@ INT32 OsLoadELFFile(ELFLoadInfo *loadInfo)
ret = OsLoadELFSegment(loadInfo);
if (ret != LOS_OK) {
OsCurrProcessGet()->vmSpace = loadInfo->oldSpace;
LOS_ArchMmuContextSwitch(&OsCurrProcessGet()->vmSpace->archMmu);
OsExecProcessVmSpaceRestore(loadInfo->oldSpace);
goto OUT;
}
......
......@@ -299,7 +299,7 @@ ERROR_REGION_OUT:
LITE_OS_SEC_TEXT_INIT STATIC UINT32 LiteIpcPoolInit(ProcIpcInfo *ipcInfo)
{
ipcInfo->pool.uvaddr = NULL;
ipcInfo->pool.kvaddr = NULL
ipcInfo->pool.kvaddr = NULL;
ipcInfo->pool.poolSize = 0;
ipcInfo->ipcTaskID = INVAILD_ID;
LOS_ListInit(&ipcInfo->ipcUsedNodelist);//上面将挂已使用的节点
......@@ -765,7 +765,10 @@ LITE_OS_SEC_TEXT STATIC BOOL IsTaskAlive(UINT32 taskID)
return FALSE;
}
tcb = OS_TCB_FROM_TID(taskID); //获取任务控制块
if (!OsProcessIsUserMode(OS_PCB_FROM_PID(tcb->processID))) {//判断是否为用户进程
if (!OsTaskIsUserMode(tcb)) {
return FALSE;
}
if (OsTaskIsUnused(tcb)) {
return FALSE;
}
if (OsTaskIsInactive(tcb)) {//任务是否活跃
......
......@@ -28,19 +28,16 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/NuttX/NuttX.gni")
module_switch = defined(LOSCFG_KERNEL_PIPE)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"//third_party/NuttX/drivers/pipes/fifo.c",
"//third_party/NuttX/drivers/pipes/pipe.c",
"//third_party/NuttX/drivers/pipes/pipe_common.c",
]
sources = NUTTX_DRIVERS_PIPES_SRC_FILES
public_configs = [ ":public" ]
}
config("public") {
include_dirs = [ "//third_party/NuttX/drivers/pipes" ]
include_dirs = NUTTX_DRIVERS_PIPES_INCLUDE_DIRS
}
......@@ -224,7 +224,6 @@ STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
LOS_SysSleepEnum mode;
UINT32 prepare = 0;
BOOL tickTimerStop = FALSE;
UINT64 currTime;
ret = OsPmSuspendCheck(pm, &sysSuspendEarly, &deviceSuspend, &mode);
if (ret != LOS_OK) {
......@@ -247,9 +246,8 @@ STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
tickTimerStop = OsPmTickTimerStop(pm);
if (!tickTimerStop) {
currTime = OsGetCurrSchedTimeCycle();
OsSchedResetSchedResponseTime(0);
OsSchedUpdateExpireTime(currTime);
OsSchedUpdateExpireTime();
}
OsPmCpuSuspend(pm);
......
......@@ -72,6 +72,7 @@
#include "trace_cnv.h"
#include "los_init.h"
#include "los_process.h"
#include "los_sched_pri.h"
#ifdef LOSCFG_KERNEL_SMP
#include "los_mp.h"
......@@ -137,7 +138,7 @@ STATIC VOID OsTraceSetFrame(TraceEventFrame *frame, UINT32 eventType, UINTPTR id
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
frame->core.cpuId = ArchCurrCpuid();
frame->core.hwiActive = OS_INT_ACTIVE ? TRUE : FALSE;
frame->core.taskLockCnt = MIN(OsPercpuGet()->taskLockCnt, 0xF); /* taskLockCnt is 4 bits, max value = 0xF */
frame->core.taskLockCnt = MIN(OsSchedLockCountGet(), 0xF); /* taskLockCnt is 4 bits, max value = 0xF */
frame->core.paramCount = paramCount;
#endif
......
......@@ -30,8 +30,8 @@
import("//kernel/liteos_a/liteos.gni")
MUSLDIR = "$LITEOSTHIRDPARTY/musl"
OPTRTDIR = "$LITEOSTHIRDPARTY/optimized-routines"
import("//third_party/optimized-routines/optimized-routines.gni")
import("$MUSLDIR/porting/liteos_a/kernel/musl.gni")
module_switch = defined(LOSCFG_LIB_LIBC)
......@@ -54,13 +54,7 @@ kernel_module(module_name) {
"$MUSLPORTINGDIR/src/string/strcpy.c",
"$MUSLPORTINGDIR/src/string/strlen.c",
]
sources += [
"$OPTRTDIR/string/arm/memchr.S",
"$OPTRTDIR/string/arm/memcpy.S",
"$OPTRTDIR/string/arm/strcmp.S",
"$OPTRTDIR/string/arm/strcpy.c",
"$OPTRTDIR/string/arm/strlen-armv6t2.S",
]
sources += OPTRT_STRING_ARM_SRC_FILES
asmflags = [
"-D__strlen_armv6t2=strlen",
"-D__strcmp_arm=strcmp",
......
......@@ -28,6 +28,7 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//kernel/liteos_a/liteos.gni")
import("//third_party/FreeBSD/FreeBSD.gni")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
......@@ -38,7 +39,7 @@ kernel_module(module_name) {
"src/los_seq_buf.c",
]
sources += [ "$LITEOSTHIRDPARTY/FreeBSD/sys/libkern/crc32.c" ]
sources += FREEBSD_SYS_LIBKERN_SRC_FILES
public_configs = [ ":public" ]
}
......
......@@ -271,7 +271,7 @@ STATIC ssize_t TelnetWrite(struct file *file, const CHAR *buf, const size_t bufL
if (telnetDev->clientFd != 0) {
#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
/* DO NOT call blocking API in software timer task | 不要在软件定时器任务中调用阻塞 API */
if (((LosTaskCB*)OsCurrTaskGet())->taskEntry == (TSK_ENTRY_FUNC)OsSwtmrTask) {
if (OsIsSwtmrTask(OsCurrTaskGet())) {
TelnetUnlock();
return ret;
}
......
......@@ -35,6 +35,7 @@
#include "los_cpup_pri.h"
#endif
#include "los_hwi_pri.h"
#include "los_sys_pri.h"
#include "shcmd.h"
......
......@@ -949,7 +949,6 @@ EXIT:
int SysUserThreadDetach(unsigned int taskID)
{
unsigned int intSave;
LosTaskCB *taskCB = NULL;
unsigned int ret;
if (OS_TID_CHECK_INVALID(taskID)) {
......@@ -957,14 +956,13 @@ int SysUserThreadDetach(unsigned int taskID)
}
SCHEDULER_LOCK(intSave);
taskCB = OS_TCB_FROM_TID(taskID);
ret = OsUserTaskOperatePermissionsCheck(taskCB);
ret = OsUserTaskOperatePermissionsCheck(OS_TCB_FROM_TID(taskID));
SCHEDULER_UNLOCK(intSave);
if (ret != LOS_OK) {
SCHEDULER_UNLOCK(intSave);
return ret;
}
ret = OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave);
ret = LOS_TaskDelete(taskID);
if (ret != LOS_OK) {
return ESRCH;
}
......@@ -998,12 +996,13 @@ EXIT:
void SysUserExitGroup(int status)
{
OsTaskExitGroup((unsigned int)status);
(void)status;
OsProcessThreadGroupDestroy();
}
/// 系统调用线程退出
void SysThreadExit(int status)
{
OsTaskToExit(OsCurrTaskGet(), (unsigned int)status);
OsRunningTaskToExit(OsCurrTaskGet(), (unsigned int)status);
}
/*!
......
......@@ -49,7 +49,6 @@ netdb_sources_full = [
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_010.cpp",
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_011.cpp",
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_012.cpp",
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_014.cpp",
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_015.cpp",
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_016.cpp",
"$TEST_UNITTEST_DIR/net/netdb/full/net_netdb_test_017.cpp",
......
......@@ -35,6 +35,17 @@
static int AddrInfoTest(void)
{
// Prerequisite: correct DNS servers must be configured.
char host_file[] = "127.0.0.2 example.com\n", serv_file[] = "ftp 21/tcp\n";
char *pathList[] = {"/etc/hosts", "/etc/services"};
char *streamList[] = {host_file, serv_file};
int streamLen[] = {sizeof(host_file), sizeof(serv_file)};
const int file_number = 2;
int flag = PrepareFileEnv(pathList, streamList, streamLen, file_number);
if (flag != 0) {
RecoveryFileEnv(pathList, file_number);
return -1;
}
struct addrinfo *addr = NULL;
int ret = getaddrinfo("example.com", "ftp", NULL, &addr);
ICUNIT_ASSERT_EQUAL(ret, 0, ret);
......@@ -50,6 +61,7 @@ static int AddrInfoTest(void)
const char *p = gai_strerror(EAI_AGAIN);
ICUNIT_ASSERT_NOT_EQUAL(p, NULL, -1);
RecoveryFileEnv(pathList, file_number);
return ICUNIT_SUCCESS;
}
......
......@@ -34,8 +34,19 @@
static int GetHostByAddrTest(void)
{
char host_file[] = "127.0.0.1 localhost\n100.0.0.0 example.com example\n";
char *pathList[] = {"/etc/hosts"};
char *streamList[] = {host_file};
int streamLen[] = {sizeof(host_file)};
const int file_number = 1;
int flag = PrepareFileEnv(pathList, streamList, streamLen, file_number);
if (flag != 0) {
RecoveryFileEnv(pathList, file_number);
return -1;
}
struct in_addr ia;
int length = 4;
int length = 4; // the address length is 4;
ia.s_addr = inet_addr("127.0.0.1");
struct hostent *addr = gethostbyaddr(&ia, sizeof ia, AF_INET);
ICUNIT_ASSERT_NOT_EQUAL(addr, NULL, -1);
......@@ -43,19 +54,18 @@ static int GetHostByAddrTest(void)
ICUNIT_ASSERT_STRING_EQUAL(addr->h_name, "localhost", -1);
ICUNIT_ASSERT_EQUAL(addr->h_length, length, -1);
ia.s_addr = inet_addr("100.109.180.184");
ia.s_addr = inet_addr("100.0.0.0");
addr = gethostbyaddr(&ia, sizeof ia, AF_INET);
ICUNIT_ASSERT_NOT_EQUAL(addr, NULL, -1);
ICUNIT_ASSERT_EQUAL(addr->h_addrtype, AF_INET, addr->h_addrtype);
ICUNIT_ASSERT_STRING_EQUAL(addr->h_name, "szvphisprb93341", -1);
ICUNIT_ASSERT_STRING_EQUAL(addr->h_aliases[0], "szvphisprb93341", -1);
ICUNIT_ASSERT_STRING_EQUAL(addr->h_name, "example.com", -1);
errno = 0;
ia.s_addr = inet_addr("127.0.0.0");
addr = gethostbyaddr(&ia, sizeof ia, AF_INET);
ICUNIT_ASSERT_EQUAL(errno, EINVAL, errno);
return ICUNIT_SUCCESS;
    RecoveryFileEnv(pathList, file_number);
return ICUNIT_SUCCESS;
}
......
......@@ -34,6 +34,16 @@
static int GetHostByNameTest(void)
{
char host_file[] = "127.0.0.1 localhost\n";
char *pathList[] = {"/etc/hosts"};
char *streamList[] = {host_file};
int streamLen[] = {sizeof(host_file)};
int flag = PrepareFileEnv(pathList, streamList, streamLen, 1);
if (flag != 0) {
RecoveryFileEnv(pathList, 1);
return -1;
}
struct hostent *addr = gethostbyname("localhost");
ICUNIT_ASSERT_NOT_EQUAL(addr, NULL, -1);
ICUNIT_ASSERT_EQUAL(strcmp(addr->h_name, "localhost"), 0, -1);
......@@ -49,6 +59,7 @@ static int GetHostByNameTest(void)
addr = gethostbyname("lo");
ICUNIT_ASSERT_EQUAL(addr, NULL, -1);
RecoveryFileEnv(pathList, 1);
return ICUNIT_SUCCESS;
}
......
......@@ -34,6 +34,17 @@
static int GetHostByNameRTest(void)
{
char host_file[] = "127.0.0.1 localhost\n";
char *pathList[] = {"/etc/hosts"};
char *streamList[] = {static_cast<char *>(host_file)};
int streamLen[] = {sizeof(host_file)};
const int file_number = 1;
int flag = PrepareFileEnv(pathList, streamList, streamLen, file_number);
if (flag != 0) {
RecoveryFileEnv(pathList, file_number);
return -1;
}
struct hostent addr, *result = NULL;
char buf[1024];
char buf1[1];
......@@ -60,6 +71,7 @@ static int GetHostByNameRTest(void)
ret = gethostbyname_r("lo", &addr, buf, sizeof buf, &result, &err);
ICUNIT_ASSERT_NOT_EQUAL(ret, 0, ret);
RecoveryFileEnv(pathList, file_number);
return ICUNIT_SUCCESS;
}
......
......@@ -34,6 +34,17 @@
static int GetHostByName2Test(void)
{
char host_file[] = "127.0.0.1 localhost\n";
char *pathList[] = {"/etc/hosts"};
char *streamList[] = {static_cast<char *>(host_file)};
int streamLen[] = {sizeof(host_file)};
const int file_number = 1;
int flag = PrepareFileEnv(pathList, streamList, streamLen, file_number);
if (flag != 0) {
RecoveryFileEnv(pathList, file_number);
return -1;
}
struct hostent *addr = gethostbyname2("localhost", AF_INET);
ICUNIT_ASSERT_NOT_EQUAL(addr, NULL, -1);
ICUNIT_ASSERT_EQUAL(strcmp(addr->h_name, "localhost"), 0, -1);
......@@ -51,6 +62,7 @@ static int GetHostByName2Test(void)
addr = gethostbyname2("localh", AF_INET);
ICUNIT_ASSERT_EQUAL(addr, NULL, -1);
RecoveryFileEnv(pathList, file_number);
return ICUNIT_SUCCESS;
}
......
......@@ -33,6 +33,17 @@
static int GetHostByName2RTest(void)
{
char host_file[] = "127.0.0.1 localhost\n";
char *pathList[] = {"/etc/hosts"};
char *streamList[] = {host_file};
int streamLen[] = {sizeof(host_file)};
const int file_number = 1;
int flag = PrepareFileEnv(pathList, streamList, streamLen, file_number);
if (flag != 0) {
RecoveryFileEnv(pathList, file_number);
return -1;
}
struct hostent addr, *result = NULL;
char buf[1024];
char buf1[1];
......@@ -59,6 +70,7 @@ static int GetHostByName2RTest(void)
ret = gethostbyname2_r("lo", AF_INET, &addr, buf, sizeof buf, &result, &err);
ICUNIT_ASSERT_NOT_EQUAL(ret, 0, ret);
RecoveryFileEnv(pathList, file_number);
return ICUNIT_SUCCESS;
}
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册