鸿蒙liteos-a添加一个短作业优先调度算法

对鸿蒙Liteos的调度算法进行改进或添加一个新的调度算法

实验目的

对鸿蒙Liteos的调度算法进行改进或添加一个新的调度算法

实验环境

ubuntu18.4,
windows11

实验内容

编译musl,prebuilts

  • 因为需要修改pthread库,故要重新编译musl,这里介绍musl以及prebuilts目录.
    查询open Harmony官方文档可知,在1.1.0release版本中具有编译prebults的sh文件,但添加了一个额外的库
重新编译
  • 在git版本管理中将prebuilts版本改至1.1.0release
    • 1.如果代码是用repo下载的全量代码,进入prebuilts命令,执行
      git tag
      git checkout OpenHarmony_release_V1.1.0
      
    • 2.不是的话自行参照目录更改
      ----prebuilts/lite/sysroot
      	----/build
      		----**.sh
      	----/thirdparty
      	----/usr
      
  • 分别执行build目录下的thirdparty_headers.sh和build_musl_clang.sh脚本会报错,需要以下操作
    • 1.下载Linux内核
      • 执行
        wget https://mirror.bjtu.edu.cn/kernel/linux/kernel/v4.x/linux-4.4.62.tar.gz
        
      • 解压到~/Kernel
        mkdir ~/Kernel
        tar -xvf linux-4.4.62.tar.gz -C ~/Kernel
        
    • 2.修改prebuilts/lite/sysroot/build/update_headers.py
      • 原文件应该是python2所写,最简单的方法是修改为python3语法
      • 修改结果见
        #!/usr/bin/env python
        #-*-coding:utf-8-*-
        
        #Copyright (c) 2020-2021 Huawei Device Co., Ltd.
        #Licensed under the Apache License, Version 2.0 (the "License");
        #you may not use this file except in compliance with the License.
        #You may obtain a copy of the License at
        #
        #    http://www.apache.org/licenses/LICENSE-2.0
        #
        #Unless required by applicable law or agreed to in writing, software
        #distributed under the License is distributed on an "AS IS" BASIS,
        #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        #See the License for the specific language governing permissions and
        #limitations under the License.
        
        # Perform for Z kernel headers
        
        import sys
        import os
        import getopt
        import subprocess
        import time
        import string
        import re
        import glob
        
        # /*..*/  //...
        Rule1 = "(\/\*(\s|.)*?\*\/)|(\/\/.*)"
        c1=re.compile(Rule1)
        
        #use list for order
        key_list = [
        #     grep key,								gerp dir,				sed key,								sed replace
            ["CONFIG_64BIT",						".",					"CONFIG_64BIT",							"__LP64__"],
            ["__unused;",							".",					"__unused;",							"__linux_unused;"],
            ["__unused\[",							".",					"__unused\[",							"__linux_unused["],
            [" private;",							".",					" private;",							" __linux_private;"],
            ["\*virtual;",							".",					"\*virtual;",							"\* __linux_virtual;"],
            ["struct msqid_ds",						".",					"struct msqid_ds",						"struct __kernel_legacy_msqid_ds"],
            ["struct semid_ds",						".",					"struct semid_ds",						"struct __kernel_legacy_semid_ds"],
            ["struct shmid_ds",						".",					"struct shmid_ds",						"struct __kernel_legacy_shmid_ds"],
            ["struct ipc_perm",						".",					"struct ipc_perm",						"struct __kernel_legacy_ipc_perm"],
            ["union semun",							".",					"union semun",							"union __kernel_legacy_semun"],
            ["_NSIG",								".",					"_NSIG",								"_KERNEL__NSIG"],
            ["_KERNEL__NSIG_",						".",					"_KERNEL__NSIG_",						"_NSIG_"],
            ["#define NSIG\s",						".",					"#define NSIG",							"#define _KERNEL_NSIG"],
            ["SIGRTMIN",							".",					"SIGRTMIN",								"__SIGRTMIN"],
            ["SIGRTMAX",							".",					"SIGRTMAX",								"__SIGRTMAX"],
            ["struct udphdr",						".",					"struct udphdr",						"struct __kernel_udphdr"],
            ["__attribute_const__",					".",					"__attribute_const__",					"__attribute__((__const__))"],
            ["struct __kernel_sockaddr_storage",	".",					"struct __kernel_sockaddr_storage",		"struct sockaddr_storage"],
            ["off_t",								"asm-mips/asm/stat.h",	"off_t",								"__kernel_off_t"],
            ["#ifndef __EXPORTED_HEADERS__",		".",					"#ifndef __EXPORTED_HEADERS__",			"#if 0 \/*__EXPORTED_HEADERS__*\/"],
            ["#ifndef __KERNEL_STRICT_NAMES",		".",					"#ifndef __KERNEL_STRICT_NAMES",		"#if 0 \/*__KERNEL_STRICT_NAMES*\/"],
            ["#ifdef __CHECKER__",					".",					"#ifdef __CHECKER__",					"#if 0 \/*__CHECKER__*\/"],
            ["#ifdef __HAVE_BUILTIN_BSWAP16__",		".",					"#ifdef __HAVE_BUILTIN_BSWAP16__",		"#if 1 \/*__HAVE_BUILTIN_BSWAP16__*\/"],
            ["#ifdef __HAVE_BUILTIN_BSWAP32__",		".",					"#ifdef __HAVE_BUILTIN_BSWAP32__",		"#if 1 \/*__HAVE_BUILTIN_BSWAP32__*\/"],
            ["#ifdef __HAVE_BUILTIN_BSWAP64__",		".",					"#ifdef __HAVE_BUILTIN_BSWAP64__",		"#if 1 \/*__HAVE_BUILTIN_BSWAP64__*\/"],
            ["#if defined(__ARMEB__)",				"asm-arm",				"#if defined(__ARMEB__)",				"#if 0 \/*__ARMEB__*\/"],
            ["#ifdef __ARMEB__",					"asm-arm",				"#ifdef __ARMEB__",						"#if 0 \/*__ARMEB__*\/"],
            ["defined(__ARM_EABI__)",				"asm-arm",				"defined(__ARM_EABI__)",				"1 \/*defined(__ARM_EABI__)*\/"],
            ["#ifdef __MIPSEB__",					"asm-mips",				"#ifdef __MIPSEB__",					"#if 0 \/*__MIPSEB__*\/"],
            ["#elif defined (__MIPSEB__)",			"asm-mips",				"#elif defined (__MIPSEB__)",			"#elif 0 \/*__MIPSEB__*\/"],
            ["#if defined(__MIPSEB__)",				"asm-mips",				"#if defined(__MIPSEB__)",				"#if 0 \/*__MIPSEB__*\/"],
            ["#elif defined(__MIPSEL__)",			"asm-mips",				"#elif defined(__MIPSEL__)",			"#elif 1 \/*__MIPSEL__*\/"],
            ["#elif defined (__MIPSEL__)",			"asm-mips",				"#elif defined (__MIPSEL__)",			"#elif 1 \/*__MIPSEL__*\/"],
            ["\!defined(__SANE_USERSPACE_TYPES__)",	"asm-mips",				"\!defined(__SANE_USERSPACE_TYPES__)",	"0 \/*__SANE_USERSPACE_TYPES__*\/"],
            ["\/\*.*\*\/",						".",					"\/\*.*\*\/",							""],
            ]
        
        def deal_file(src):
            # file exist or not
            if not os.path.exists(src):
                print ('Error: file - %s doesn\'t exist.'% src)
                return False
            if os.path.islink(src):
                print ('Error: file - %s is a link.')
                return False
            filetype = (os.path.splitext(src))[1]
            if not filetype in ['.c','.h','.cpp','.hh','.cc']:
                return False
            try:
                if not os.access(src, os.W_OK):
                    os.chmod(src, 0o0664)
            except:
                print ('Error: you can not chang %s\'s mode.'% src)
        
            # del all comments
            inputf = open(src, 'r')
            outputfilename = (os.path.splitext(src))[0] + '_no_comment'+filetype
            outputf = open(outputfilename, 'w')
        
            lines=inputf.read()
            inputf.close()
            lines=re.sub(Rule1,"",lines)
            outputf.write(lines)
            outputf.close()
        
            #del right space & blank line
            os.remove(src)
            inputf  = open(outputfilename, 'r')
            outputf = open(src, 'w')
            #write head info
            outputf.write("/*\n")
            outputf.write(" * This header was generated from the Linux kernel headers by update_headers.py,\n")
            outputf.write(" * to provide necessary information from kernel to userspace, such as constants,\n")
            outputf.write(" * structures, and macros, and thus, contains no copyrightable information.\n")
            outputf.write(" */\n")
            line = inputf.readline()
            while line:
                if line == '\n':
                    line = line.strip("\n")
                else:
                    line = line.rstrip() + '\n'
                outputf.write(line)
                line = inputf.readline()
            inputf.close()
            outputf.close()
            os.remove(outputfilename)
        
            return True
        
        
        def deal_dir(src):
            #  dir exist or not
            if not os.path.exists(src):
                print ('Error: dir - %s is not exist.'%(src))
                return False
            filelists = os.listdir(src)
            for eachfile in filelists:
                eachfile = src + '/' +eachfile
                if os.path.isdir(eachfile):
                    deal_dir(eachfile)
                elif os.path.isfile(eachfile):
                    deal_file(eachfile)
            return True
        
        
        def copy_kernel_headers(build_top, original_dir, target_dir):
            headers_dir = build_top + '/' + target_dir
            external_dir = build_top + original_dir
        
            headers_rm_cmd = "rm " + headers_dir + "/uapi -rf"
            headers_cp_cmd = "cp " + external_dir + " " + headers_dir + " -r"
        
            try:
                status = subprocess.call(headers_rm_cmd, shell=True)
            except:
                print("[Error] rm error!!!")
        
            try:
                status = subprocess.call(headers_cp_cmd, shell=True)
            except:
                print("[Error] cp error!!!")
        
            return 1
        
        def replace_key_words_ext(keys):
            replace_key_words(keys[0], keys[1], keys[2], keys[3])
            return 1
        
        def replace_key_words(original_key, target_dir, replace_key, replace_str):
            replace_cmd = "grep \""+ original_key + "\" -rl " + target_dir + " | xargs sed -i \"s/" + replace_key + "/" + replace_str + "/g\""
            try:
                status = subprocess.call(replace_cmd, shell=True)
            except:
                print("[Error] replace CONFIG_64BIT error!!!")
        
            return 1
        
        
        
        def usage():
            print("    Usage: run the script at the root of project.\n    For example:\n\
              python ./foundation/ccruntime/libc/kernel/tools/update_Z_header.py")
            return 0
        
        
        def main():
        
            if len(sys.argv) > 1:
                usage()
                return -1
        
            kernel_dir = "prebuilts/lite/sysroot/ohos_tmp"
            external_dir = '/prebuilts/lite/sysroot/ohos_tmp_ori/uapi'
            status = -1
        
            try:
                build_top = os.environ["Z_BUILD_TOP"]
            except KeyError as e:
                print("[Warning] no env : %s, use current work dir." %(str(e)))
                build_top = subprocess.check_output("pwd", shell=True)
        
            status = copy_kernel_headers(build_top.strip(), external_dir, kernel_dir)
            if status != 1:
                print("[Error] copy files fail!!!")
                sys.exti(1)
        
            try:
                os.chdir(kernel_dir + "/uapi")
            except:
                print("[Error] no uapi dir1!!!")
                sys.exit(1)
        
            current_dir = os.getcwd()
        
            if "uapi" not in current_dir:
                print("[Error] not uapi dir!!!")
                sys.exit(1)
        
            for val in key_list:
                replace_key_words_ext(val)
        
            try:
                os.chdir("../")
            except:
                print("[Error] no uapi dir2!!!")
                sys.exit(1)
            deal_dir("uapi")
        
            return 1
        
        if __name__ == "__main__":
            starttime=time.time()
            main()
            endtime=time.time()
            print(endtime-starttime)
        
        
        
    • 3.现在执行thirdparty_headers.sh会报错
      • 先进入prebuilts/lite/sysroot/thirdparty,然后执行
        export KERNEL_DIR=~/Kernel/linux-4.4.62
        cp -r $KERNEL_DIR/include/uapi/* ./linux_headers_install
        pushd $KERNEL_DIR
        make headers_install ARCH=arm INSTALL_HDR_PATH=./tmp_dir
        popd
        cp -r $KERNEL_DIR/tmp_dir/include/asm ./linux_headers_install
        
    • 4.因为使用1.1.0release的prebuilt添加了一些新组件,进入third_party
      • 执行
        git clone https://gitee.com/openharmony/third_party_optimized_routines.git
        mv third_party_optimized_routines optimized-routines
        cd optimized-routines/
        git checkout OpenHarmony_release_v1.1.0
        
    • 5.现在进入prebuilts/lite/sysroot/build/
      • 执行
        mkdir musl
        mkdir musl/include
        ./thirdparty_headers.sh
        ./build_musl_clang.sh
        cp -r usr ../
        

开始添加新调度方法

内核部分
  • 1.kernel/liteos_a/kernel/base/include/los_process_pri.h 添加宏
    #define LOS_SCHED_SJF     3U
    
  • 2.修改kernel/liteos_a/syscall/process_syscall.c中函数
    static int OsUserTaskSchedulerSet(unsigned int tid, unsigned short policy, unsigned short priority, bool policyFlag)
    {
        PRINTK("\n----------------------------------------\n");
        PRINTK("entry OsUserTaskSchedulerSet\n");
        int ret;
        unsigned int intSave;
        LosTaskCB *taskCB = NULL;
    
        if (OS_TID_CHECK_INVALID(tid)) {
            return EINVAL;
        }
    
        if (priority > OS_TASK_PRIORITY_LOWEST) {
            return EINVAL;
        }
    
        if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)&& (policy != LOS_SCHED_SJF)) {
            return EINVAL;
        }
    
        SCHEDULER_LOCK(intSave);
        taskCB = OS_TCB_FROM_TID(tid);
        PRINTK("OsUserTaskSchedulerSet entry OsUserTaskOperatePermissionsCheck\n");
        ret = OsUserTaskOperatePermissionsCheck(taskCB);
        if (ret != LOS_OK) {
            SCHEDULER_UNLOCK(intSave);
            PRINTK("OsUserTaskSchedulerSet entry OsUserTaskOperatePermissionsCheck error ret=%d\n", ret);
            return ret;
        }
        PRINTK("leave OsUserTaskSchedulerSet and entry OsTaskSchedulerSetUnsafe\n");
        return OsTaskSchedulerSetUnsafe(taskCB, policy, priority, policyFlag, intSave);
    }
    
    int SysSchedSetScheduler(int id, int policy, int prio, int flag)
    {
        PRINTK("entry SysSchedSetScheduler\n");
        int ret;
    
        if (flag < 0)
        {
            PRINTK("SysSchedSetScheduler entry OsUserTaskSchedulerSet\n");
            return -OsUserTaskSchedulerSet(id, policy, prio, TRUE);
        }
    
        if (prio < OS_USER_PROCESS_PRIORITY_HIGHEST)
        {
            PRINTK("SysSchedSetScheduler prio < OS_USER_PROCESS_PRIORITY_HIGHEST error\n");
            return -EINVAL;
        }
    
        /* Temporarily not support linux policy: SCHED_BATCH 3U, SCHED_RESET_ON_FORK 4U, SCHED_IDLE 5U, SCHED_DEADLINE 6U */
        // if ((policy == 0) || (policy == 3) || (policy == 4) || (policy == 5) || (policy == 6)) {
        if ((policy == 0) || (policy == 8) || (policy == 4) || (policy == 5) || (policy == 6))
        {
            PRINTK("-ENOSYS\n");
            return -ENOSYS;
        }
    
        if (id == 0)
        {
            id = (int)LOS_GetCurrProcessID();
        }
    
        PRINTK("SysSchedSetScheduler entry OsPermissionToCheck\n");
        ret = OsPermissionToCheck(id, LOS_GetCurrProcessID());
        if (ret < 0)
        {
            PRINTK("SysSchedSetScheduler  OsPermissionToCheck error\n");
            return ret;
        }
        PRINTK("leave SysSchedSetScheduler and entry OsSetProcessScheduler\n");
        return OsSetProcessScheduler(LOS_PRIO_PROCESS, id, prio, policy, TRUE);
    }
    
        int SysSetTaskTimeSlice(UINT32 taskId, int timeSliceNum)
    {
        PRINTK("\n----------------------------\n");
    
        PRINTK("entry SysSetTaskTimeSlice taskId=%d\n", taskId);
        if (OS_TID_CHECK_INVALID(taskId))
        {
            PRINTK("error set task timeslice error,taskId is not exist\n");
            return -1;
        }
        LosTaskCB *get = OsGetTaskCB(taskId);
    
        get->timeSlice = timeSliceNum;
        PRINTK("leave SysSetTaskTimeSlice\n");
    
        return 0;
    }
    
    int SysGetTaskTimeSlice(UINT32 taskId)
    {
        PRINTK("\n----------------------------\n");
    
        PRINTK("entry SysGetTaskTimeSlice taskId=%d\n", taskId);
        if (OS_TID_CHECK_INVALID(taskId))
        {
            PRINT_ERR("set task timeslice error,taskId is not exist\n");
            return -1;
        }
        LosTaskCB *get = OsGetTaskCB(taskId);
        
        PRINTK("leave SysGetTaskTimeSlice\n");
        return get->timeSlice;
    }
    
    
  • 3.修改kernel/liteos_a/kernel/base/core/los_process.c中函数
    STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
    {
        PRINTK("entry OsProcessSchedlerParamCheck\n");
        if (OS_PID_CHECK_INVALID(pid)) {
            return LOS_EINVAL;
        }
    
        if (which != LOS_PRIO_PROCESS) {
            return LOS_EOPNOTSUPP;
        }
    
        if (prio > OS_PROCESS_PRIORITY_LOWEST) {
            return LOS_EINVAL;
        }
    
        if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)&&(policy!=LOS_SCHED_SJF)) {
            return LOS_EOPNOTSUPP;
        }
        PRINTK("leave OsProcessSchedlerParamCheck\n");
        return LOS_OK;
    }
    
    STATIC INLINE VOID OsSchedTaskEnqueue(LosProcessCB *processCB, LosTaskCB *taskCB)
    {
        if (((taskCB->policy == LOS_SCHED_RR) && (taskCB->timeSlice != 0)) ||
            ((taskCB->taskStatus & OS_TASK_STATUS_RUNNING) && (taskCB->policy ==    LOS_SCHED_FIFO))) {
            OS_TASK_PRI_QUEUE_ENQUEUE_HEAD(processCB, taskCB);
        } else if(taskCB->policy==LOS_SCHED_SJF){
            LOS_DL_LIST *pos=NULL;
            uint8_t get=0U;
            LOS_DL_LIST_FOR_EACH(pos,&processCB->threadPriQueueList[taskCB->priority])
            {
                LosTaskCB *itemTask=OS_TCB_FROM_PENDLIST(pos);
                if(itemTask->timeSlice>taskCB->timeSlice)
                {
                    get=1U;
                    break;
                }
            }
            if(get==1U)
            {
                OS_TASK_PRI_QUEUE_ENQUEUE_POS(processCB,taskCB,pos->pstPrev);
            }else
            {
                OS_TASK_PRI_QUEUE_ENQUEUE(processCB, taskCB);
            }
        }else{
            OS_TASK_PRI_QUEUE_ENQUEUE(processCB, taskCB);
        }
        taskCB->taskStatus |= OS_TASK_STATUS_READY;
    }
    
    LITE_OS_SEC_TEXT_INIT VOID OsTaskSchedQueueEnqueue(LosTaskCB *taskCB, UINT16 status)
    {
        LosProcessCB *processCB = NULL;
    
        LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));
    
        processCB = OS_PCB_FROM_PID(taskCB->processID);
        if (!(processCB->processStatus & OS_PROCESS_STATUS_READY)) {
            if (((processCB->policy == LOS_SCHED_RR) && (processCB->timeSlice != 0)) ||
                ((processCB->processStatus & OS_PROCESS_STATUS_RUNNING) &&  (processCB->policy == LOS_SCHED_FIFO))) {
                OS_PROCESS_PRI_QUEUE_ENQUEUE_HEAD(processCB);
            }  else if(processCB->policy==LOS_SCHED_SJF){
                LOS_DL_LIST *pos=NULL;
                uint8_t get=0U;
                LOS_DL_LIST_FOR_EACH(pos,&processCB->pendList)
                {
                    LosProcessCB *itemProcess=OS_PCB_FROM_PENDLIST(pos);
                    if(itemProcess->timeSlice>processCB->timeSlice)
                    {
                        get=1U;
                        break;
                    }
                }
                if(get==1U)
                {
                    OS_PROCESS_PRI_QUEUE_ENQUEUE_POS(processCB,pos->pstPrev);
                }else
                {
                    OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB);
                }
            }else {
                OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB);
            }
            processCB->processStatus &= ~(status | OS_PROCESS_STATUS_PEND);
            processCB->processStatus |= OS_PROCESS_STATUS_READY;
        } else {
            LOS_ASSERT(!(processCB->processStatus & OS_PROCESS_STATUS_PEND));
            LOS_ASSERT((UINTPTR)processCB->pendList.pstNext);
            if ((processCB->timeSlice == 0) && (processCB->policy == LOS_SCHED_RR)) {
                OS_PROCESS_PRI_QUEUE_DEQUEUE(processCB);
                OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB);
            }
        }
        OsSchedTaskEnqueue(processCB, taskCB);
    }
    
    
  • 4.kernel/liteos_a/syscall/syscall_lookup.h中添加
    SYSCALL_HAND_DEF(__NR_set_task_timeslice,SysSetTaskTimeSlice,int, ARG_NUM_2)
    SYSCALL_HAND_DEF(__NR_get_task_timeslice,SysGetTaskTimeSlice,int, ARG_NUM_1)
    
  • 5.kernel/liteos_a/kernel/base/include/los_priqueue_pri.h中添加
    /**
     * @ingroup los_priqueue
     * @brief Insert a item to the priority queue.
     *
     * @par Description:
     * This API is used to insert a item to the priority queue according to the priority of this    item.
     * @attention
     * <ul>
     * <li>Param priqueueItem must point to valid memory.</li>
     * <li>Param priority rang is [0, OS_PRIORITY_QUEUE_NUM),included 0 and not included    OS_PRIORITY_QUEUE_NUM.</li>
     * </ul>
     * @param priQueueList   [IN] The list of priority queue.
     * @param bitMap         [IN] bit map of priority queue.
     * @param priqueueItem   [IN] The node of item to be inserted.
     * @param priority       [IN] Priority of the item be inserted.
     * @param pos [IN] The node of item to be inserted after pos 
     * @retval none.
     * @par Dependency:
     * <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
     * @see OsPriQueueDequeue.
     */
    extern VOID OsPriQueueEnqueuePos(LOS_DL_LIST *priQueueList,LOS_DL_LIST *pos, UINT32 *bitMap,LOS_DL_LIST *priqueueItem,  UINT32 priority);
    
  • 6.kernel/liteos_a/kernel/base/include/los_task_pri.h中添加
    #define OS_TASK_PRI_QUEUE_ENQUEUE_POS(processCB, taskCB,pos) OsPriQueueEnqueuePos((processCB)->threadPriQueueList,pos, &((processCB)->threadScheduleMap), &((taskCB)->pendList), (taskCB)->priority)
    
    #define OS_PROCESS_PRI_QUEUE_ENQUEUE_POS(processCB,pos) OsPriQueueEnqueuePos(g_priQueueList,pos, &g_priQueueBitmap, &((processCB)->pendList), (processCB)->priority)
    
  • 7.修改kernel/liteos_a/kernel/base/sched/sched_sq/los_priqueue.c中函数
    VOID OsPriQueueEnqueuePos(LOS_DL_LIST *priQueueList,LOS_DL_LIST *pos, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority)
    {
        /*
         * Task control blocks are inited as zero. And when task is deleted,
         * and at the same time would be deleted from priority queue or
         * other lists, task pend node will restored as zero.
         */
        LOS_ASSERT(priqueueItem->pstNext == NULL);
    
        if (LOS_ListEmpty(&priQueueList[priority])) {
            *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority;
        }
        LOS_ListAdd(pos, priqueueItem);
    }
    
  • 8.kernel/liteos_a/syscall/los_syscall.h中添加
    extern int SysSetTaskTimeSlice(UINT32 taskId,int timeSliceNum);
    extern int SysGetTaskTimeSlice(UINT32 taskId);
    
