对鸿蒙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
- 1.如果代码是用repo下载的全量代码,进入prebuilts命令,执行
-
- 2.不是的话自行参照目录更改
----prebuilts/lite/sysroot ----/build ----**.sh ----/thirdparty ----/usr
- 2.不是的话自行参照目录更改
- 分别执行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
- 执行
- 1.下载Linux内核
-
- 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)
- 2.修改prebuilts/lite/sysroot/build/update_headers.py
-
- 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
- 先进入prebuilts/lite/sysroot/thirdparty,然后执行
- 3.现在执行thirdparty_headers.sh会报错
-
- 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
- 执行
- 4.因为使用1.1.0release的prebuilt添加了一些新组件,进入third_party
-
- 5.现在进入prebuilts/lite/sysroot/build/
- 执行
mkdir musl mkdir musl/include ./thirdparty_headers.sh ./build_musl_clang.sh cp -r usr ../
- 执行
- 5.现在进入prebuilts/lite/sysroot/build/
开始添加新调度方法
内核部分
- 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, ¶m); 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, ¶m);
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, ¶m))
{
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