musl部分
  • 1.third_party/musl/arch/arm/bits/syscall.h.in中添加修改如下宏
    #define __NR_set_task_timeslice (__NR_OHOS_BEGIN + 21)
    #define __NR_get_task_timeslice (__NR_OHOS_BEGIN + 22)
    #define __NR_syscallend         (__NR_OHOS_BEGIN + 23)
    
  • 2.third_party/musl/include/pthread.h中添加
    int pthread_setTaskTimeslice(pthread_t ,int );
    int pthread_getTaskTimeslice(pthread_t);
    
  • 3.third_party/musl/include/sched.h中添加修改如下宏
    #define SCHED_SJF 3
    #define SCHED_BATCH 7
    
  • 4.third_party/musl/kernel/include/sched.h中添加修改如下宏
    #define SCHED_SJF 3
    #define SCHED_BATCH 7
    
  • 5.third_party/musl/kernel/obj/include/bits/syscall.h中添加修改如下宏
    #define __NR_set_task_timeslice (__NR_OHOS_BEGIN + 21)
    #define __NR_get_task_timeslice (__NR_OHOS_BEGIN + 22)
    #define __NR_syscallend         (__NR_OHOS_BEGIN + 23)
    
  • 6.修改third_party/musl/src/thread/pthread_create.c如下部分
    int __pthread_init_and_check_attr(const pthread_attr_t *restrict attrp, pthread_attr_t *attr)
    {
    	int policy = 0;
    	struct sched_param param = { 0 };
    	int c11 = (attrp == __ATTRP_C11_THREAD);
    	int ret;
    
    	if (attrp && !c11) memcpy(attr, attrp, sizeof(pthread_attr_t));
    
    	if (!attrp || c11) {
    		pthread_attr_init(attr);
    	}
    
    	if (!attr->_a_sched) {
    		ret = pthread_getschedparam(pthread_self(), &policy, &param);
    		if (ret) return ret;
    		attr->_a_policy = policy;
    		attr->_a_prio = param.sched_priority;
    	}
    
    	if (attr->_a_policy != SCHED_RR && attr->_a_policy != SCHED_FIFO&&attr->_a_policy !=    SCHED_SJF) {
    		return EINVAL;
    	}
    
    	if (attr->_a_prio < 0 || attr->_a_prio > PTHREAD_PRIORITY_LOWEST) {
    		return EINVAL;
    	}
    
    	return 0;
    }
    
  • 7.新建third_party/musl/src/thread/pthread_taskTimeslice.c
    #include "pthread_impl.h"
    int __pthread_setTaskTimeslice(pthread_t ppid,int num)
    {
        struct pthread* th=ppid;
        return __syscall(__NR_set_task_timeslice,th->tid,num);
    }
    int __pthread_getTaskTimeslice(pthread_t ppid)
    {
        struct pthread* th=ppid;
        return __syscall(__NR_get_task_timeslice,th->tid);
    }
    weak_alias(__pthread_setTaskTimeslice, pthread_setTaskTimeslice);
    weak_alias(__pthread_getTaskTimeslice, pthread_getTaskTimeslice);
    
  • 8.修改third_party/musl/src/thread/pthread_attr_setschedpolicy.c
    #include "pthread_impl.h"
    
    int pthread_attr_setschedpolicy(pthread_attr_t  *a, int policy)
    {
        printf("\nI use the musl pthead\n");//添加  此行
        if (policy != SCHED_RR && policy !=     SCHED_FIFO&&policy!=SCHED_SJF) {
    	    return EINVAL;
        }
        // printf("musl set policy %d\n",policy);// 添加此行
        a->_a_policy = policy;
        return 0;
    }
    
重新编译musl以及内核
  • 参考本章以及前几次实验

编写测试程序

project2/project2.c
#include "pthread.h"
#include "stdio.h"
#include "sched.h"
#include "syscall.h"
pthread_t ppid[4];
pthread_attr_t attr[4];

void *thread(void* threadId)
{
    int i;
    int policy;
    struct sched_param param;
    pthread_getschedparam(pthread_self(), &policy, &param);
    switch (policy)
    {
    case SCHED_SJF:
        printf("SCHED_SJF 1\n");
        break;
    case SCHED_RR:
        printf("SCHED_RR 1 \n");
        break;

    case SCHED_FIFO:
        printf("SCHED_FIFO 1\n");
        break;
    }

    int counts=pthread_getTaskTimeslice(ppid[(int)threadId]);


    for (i = 0; i < counts; i++)
    {
        // sleep(1);
        printf("Pthread %d :timeslice=%d\n",(int)threadId,i);
    }
    printf("Pthread %d exit\n",(int)threadId);
    return NULL;
}
int main()
{
    struct sched_param param;

    param.sched_priority = 31;
    for(int i=1;i<=3;i++)
    {
        pthread_attr_init(attr+i);

        pthread_attr_setinheritsched(attr+i, PTHREAD_EXPLICIT_SCHED);
        pthread_attr_setschedpolicy(attr+i, SCHED_SJF);
        if (0 != pthread_attr_setschedparam(attr+i, &param))
        {
            printf("setschedpolicy attr1 NG! \n");
        }
        pthread_create(ppid+i, attr+i, thread,(void*)i);
        pthread_setTaskTimeslice(ppid[i],30-5*i);
    }

    pthread_join(ppid[1], NULL);
    pthread_join(ppid[2], NULL);
    pthread_join(ppid[3], NULL);
    for(int i=1;i<=3;i++)
        pthread_attr_destroy(attr+i);
    return 0;
}

程序设置线程1,2,3的时间片数量为25,20,15.故执行顺序一个为线程3,2,1

project2/makefile
LITEOS_SOURCE_TOP_DIR = /home/hz/hos1.0
all:
	clang  -o project2 project2.c \
	-target arm-liteos \
	--sysroot=$(LITEOS_SOURCE_TOP_DIR)/prebuilts/lite/sysroot \
	-L ~/llvm/lib/clang/9.0.0/lib/arm-liteos/a7_softfp_neon-vfpv4 \
	-I $(LITEOS_SOURCE_TOP_DIR)/prebuilts/lite/sysroot/usr/include/arm-liteos \
	-L $(LITEOS_SOURCE_TOP_DIR)/prebuilts/lite/sysroot/usr/lib/arm-liteos
clean:
	rm -f *.o project2

执行make即可

烧录
烧录
  • 参照前几次实验

实验结果在这里插入图片描述

  • 主要看:
    • 1.执行project2
    • 2.线程3执行
    • 3.线程2执行
    • 4.线程1执行
  • 符合预想
    • 其他部分为修改文件过程调试的日志输出

实验分析

总体步骤:

  • 内核调度部分添加新的宏以及调度内容
  • 修改musl,使得新的调度能正确被设置
  • 添加修改和查询timeSlice的系统调用
  • 编写测试程序

实验总结

更进一步熟知了openharmony的liteos-a

参考文献

openharmony的官方gitee

附录

  • musl
  • kernel
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值