From 0809daf4dcf7d6fa20a948980f2cc4b3e052c960 Mon Sep 17 00:00:00 2001 From: liujunxian Date: Mon, 12 Dec 2022 19:20:49 +0800 Subject: [PATCH] update docs of UniProton Signed-off-by: liujunxian --- ...37\350\203\275\350\256\276\350\256\241.md" | 184 ++ ...45\345\217\243\350\257\264\346\230\216.md" | 2255 +++++++++++++++++ ...7\345\215\227-\346\246\202\350\277\260.md" | 12 + docs/zh/docs/UniProton/figures/FCS.png | Bin 0 -> 19278 bytes .../UniProton/figures/MemoryApplication.png | Bin 0 -> 6386 bytes .../docs/UniProton/figures/MemoryRelease.png | Bin 0 -> 10618 bytes .../docs/UniProton/figures/pend_semaphore.png | Bin 0 -> 32691 bytes .../docs/UniProton/figures/post_semaphore.png | Bin 0 -> 26707 bytes 8 files changed, 2451 insertions(+) create mode 100644 "docs/zh/docs/UniProton/UniProton\345\212\237\350\203\275\350\256\276\350\256\241.md" create mode 100644 "docs/zh/docs/UniProton/UniProton\346\216\245\345\217\243\350\257\264\346\230\216.md" create mode 100644 "docs/zh/docs/UniProton/UniProton\347\224\250\346\210\267\346\214\207\345\215\227-\346\246\202\350\277\260.md" create mode 100644 docs/zh/docs/UniProton/figures/FCS.png create mode 100644 docs/zh/docs/UniProton/figures/MemoryApplication.png create mode 100644 docs/zh/docs/UniProton/figures/MemoryRelease.png create mode 100644 docs/zh/docs/UniProton/figures/pend_semaphore.png create mode 100644 docs/zh/docs/UniProton/figures/post_semaphore.png diff --git "a/docs/zh/docs/UniProton/UniProton\345\212\237\350\203\275\350\256\276\350\256\241.md" "b/docs/zh/docs/UniProton/UniProton\345\212\237\350\203\275\350\256\276\350\256\241.md" new file mode 100644 index 000000000..a79fcfe97 --- /dev/null +++ "b/docs/zh/docs/UniProton/UniProton\345\212\237\350\203\275\350\256\276\350\256\241.md" @@ -0,0 +1,184 @@ +# UniProton功能设计 + + + +- [UniProton功能设计](#uniproton功能设计) + + - [支持任务管理](#支持任务管理) + + - [支持事件管理](#支持事件管理) + + - [支持队列管理](#支持队列管理) + + - [支持硬中断管理](#支持硬中断管理) + + - [支持内存管理](#支持内存管理) + + ​ [FSC内存算法](#fsc内存算法) + + ​ [核心思想](#核心思想) + + ​ [内存申请](#内存申请) + + ​ [内存释放](#内存释放) + + - [支持定时器管理](#支持定时器管理) + + - [支持信号量管理](#支持信号量管理) + + - [支持异常管理](#支持异常管理) + + - [支持CPU占用率统计](#支持cpu占用率统计) + + - [支持STM32F407ZGT6开发板](#支持stm32f407zgt6开发板) + + - [支持OpenAMP混合部署](#支持openamp混合部署) + + - [支持POSIX标准接口](#支持posix标准接口) + + + +## 支持任务管理 + +UniProton是一个单进程支持多线程的操作系统。在UniProton中,一个任务表示一个线程。UniProton中的任务为抢占式调度机制,而非时间片轮转调度方式。高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务挂起或阻塞后才能得到调度。 + +UniProton的任务一共有32个优先级(0-31),最高优先级为0,最低优先级为31。每个优先级可以创建多个任务。 + +UniProton任务管理模块提供任务创建、任务删除、任务挂起、任务恢复、任务延时、锁任务调度、解锁任务调度、当前任务ID获取、任务私有数据获取与设置、查询指定任务正在Pending的信号量ID、查询指定任务状态、上下文信息、任务通用信息、任务优先级设定与获取、调整指定优先级的任务调度顺序、注册及取消任务创建钩子、任务删除钩子、任务切换钩子等功能。UniProton在初始化阶段,默认会创建一个最低优先级的IDLE任务,用户在没有处于运行态的任务时,IDLE任务被运行。 + +## 支持事件管理 + +事件机制可以实现线程之间的通讯。事件通讯只能是事件类型的通讯,无数据传输。 + +UniProton事件作为任务的扩展,实现任务之间的通讯。每个任务支持32种类型事件(32个 bit位,每bit代表一种事件类型)。 + +UniProton提供读取本任务事件和写指定任务事件的功能。读事件时可以同时读取多种事件,也可以只读取一种事件,写事件时也可以同时写一种或多种类型事件。 + +## 支持队列管理 + +队列(Queue),又称消息队列,是线程间实现通信的一种方式,实现了数据的存储和传递功能。根据优先级可以将数据写入到队列头或队列尾,但只能从队列的头处读取数据。 + +UniProton创建队列时,根据用户传入队列长度和消息单元大小来开辟相应的内存空间以供该队列使用。在队列控制块中维护一个头指针Head和一个尾指针Tail来表示当前队列中数据存储情况。头指针Head表示队列中被占用消息的起始地址,尾指针Tail表示队列中空闲消息的起始地址。 + +## 支持硬中断管理 + +硬中断是由硬件触发的会改变系统运行轨迹的一个电平信号,硬中断用于通知CPU某个硬件事件的发生。硬中断一般分为可屏蔽中断和不可屏蔽中断(NMI)两种。 + +硬中断的优先级高于所有任务,其内部也有不同的优先级,当同时有多个硬中断被触发时,最高优先级的硬中断总是优先得到响应。高优先级硬中断是否能打断正在执行的低优先级硬中断(即中断嵌套),视不同芯片平台而异。 + +出于任务延时、软件定时器等需要,OS会在初始化阶段,创建1个Tick硬中断,其实质是一个周期性的硬件定时器。 + +## 支持内存管理 + +内存管理主要工作是动态的划分并管理用户分配好的大片内存区间。当程序某一部分需要使用内存,可以通过操作系统的内存申请函数索取指定大小内存块,一旦使用完毕,通过内存释放函数归还所占用内存,使之可以重复使用。 + +目前UniProton提供了FSC内存算法,该算法优缺点及应用场景如下表所示: + +| 内存算法 | 优点 | 缺点 | 应用场景 | +| :----------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------ | ------------------------------------ | +| 类型私有FSC算法 | 内存控制块信息占用内存较少,支持最小4字节对齐的内存块大小申请;支持相邻内存块的快速分割合并,无内存碎片。 | 内存申请和内存释放的效率较低。 | 能够灵活适应各种产品的场景(核内)。 | + +如下简要描述一下FSC内存算法: + +### FSC内存算法 + +#### 核心思想 + +对于申请的内存大小为uwSize,如果用二进制,则表示为0b{0}1xxx,{0}表示1前面可能有0个或多个零。无论1后面xxx为何内容,如果将1变成10,xxx则全部变成0,则总会出现10yyy > 1xxx(此处yyy表示xxx的对应位全部变成0)。 + +我们可以直接得到最左边的1的下标。下标值或者从高位到低位依次为0-31(BitMap),或者从低位到高位依次为0-31(uwSize)。如果32位寄存器从高位到低位的bit位的下标依次为0-31,则0x80004000的最左边1的下标为0。于是我们可以维护一个空闲链表头数组(元素数不超过31),以内存块大小最左边的1的下标做为链表头的数组索引,即将所有最左边的1的下标相同的内存块挂接在同一个空闲链表中。 + +如:索引为2的链表可挂接的空闲块大小为4、5、6、7;索引为N的链表可挂接的空闲块大小为2N到2 N+1-1。 + +![](./figures/FCS.png) + +#### 内存申请 + +当申请uwSize大小的内存时,首先利用汇编指令得到最左边的1的下标,假定为n。为确保空闲链表中的第一个空闲内存块满足uwSize,从索引为n+1开始搜索。若n+1所属空闲链表不为空,则取该链表中的第一个空闲块。若n+1链表为空,则判断n+2链表,依次类推,直到找到非空链表或索引达到31。 + +为避免for循环逐级判断空闲链表是否为空,定义一个32位的BitMap全局变量。若索引n的空闲链表非空,则BitMap的下标为n的位置1,否则清0。BitMap的下标为31的位在初始化时直接置1。于是查找从n+1开始的第一个非空闲链表,可以首先将BitMap复本的0到n位清零,然后获取复本的最左边的1的下标,若不等于31,即为第一个空闲链表非空的数组索引。 + +所有的空闲块都以双向链表形式,串接在空闲链表中。若从链表中获取的第一个空闲块比较大,即分割出一个usSize的内存块后,剩下的空间至少可做一次最小分配。则将剩余的空闲块调整到对应的空闲链表中。 + + ![](./figures/MemoryApplication.png) + +内存控制头中记录有空闲内存块的大小(包括控制头本身)。内存控制头中有一个复用成员,位于最首部时。当内存块空闲时,作为指向后一个空闲内存块的指针;当内存块占用时,存放魔术字,表示该内存块非空闲。为避免魔术字与指针冲突(与地址值相同),高低4位均为0xf。因为已分配的内存块起始地址需按4字节对齐,所以不存在冲突。 + +#### 内存释放 + +当释放内存时,需要将前后相邻的空闲块进行合并。首先,通过判断控制头中的魔术字,确认地址参数(pAddr)的合法性。通过首地址加偏移值的方式,得到后邻的内存块控制头的起始地址。若后邻内存块是空闲的,则将后邻内存块从所属空闲链表中删除,调整当前内存块的大小。 + +为了使内存释放时能迅速找到前邻的内存块控制头,及判断前邻的内存块是否空闲。内存控制头中增加一个成员,标记前邻的内存块是否空闲。可在内存申请的时,将后邻的该标记设置为占用态(若空闲内存块被分割成两块,前一块为空闲,将当前内存块的该标记设置为空闲态);在内存释放时,将后邻的该标记设置为空闲态。释放当前内存时,若前邻的内存块标记为使用,则不需要合并前邻的内存块;若前邻的内存块标记为空闲,则需要进行合并。若某个内存块为空闲时,则将其后邻控制块的标记设为到本控制块的距离值。 + + ![](./figures/MemoryRelease.png) + +## 支持定时器管理 + +定时器管理是为满足产品定时业务需要,UniProton提供了软件定时器功能。 + +对于软件定时器,是基于Tick实现,所以定时周期必须为Tick的整数倍,在Tick处理函数中进行软件定时器的超时扫描。 + +目前提供的软件定时器接口,可以完成定时器创建,启动,停止,重启,删除操作。 + +## 支持信号量管理 + +信号量(Semaphore)常用于协助一组互相竞争的任务来访问临界资源,在需要互斥的场合作为临界资源计数使用,根据临界资源使用场景分为核内信号量和核间信号量。 + +信号量对象有一个内部计数器,它支持如下两种操作: + +- 申请(Pend):Pend 操作等待指定的信号量,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其他线程发布该信号量,等待的容忍时间可设定。 + + +- 释放(Post):Post操作发布指定的信号量,若无任务等待该信号量,则直接将计数器加1返回。否则唤醒为此信号量挂起的任务列表中的第一个任务(最早阻塞的)。 + + +通常一个信号量的计数值用于对应有效的资源数,表示剩余可被占用的互斥资源数。其值的含义如下有两种情况: + +- 为0值:表示没有积累下来的Post操作,且有可能有在此信号量上阻塞的任务。 + + +- 为正值:表示有一个或多个Post下来的发布操作。 + + +## 支持异常管理 + +UniProton中的异常接管属于维测特性,其主要目的是在系统出现异常后,记录尽可能多的异常现场信息,便于后续问题定位。同时提供异常时的钩子函数,便于用户能够在异常发生时做一些用户化的特殊处理。其主要功能是接管内部异常处理或者外部硬件异常。 + +## 支持CPU占用率统计 + +UniProton中的系统CPU占用率(CPU Percent)是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~10000,其精度为万分比。10000表示系统满负荷运转。 + +UniProton中的线程CPU占用率指单个线程的CPU占用率,用于表示单个线程在一段时间内的闲忙程度。线程CPU占用率的有效表示范围为0~10000,其精度为万分比。10000表示在一段时间内系统一直在运行该线程。单核系统所有线程(包括中断和空闲任务)的CPU之和为10000。 + +UniProton的系统级CPU占用率依赖于Tick模块,通过Tick采样IDLE任务或IDLE软中断计数来实现 + +## 支持STM32F407ZGT6开发板 + +支持开发板主要涉及OS内核外围的启动流程和单板驱动,目录结构如下: + +├─apps # 基于UniProton实时OS编程的demo程序。 + +│ ├─hello_world # hello_world示例程序。 + +├─bsp # 提供的板级驱动与OS对接。 + +├─build # 提供编译脚本编译出最终镜像。 + +├─config # 配置选项,供用户调整运行时参数。 + +├─include # UniProton实时部分提供的编程接口API。 + +└─libs # UniProton实时部分的静态库,build目录中的makefile示例已经将头文件和静态库的引用准备好,应用可直接使用。 + +## 支持OpenAMP混合部署 + +OpenAMP是一个开源软件框架,旨在通过非对称多处理器的开源解决方案,来标准化异构嵌入式系统中操作环境之间的交互。OpenAMP包括如下四大组件: + +1. remoteproc:管理从核的生命周期,管理共享内存、通信使用的buffer、vring等资源,初始化rpmsg和virtio。 +2. rpmsg:实现多核通信的通道,基于virtio实现。 +3. virtio:通过一套虚拟IO实现主从核的驱动程序通信,是一种半虚拟化技术。 +4. libmetal:屏蔽操作系统实现细节,提供通用用户API访问设备,处理设备中断、内存请求。 + +## 支持POSIX标准接口 + +UniProton支持posix标准接口 \ No newline at end of file diff --git "a/docs/zh/docs/UniProton/UniProton\346\216\245\345\217\243\350\257\264\346\230\216.md" "b/docs/zh/docs/UniProton/UniProton\346\216\245\345\217\243\350\257\264\346\230\216.md" new file mode 100644 index 000000000..dfc475a0b --- /dev/null +++ "b/docs/zh/docs/UniProton/UniProton\346\216\245\345\217\243\350\257\264\346\230\216.md" @@ -0,0 +1,2255 @@ +# UniProton接口说明 + + + +- [UniProton接口说明](#UniProton接口说明) + + - [任务](#任务) + + [创建并激活任务](#创建并激活任务) + + [删除任务](#删除任务) + + [挂起任务](#挂起任务) + + [恢复任务](#恢复任务) + + [任务延时](#任务延时) + + [锁任务调度](#锁任务调度) + + [恢复任务调度的锁](#恢复任务调度的锁) + + [任务PID合法性检查](#任务pid合法性检查) + + [任务私有数据获取](#任务私有数据获取) + + [查询本核指定任务正在PEND的信息量](#查询本核指定任务正在pend的信息量) + + [查询任务状态](#查询任务状态) + + [查询任务上下文信息](#查询任务上下文信息) + + [查询任务基本信息](#查询任务基本信息) + + [任务优先级获取](#任务优先级获取) + + [任务优先级设定](#任务优先级设定) + + [调整指定优先级的任务调度顺序](#调整指定优先级的任务调度顺序) + + - [事件](#事件) + + [写事件](#写事件) + + [读事件](#读事件) + + - [队列](#队列) + + [创建队列](#创建队列) + + [读队列](#读队列) + + [写队列](#写队列) + + [删除队列](#删除队列) + + [查询队列的历史最大使用长度](#查询队列的历史最大使用长度) + + [查询指定源PID的待处理消息个数](#查询指定源pid的待处理消息个数) + + - [中断](#中断) + + [创建硬中断](#创建硬中断) + + [硬中断属性设置](#硬中断属性设置) + + [删除硬中断](#删除硬中断) + + [使能硬中断](#使能硬中断) + + [屏蔽硬中断](#屏蔽硬中断) + + [恢复指定硬中断](#恢复指定硬中断) + + [禁止硬中断](#禁止硬中断) + + [恢复硬中断](#恢复硬中断) + + [响应硬中断](#响应硬中断) + + [触发硬中断](#触发硬中断) + + [清除硬中断](#清除硬中断) + + - [定时器](#定时器) + + [定时器创建](#定时器创建) + + [定时器删除](#定时器删除) + + [定时器启动](#定时器启动) + + [定时器停止](#定时器停止) + + [定时器重启](#定时器重启) + + [软件定时器组创建](#软件定时器组创建) + + - [信号量](#信号量) + + [信号量创建](#信号量创建) + + [信号量删除](#信号量删除) + + [Pend信号量](#pend信号量) + + [Post信号量](#post信号量) + + [信号量计数值重置](#信号量计数值重置) + + [信号量计数值获取](#信号量计数值获取) + + [信号量阻塞任务PID获取](#信号量阻塞任务pid获取) + + - [异常](#异常) + + [用户注册异常处理钩子](#用户注册异常处理钩子) + + - [CPU占用率](#cpu占用率) + + [获取当前cpu占用率](#获取当前cpu占用率) + + [获取指定个数的线程的CPU占用率](#获取指定个数的线程的cpu占用率) + + [设置CPU占用率告警阈值](#设置cpu占用率告警阈值) + + [查询CPUP告警阈值和告警恢复阈值](#查询cpup告警阈值和告警恢复阈值) + + [注册CPUP告警回调函数](#注册cpup告警回调函数) + + - [OS启动](#os启动) + + [main函数入口](#main函数入口) + + [用户业务入口](#用户业务入口) + + [硬件驱动初始化入口](#硬件驱动初始化入口) + + [硬件启动流程入口](#硬件启动流程入口) + + - [openamp](#openamp) + + [初始化openamp资源函数](#初始化openamp资源函数) + + [消息接收函数](#消息接收函数) + + [消息发送函数](#消息发送函数) + + [释放openamp资源](#释放openamp资源) + + - [POSIX接口](#posix接口) + + [任务管理](#任务管理) + + ​ [pthread_attr_init](#pthread_attr_init) + + ​ [pthread_attr_destroy](#pthread_attr_destroy) + + ​ [pthread_attr_setstackaddr](#pthread_attr_setstackaddr) + + ​ [pthread_attr_getstackaddr](#pthread_attr_getstackaddr) + + ​ [pthread_attr_getstacksize](#pthread_attr_getstacksize) + + ​ [pthread_attr_setstacksize](#pthread_attr_setstacksize) + + ​ [pthread_attr_getinheritsched](#pthread_attr_getinheritsched) + + ​ [pthread_attr_setinheritsched](#pthread_attr_setinheritsched) + + ​ [pthread_attr_getschedpolicy](#pthread_attr_getschedpolicy) + + ​ [pthread_attr_setschedpolicy](#pthread_attr_setschedpolicy) + + ​ [pthread_attr_getdetachstate](#pthread_attr_getdetachstate) + + ​ [pthread_attr_setdetachstate](#pthread_attr_setdetachstate) + + ​ [pthread_create](#pthread_create) + + ​ [pthread_cancel](#pthread_cancel) + + ​ [pthread_testcancel](#pthread_testcancel) + + ​ [pthread_setcancelstate](#pthread_setcancelstate) + + ​ [pthread_setcanceltype](#pthread_setcanceltype) + + ​ [pthread_exit](#pthread_exit) + + ​ [pthread_cleanup_push](#pthread_cleanup_push) + + ​ [pthread_cleanup_pop](#pthread_cleanup_pop) + + ​ [pthread_setschedprio](#pthread_setschedprio) + + ​ [pthread_self](#pthread_self) + + ​ [pthread_equal](#pthread_equal) + + ​ [sched_yield](#sched_yield) + + ​ [sched_get_priority_max](#sched_get_priority_max) + + ​ [sched_get_priority_min](#sched_get_priority_min) + + ​ [pthread_join](#pthread_join) + + ​ [pthread_detach](#pthread_detach) + + ​ [pthread_key_create](#pthread_key_create) + + ​ [pthread_setspecific](#pthread_setspecific) + + ​ [pthread_getspecific](#pthread_getspecific) + + ​ [pthread_key_delete](#pthread_key_delete) + + [信号量管理](#信号量管理) + + ​ [sem_init](#sem_init) + + ​ [sem_destroy](#sem_destroy) + + ​ [sem_open](#sem_open) + + ​ [sem_close](#sem_close) + + ​ [sem_wait](#sem_wait) + + ​ [sem_trywait](#sem_trywait) + + ​ [sem_timedwait](#sem_timedwait) + + ​ [sem_post](#sem_post) + + ​ [sem_getvalue](#sem_getvalue) + + [互斥量管理](#互斥量管理) + + ​ [pthread_mutexattr_init](#pthread_mutexattr_init) + + ​ [pthread_mutexattr_destroy](#pthread_mutexattr_destroy) + + ​ [pthread_mutexattr_settype](#pthread_mutexattr_settype) + + ​ [pthread_mutexattr_gettype](#pthread_mutexattr_gettype) + + ​ [pthread_mutexattr_setprioceiling](#pthread_mutexattr_setprioceiling) + + ​ [pthread_mutexattr_getprioceiling](#pthread_mutexattr_getprioceiling) + + ​ [pthread_mutexattr_setprotocol](#pthread_mutexattr_setprotocol) + + ​ [pthread_mutexattr_getprotocol](#pthread_mutexattr_getprotocol) + + ​ [pthread_mutex_init](#pthread_mutex_init) + + ​ [pthread_mutex_destroy](#pthread_mutex_destroy) + + ​ [pthread_mutex_lock](#pthread_mutex_lock) + + ​ [pthread_mutex_trylock](#pthread_mutex_trylock) + + ​ [pthread_mutex_timedlock](#pthread_mutex_timedlock) + + ​ [pthread_mutex_unlock](#pthread_mutex_unlock) + + [读写锁编程](#读写锁编程) + + ​ [pthread_rwlock_init](#pthread_rwlock_init) + + ​ [pthread_rwlock_destroy](#pthread_rwlock_destroy) + + ​ [pthread_rwlock_rdlock](#pthread_rwlock_rdlock) + + ​ [pthread_rwlock_tryrdlock](#pthread_rwlock_tryrdlock) + + ​ [pthread_rwlock_timedrdlock](#pthread_rwlock_timedrdlock) + + ​ [pthread_rwlock_wrlock](#pthread_rwlock_wrlock) + + ​ [pthread_rwlock_trywrlock](#pthread_rwlock_trywrlock) + + ​ [pthread_rwlock_timedwrlock](#pthread_rwlock_timedwrlock) + + ​ [pthread_rwlock_unlock](#pthread_rwlock_unlock) + + [时钟管理](#时钟管理) + + ​ [clock_gettime](#clock_gettime) + + ​ [clock_settime](#clock_settime) + + ​ [clock_getres](#clock_getres) + + ​ [nanosleep](#nanosleep) + + ​ [timer_create](#timer_create) + + ​ [timer_delete](#timer_delete) + + ​ [timer_settime](#timer_settime) + + ​ [timer_gettime](#timer_gettime) + + [内存管理](#内存管理) + + ​ [malloc](#malloc) + + ​ [free](#free) + + + +## 任务 + +### 创建并激活任务 + +在OS启动之前(比如在uniAppInit)中创建的任务,只是简单地加入就绪队列。 OS启动后创建的任务,如果优先级高于当前任务且未锁任务,则立即发生任务调度并被运行,否则加入就绪队列,等待执行。 + +**输入**: 任务创建参数,包括任务名、任务栈大小、任务优先级、任务处理函数等。 + +**处理**: + +1. 申请任务栈空间,初始化任务栈,置栈顶魔术字。 +2. 初始化任务上下文。 +3. 初始化任务控制块。 +4. 激活任务,任务是否马上能得到执行,取决于OS是否已经启动、优先级是否高于当前任务且没有锁任务调度、当前线程是否为硬中断。 + +**输出** : + +- 成功:任务ID,若任务具备执行条件,则直接运行任务,否则将任务挂入就绪队列。 + +- 失败:提示错误码。 + +### 删除任务 + + 删除任务并释放任务资源。 + +**输入**:任务ID。 + +**处理**: + +1. 检查任务是否具备删除条件,如锁任务调度情况下不允许删除任务。 +2. 如果任务处于阻塞状态,从对应的阻塞队列中摘除。 +3. 释放任务控制块。 +4. 释放任务栈空间。 +5. 从就绪队列中载入最高优先级的任务,若具备调度条件,则执行。 + +**输出**: + +- 成功:若具备调度条件,则执行就绪队列中的最高任务; + +- 失败:返回错误码。 + +### 挂起任务 + + 挂起任务。 + +**输入**:任务ID。 + +**处理**:将指定任务从就绪队列中摘除,若指定任务处于Running态,则会触发任务切换。 + +**输出**: + +- 成功:挂起指定任务。 + +- 失败:返回错误码。 + +### 恢复任务 + +恢复挂起的任务。 + +**输入**:任务ID。 + +**处理**:恢复挂起的任务,若任务仍处于延时、阻塞态,则只是取消挂起态,并不加入就绪队列。 + +**输出**: + +- 成功:取消任务挂起状态。 +- 失败:返回错误码。 + +### 任务延时 + +将当前任务延时指定时间。 + +**输入**:延时时间。 + +**处理**: + +1. 延时时间转换成OS的Tick数。 +2. 将当前任务从就绪队列中摘除,置成延时态。 +3. 从就绪队列中载入最高优先级的任务,并执行。 +4. Tick中断处理函数中判断任务的延时时间是否已经足够,如果足够,将任务加入就绪队列。 + +**输出**: + +- 成功:当前任务切出,就绪队列中的最高优先级任务切入。 +- 失败:返回错误码。 + +### 锁任务调度 + +禁止任务之间的切换。 + +**输入**:锁任务调度请求。 + +**处理**: + +1. 若有任务切换请求,将其清除。 +2. 锁任务调度次数++。 + +**输出**: 任务之间无法切换。 + +### 恢复任务调度的锁/解锁状态 + +与锁任务调度配对使用,是否解锁任务调度,取决于最近一次锁任务调度前,是否允许任务调度。 + +**输入**:恢复任务调度的锁/解锁状态请求。 + +**处理**: + +1. 锁任务调度次数--。 +2. 若锁任务调度次数等于0,则发起任务调度。 + +**输出**:若最近一次锁任务调度前,允许任务调度,则从就绪队列中载入最高优先级任务,并执行。否则,维持原状,不能发生任务切换。 + +### 任务PID合法性检查 + +检查指定任务PID是否合法。 + +**输入**:任务PID。 + +**处理**:判断输入的任务PID是否超过最大任务PID号或是否已创建。 + +**输出**: + +- TRUE :任务PID有效。 +- FALSE:任务PID无效。 + +### 任务私有数据获取 + +获取当前任务的私有数据。 + +**输入**:无。 + +**处理**:将任务TCB中记录的任务私有数据返回。 + +**输出**:任务私有数据。 + +### 查询本核指定任务正在PEND的信号量 + +查询指定任务正在PEND的信号量ID。 + +**输入**:任务PID。 + +**处理**: 根据任务状态和任务控制块,判断任务是否PEND在信号量,以及PEND的信号量ID。 + +**输出**: + +- 成功:返回信号量ID。 +- 失败:返回错误码。 + +### 查询任务状态 + +获取指定任务的状态。 + +**输入**:任务PID。 + +**处理**:将指定任务的TCB中记录的任务状态字段返回。 + +**输出**: + +- 成功:返回任务状态信息。 +- 失败:返回错误码。 + +### 查询任务上下文信息 + +获取指定任务的上下文信息。 + +**输入**:任务PID。 + +**处理**: 将指定任务的TCB中记录的任务上下文信息返回。 + +**输出**: + +- 成功:返回任务上下文信息。 +- 失败:返回错误码。 + +### 查询任务基本信息 + +获取任务基本信息,包括任务切换时的PC,SP、任务状态、优先级、任务栈大小、栈顶值,任务名等。 + +**输入**:任务PID,用于存放任务基本信息查询结果的缓冲区 + +**处理**: 将指定任务的TCB中记录的任务基本信息返回。 + +**输出**: + +- 成功:返回任务基本信息。 +- 失败:返回错误码。 + +### 任务优先级获取 + +获取指定任务的优先级。 + +**输入**:任务PID + +**处理**:将指定任务的TCB中记录的优先级字段返回。 + +**输出**: + +- 成功:返回任务优先级信息。 +- 失败:返回错误码。 + +### 任务优先级设定 + +设置指定任务的优先级。 + +**输入**:任务PID、优先级值 + +**处理**:将输入的任务优先级信息存入指定任务TCB中优先级字段 + +**输出**: + +- 成功:指定任务的优先级被修改。 +- 失败:返回错误码。 + +### 调整指定优先级的任务调度顺序 + +设置指定任务的优先级。 + +**输入**:指定的优先级、指定需要调整调度顺序的任务,用于保存被调整到队首的任务ID的缓冲。 + +**处理**:若指定要调整调度顺序的任务为TASK_NULL_ID,则优先级队列中的第一个就绪任务调整至队尾;否则,将指定要调整调度顺序的任务调整至优先级队列的队首。 + +**输出**: + +- 成功:指定优先级的任务调度顺序被修改。 +- 失败:返回错误码。 + +## 事件 + +### 写事件 + +写事件操作实现对指定任务写入指定类型的事件,可以一次同时写多个事件。 + +**输入**:任务ID、事件号。 + +**处理**: + +1. 对指定任务事件类型写上输入事件。 +2. 判断目的任务是否正在接收等待事件,且其等待的事件是否已经符合唤醒条件(唤醒条件即读取的事件已经发生)。 +3. 如果符合唤醒条件,则需清除任务读事件状态。 +4. 如果符合唤醒条件,则需清除任务读事件状态。 +5. 清除任务超时状态。 +6. 在任务没有被挂起的情况下,需要将任务加入就绪队列并尝试任务调度。 + +**输出**: + +- 成功:事件写入成功。 +- 失败:错误码。 + +### 读事件 + +读事件操作可以根据入参事件掩码类型读取单个或者多个事件。 + +**输入**:要读取的事件掩码、读取事件所采取的策略、超时时间、接收事件的指针。 + +**处理**: + +1. 根据入参事件掩码类型对自身任务输入读取事件类型。 +2. 判断事件读取模式,是读取输入的所有事件还是其中的任意一种事件。 +3. 根据读取模式,判断期望的事件是否满足读取情况。 +4. 判断事件等待模式:如果为等待事件模式则根据模式来设置相应的超时时间;如果为非等待模式则事件读取失败。 +5. 如果需要等待阻塞读取,则需要将自己的任务从就绪列表中删除,并进行任务调度。 +6. 读取成功后,清除读取的事件类型,并且把事件类型返回。 + +**输出**: + +- 成功:读事件成功,事件指针赋值。 +- 失败:错误码 + + + +## 队列 + +### 创建队列 + +创建一个队列,创建时可以设定队列长度和队列结点大小。 + +**输入**: 队列节点个数、每个队列节点大小、队列ID指针。 + +**处理**: + +1. 申请一个空闲的队列资源。 +2. 申请队列所需内存。 +3. 初始化队列配置。 + +**输出**: + +- 成功:队列ID。 +- 失败:错误码。 + +### 读队列 + +读指定队列的数据。 + +**输入**:队列ID、缓冲区指针、长度指针、超时时间。 + +**处理**: + +1. 获取指定队列控制块。 +2. 读队列PEND标志,根据缓冲区大小填入队列数据。 +3. 修改队列头指针。 + +**输出**: + +- 成功:缓冲区内填入队列数据。 +- 失败:错误码。 + +### 写队列 + +写数据到指定队列。 + +**输入**: 队列ID、缓冲区指针、缓冲区长度、超时时间、优先级。 + +**处理**: + +1. 获取指定队列控制块。 +2. 读队列PEND标志,选取消息节点,初始化消息节点并拷贝数据。 +3. 队列读资源计数器加一。 + +**输出**: + +- 成功:写入队列数据成功。 +- 失败:错误码。 + +### 删除队列 + +删除一个消息队列,删除后队列资源被回收。 + +**输入**:队列ID。 + +**处理**: + +1. 获取指定队列控制块,确保队列未在使用中。 +2. 释放队列内存。 + +**输出**: + +- 成功:删除队列成功。 +- 失败:错误码 + +### 查询队列的历史最大使用长度 + +获取从队列创建到删除前的历史最大使用长度。 + +**输入**:队列ID、队列节点使用峰值指针。 + +**处理**: + +1. 获取指定队列控制块。 +2. 将队列节点使用峰值赋值到指针参数。 + +**输出**: + +- 成功:获取峰值成功。 +- 失败:错误码 + +### 查询指定源PID的待处理消息个数 + +从指定队列中,获取指定源PID的待处理消息个数。 + +**输入**:队列ID、线程PID、待处理的消息个数指针。 + +**处理**: + +1. 获取指定队列控制块。 +2. 遍历队列查询待处理的消息个数,赋值到指针变量。 + +**输出**: + +- 成功:获取待处理的消息个数成功。 +- 失败:错误码。 + +## 中断 + +### 创建硬中断 + +硬中断在使用前,必须先创建。 + +**输入**:硬中断的创建参数,如:硬中断号(与芯片相关)、硬中断优先级、硬中断处理函数等。 + +**处理**:根据硬中断号设置硬中断优先级、处理函数。 + +**输出**: + +- 成功:硬中断触发后,CPU能够响应该硬中断,并回调硬中断处理函数。 +- 失败:返回错误码。 + +### 硬中断属性设置 + +在创建硬中断前,需要设置硬中断的模式,包括独立型(#OS_HWI_MODE_ENGROSS)和组合型(#OS_HWI_MODE_COMBINE)两种配置模式。 + +**输入**:硬中断号、硬中断模式。 + +**处理**:根据硬中断号设置硬中断的模式; + +**输出**: + +- 成功:指定的硬中断号被设置好硬中断模式。 +- 失败:返回错误码。 + +### 删除硬中断 + +屏蔽相应硬中断或事件,取消硬中断处理函数的注册。 + +**输入**:硬中断号。 + +**处理**:取消指定硬中断的处理函数与中断号的绑定关系。 + +**输出**:硬中断被删除,当硬中断信号触发后,CPU不会响应该中断。 + +### 使能硬中断 + +使能指定的硬中断。 + +**输入**:硬中断号。 + +**处理**:将指定硬中断的使能位置位。 + +**输出**:指定的硬中断被使能,当硬中断信号触发后,CPU会响应该中断。 + +### 屏蔽硬中断 + +屏蔽指定的硬中断。 + +**输入**:硬中断号。 + +**处理**:清除指定硬中断的使能位。 + +**输出**:指定的硬中断被屏蔽,当硬中断信号触发后,CPU不会响应该中断。 + +### 恢复指定硬中断 + +恢复指定的硬中断。 + +**输入**:硬中断号、中断使能寄存器的保存值。 + +**处理**:还原指定硬中断的使能位。 + +**输出**:指定中断的使能位恢复为指定状态。 + +### 禁止硬中断 + +禁止响应所有可屏蔽硬中断。 + +**输入**:禁止硬中断请求。 + +**处理**: + +1. 记录系统状态,用于后续返回。 +2. 禁止响应所有可屏蔽硬中断。 + +**输出**: + +- 所有可屏蔽硬中断都不能响应。 +- 禁止硬中断响应前的系统状态。 + +### 恢复硬中断 + +恢复硬中断的禁止/允许响应状态,与禁止硬中断配对使用。是否允许响应硬中断,取决于最近一次禁止硬中断前,系统是否允许响应硬中断。 + +**输入**:最近一次禁止硬中断前的系统状态。 + +**处理**:将系统状态恢复到最近一次禁止硬中断前。 + +**输出**:系统状态恢复到最近一次禁止硬中断前。 + +### 响应硬中断 + +硬中断触发后,CPU会响应硬中断。 + +**输入**:硬件触发的硬中断信号,且系统没有禁止硬中断。 + +**处理**: + +1. 保存当前上下文。 +2. 调用硬中断处理函数。 +3. 若任务被打断,则恢复最高优先级任务的上下文,该任务不一定是被中断打断的任务。 +4. 若低优先级中断被打断,则直接恢复低先级中断的上下文。 + +**输出**:硬中断被响应。 + +### 触发硬中断 + +触发指定核号的指定硬中断。 + +**输入**:核号、硬中断号。 + +**处理**: + +1. 目前只支持触发本核的硬中断,若指定的核号不为本核,则做报错处理。 +2. 目前只支持触发软件可触发的硬中断,若指定的中断无法进行软件触发,则做报错处理。 +3. 当以前两个条件都满足,则设置对应的中断触发寄存器,软件触发中断。 + +**输出**: + +- 成功:响应的硬中断被触发。 +- 失败:返回错误码。 + +### 清除中断位 + +清除所有的中断请求位或指定的中断请求位。 + +**输入**:硬中断号。 + +**处理**:清除所有的中断请求位或指定的中断请求位。 + +**输出**:所有的中断请求位或指定的中断请求位被清除 + +## 定时器 + +### 定时器创建 + +根据定时器类型,触发模式,定时时长,处理函数等创建一个定时器。 + +**输入**: + +1. 创建参数结构体(包括定时器类型,触发模式,定时时长,处理函数等)。 +2. 用于保存输出的定时器句柄的指针。 + +**处理**:根据入参找到空闲控制块,将入参内容填入控制块中相应的字段中。 + +**输出**: + +- 成功:定时器创建成功,后续可根据得到的定时器句柄做启动、删除等操作。 +- 失败:返回错误码。 + +### 定时器删除 + +删除指定的定时器。 + +**输入**: 定时器句柄 + +**处理**:根据传入的定时器句柄,找到定时器控制块,将其内容清空并将控制块挂接到相应的空闲链表中。 + +**输出**: + +- 成功:定时器被删除。 +- 失败:返回错误码。 + +### 定时器启动 + +指定的定时器开始计时。 + +**输入**: 定时器句柄 + +**处理**:对于软件定时器,根据当前Tick计数以及定时器周期,计算结束时间,将此定时器控制块挂入定时器SortLink。 + +**输出**: + +- 成功:定时器开始计时。 +- 失败:返回错误码。 + +### 定时器停止 + +指定的定时器停止计时。 + +**输入**:定时器句柄。 + +**处理**:对于软件定时器,计算剩余时间并将其保存后,将此定时器控制块从定时器SortLink中摘除。 + +**输出**: + +- 成功:指定任务的信号量计数值被修改。 +- 失败:返回错误码。 + +### 定时器重启 + +指定的定时器重新开始计时。 + +**输入**:定时器句柄 + +**处理**:对于软件定时器,根据当前Tick计数以及定时器周期,计算结束时间,将此定时器控制块挂入定时器SortLink。 + +**输出**: + +- 成功:指定任务的信号量计数值被修改。 +- 失败:返回错误码。 + +### 软件定时器组创建 + +创建一个软件定时器组,后续的软件定时器创建时需要以此为基础。 + +**输入**: + +1. 软件定时器组创建参数(主要关注时钟源类型及最大支持的定时器个数)。 +2. 用于保存输出的定时器组号的地址。 + +**处理**:根据传入的最大支持的定时器个数申请定时器控制块内存,并完成其初始化操作。 + +**输出**: + +- 成功:基于Tick的软件定时器组被成功创建。 +- 失败:返回错误码。 + +## 信号量 + +### 信号量创建 + +创建一个信号量,并设置其初始计数器数值。 + +**输入**:信号量初始计数值、用于保存创建得到句柄的地址。 + +**处理**:找到一个空闲信号量控制块,将输入的初始计数值填入后将信号量ID当做句柄返回。 + +**输出**: + +- 成功:信号量被创建。 +- 失败:返回错误码。 + +### 信号量删除 + +删除指定信号量,若有任务阻塞于该信号量,则删除失败。 + +**输入**:信号量句柄 + +**处理**:对于核内信号量,根据输入的信号量句柄找到信号量控制块,通过查看控制块中任务阻塞链表是否为空来判断是否有任务阻塞于该信号量,若有则删除失败返回,否则释放该信号量控制块。 + +**输出**: + +- 成功:信号量被删除。 +- 失败:返回错误码。 + +### Pend信号量 + +申请指定的信号量,若其计数值大于0,则直接将计数值减1返回,否则发生任务阻塞,等待时间可通过入参设定。 + +**输入**:信号量句柄、等待时间 + +**处理**: + +![](D:/何斌/社区/欧拉社区/22.03LTS SP1需求/文档/UniProton用户指南/figures/pend_semaphore.png) + +**输出**: + +- 成功:返回0。 +- 失败:返回错误码。 + +### Post信号量 + +发布信号量,将该信号量计数值+1,若有任务阻塞于该信号量,则将其唤醒。 + +**输入**:信号量句柄。 + +**处理**: + +![](D:/何斌/社区/欧拉社区/22.03LTS SP1需求/文档/UniProton用户指南/figures/post_semaphore.png) + +**输出**: + +- 成功:信号量发布成功。 +- 失败:返回错误码。 +- 失败:返回错误码。 + +### 信号量计数值重置 + +设置指定信号量计数值,如果有任务阻塞于该信号量,则设置失败。 + +**输入**:信号量句柄、信号量计数值。 + +**处理**:根据输入的信号量句柄,找到相应的信号量控制块,查看控制块中任务阻塞链表,若其不为空,则返回错误,否则将控制块中信号量计数值设为输入的计数值。 + +**输出**: + +- 成功:指定信号量的计数值被修改; +- 失败:返回错误码。 + +### 信号量计数值获取 + + 获取指定信号量计数值。 + +**输入**: 信号量句柄 + +**处理**:根据输入的信号量句柄,找到相应的信号量控制块,将控制块中记录的信号量计数值返回。 + +**输出**: + +- 成功:返回信号量计数值。 +- 失败:返回错误计数值标记。 + +### 信号量阻塞任务PID获取 + +获取阻塞在指定信号量上的任务个数及任务PID列表。 + +**输入**: + +1. 信号量句柄。 +2. 用于存放输出的阻塞任务个数的地址。 +3. 用于存放输出的阻塞任务PID的缓冲区首地址。 +4. 用于存放输出的阻塞任务PID的缓冲区长度。 + +**处理**:若有任务阻塞于指定信号量,则输出阻塞任务的个数及任务PID清单;否则,将阻塞任务个数置为0。 + +**输出**: + +- 成功:输出阻塞于该信号量的任务个数及任务PID清单。 +- 失败:返回错误码。 + +## 异常 + +### 用户注册异常处理钩子 + +用户注册异常处理函数类型定义的异常处理函数钩子,记录异常信息。 + +**输入**:类型为ExcProcFunc的钩子函数。 + +**处理**:将用户注册的钩子函数注册到OS框架里,发生异常时调用。 + +**输出**: + +- 成功:注册成功。 +- 失败:返回错误码。 + + + +## CPU占用率 + +### 获取当前cpu占用率 + +通过本接口获取当前cpu占用率。 + +**输入**:无。 + +**处理**:采用基于IDLE计数的统计算法,统计结果会有一定误差,误差不超过百分之五。 + +**输出**: + +- 成功:返回当前的cpu占用率[0,10000]。 +- 失败:返回错误码。 + +### 获取指定个数的线程的CPU占用率 + +根据用户输入的线程个数,获取指定个数的线程CPU占用率。 + +**输入**: 线程个数、缓冲区指针、实际线程个数指针。 + +**处理**: + +1. 采用基于 IDLE 计数的统计算法,统计结果会有一定误差,误差不超过百分之五。 +2. 当配置项中的采样周期值等于0时,线程级CPUP采样周期为两次调用该接口或者PRT_CpupNow之间的间隔。否则,线程级CPUP采样周期为配置项中的OS_CPUP_SAMPLE_INTERVAL大小。 +3. 输出的实际线程个数不大于系统中实际的线程个数(任务个数和一个中断线程)。 +4. 若在一个采样周期内有任务被删除,则统计的任务线程和中断线程CPUP总和小于10000。 + +**输出**: + +- 成功:在缓冲区写入cpu占用率。 +- 失败:返回错误码。 + + + +### 设置CPU占用率告警阈值 + +根据用户配置的 CPU 占用率告警阈值 warn 和告警恢复阈值 resume,设置告警和恢复阈值。 + +**输入**:告警阈值、恢复阈值。 + +**处理**:设置 CPUP 告警阈值和恢复阈值 + +**输出**: + +- 成功:设置成功。 +- 失败:返回错误码。 + +### 查询CPUP告警阈值和告警恢复阈值 + +根据用户配置的告警阈值指针 warn 和告警恢复阈值指针 resume,查询告警阈值和告警恢复阈值。 + +**输入**:告警阈值指针、恢复阈值指针。 + +**处理**:获取 CPUP 告警阈值和恢复阈值,赋值指针变量。 + +**输出**: + +- 成功:获取成功。 +- 失败:返回错误码。 + +### 注册CPUP告警回调函数 + +根据用户配置的回调函数 hook,注册 CPUP 告警回调函数。 + +**输入**:类型为 CpupHookFunc 的 CPU 告警回调函数。 + +**处理**:将用户的钩子函数注册到 OS 框架。 + +**输出**: + +- 成功:注册成功。 +- 失败:错误码 + +## OS启动 + +### main函数入口: + +二进制执行文件函数入口。 + +**输入**:无 + +**输出**: + +- 成功:返回OK。 +- 失败:错误码 + +### 用户业务入口 + +PRT_AppInit 用户业务函数入口,在 main 函数后调用,在此函数中添加业务功能代码。 + +**输入**:无 + +**输出**: + +- 成功:返回OK。 +- 失败:错误码 + +### 硬件驱动初始化入口 + +PRT_HardDrvInit 硬件驱动初始化函数入口,在 main 函数后调用,在此函数中添加板级驱动初始化功能代码。 + +**输入**:无 + +**输出**: + +- 成功:返回OK。 +- 失败:错误码 + +### 硬件启动流程入口 + +PRT_HardBootInit 在 OS 启动时调用,在main函数前被调用,可以用于 BSS 初始化、随机值设置等。 + +**输入**:无 + +**输出**: + +- 成功:返回OK。 +- 失败:错误码。 + +## openamp + +### 初始化openamp资源函数 + +初始化保留内存,初始化 remoteproc、virtio、rpmsg,建立 Uniproton 与 Linux 两端配对的 endpoint,供消息收发使用。 + +**输入**:无。 + +**输出**: + +- 成功:初始化成功。 +- 失败:错误码。 + +### 消息接收函数 + +接收消息,并触发SGI中断 + +**输入**: + +1. 类型为 unsigned char * 的存储消息的缓冲区。 +2. 类型为 int 的消息预期长度。 +3. 类型为 int *,用于获取消息实际长度。 + +**输出**: + +- 成功:消息接收成功。 +- 失败:错误码。 + +### 消息发送函数 + +发送消息和SGI中断 + +**输入**:类型为 unsigned char * 的存储消息的缓冲区、类型为 int 的消息长度。 + +**输出**: + +- 成功:消息发送成功。 +- 失败:错误码。 + +### 释放openamp资源 + +用于释放ope无mp资源。 + +**输入**:无 + +**输出**: + +- 成功:资源释放成功。 +- 失败:错误码。 + +## POSIX接口 + +### 任务管理 + +#### pthread_attr_init + +pthread_attr_init() 函数初始化一个线程对象的属性,需要用 pthread_attr_destroy() 函数对其去除初始化。 + +**参数**:指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr,结构中的元素分别对应着新线程的运行属性。 + +**输出**: + +- 0:初始化成功。 +- ENOMEM:内存不足,无法初始化线程属性对象。 +- EBUSY:attr是以前初始化但未销毁的线程属性。 + +#### pthread_attr_destroy + +pthread_attr_destroy( ) 函数应销毁线程属性对象。被销毁的attr属性对象可以使用pthread_attr_init( )重新初始化;在对象被销毁后引用该对象的结果是未定义的。 + +**参数**:指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 + +**输出**: + +- 0:函数销毁对象成功。 +- EINVAL:attr指向的是未初始化的线程属性对象。 + +#### pthread_attr_setstackaddr + +pthread_attr_setstackaddr( ) 函数设置attr对象中的线程创建堆栈addr属性。堆栈addr属性指定用于创建线程堆栈的存储位置。 + +**输入**:指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr、 栈地址stackaddr。 + +**输出**: + +- 0:设置成功。 +- EINVAL:attr指向的是未初始化的线程属性对象。 + +#### pthread_attr_getstackaddr + +pthread_attr_getstackaddr( ) 如果成功,函数将堆栈地址属性值存储在堆栈地址中。 + +**参数**:指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr、栈地址stackaddr. + +**输出**: + +- 0:获取成功。 +- EINVAL:attr指向的是未初始化的线程属性对象。 + +#### pthread_attr_getstacksize + +pthread_attr_getstacksize( ) 和pthread_attr_setstacksize( ) 函数分别应获取和设置 attr 对象中的线程创建堆栈大小属性(以字节为单位)。 + +**参数**: + +1. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr. +2. 栈大小指针stacksize,指向设置或获取的堆栈大小。 + +**输出**: + +- 0:获取成功。 +- EINVAL:attr指向的是未初始化的线程属性对象。 + +#### pthread_attr_setstacksize + +设置attr对象中的线程创建堆栈大小属性。 + +**参数**: + +1. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +2. 栈大小指针stacksize,指向设置或获取的堆栈大小。 + +**输出**: + +- 0:设置成功。 +- EINVAL:堆栈size小于最小值或超过限制。 + +#### pthread_attr_getinheritsched + +获取线程的继承属性。 + +**参数**: + +- 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +- 线程的继承性指针inheritsched。 + +**输出**: + +- 0:获取成功。 +- EINVAL:attr指向的是未初始化的线程属性对象。 + +#### pthread_attr_setinheritsched + +设置线程的继承属性。可设置如下参数: + +- PTHREAD_INHERIT_SCHED:指定线程调度属性应继承自创建线程,并且应忽略此attr参数中的调度属性。 +- PTHREAD_EXPLICIT_SCHED:指定线程调度属性应设置为此属性对象中的相应值。 + +**参数**: + +- 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +- 线程的继承性inheritsched。 + +**输出**: + +- 0:设置成功。 +- EINVAL:继承的值无效,或attr指向的是未初始化的线程属性对象。 +- ENOTSUP:试图将属性设置为不支持的值。 + +#### pthread_attr_getschedpolicy + +获取调度策略属性,策略支持SCHED_FIFO。当使用调度策略SCHED_FIFO执行的线程正在等待互斥体时,互斥体解锁,它们应按优先级顺序获取互斥体。 + +**参数**: + +1. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +2. 线程的调度策略指针policy。 + +**输出**: + +- 0:获取成功。 +- attr:指向的是未初始化的线程属性对象。 + +#### pthread_attr_setschedpolicy + +设置调度策略属性,策略支持SCHED_FIFO。当使用调度策略SCHED_FIFO执行的线程正在等待互斥体时,互斥体解锁时,它们应按优先级顺序获取互斥体。 + +**参数**: + +1. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +2. 线程的调度策略policy。 + +**输出**: + +- 0:设置成功。 +- EINVAL:policy的值无效,或者attr指向没有初始化的线程对象。 +- ENOTSUP:试图将属性设置为不支持的值。 + +#### pthread_attr_getdetachstate + +获取线程分离属性,分离状态应设置为PTHREAD_CREATE_DETAED或PTHREAD_CREATE_JOI无BLE。 + +**参数**: + +1. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +2. 分离属性指针detachstate。 + +**输出**: + +- 0:获取成功。 +- EINVAL:attr指向没有初始化的线程对象。 + +#### pthread_attr_setdetachstate + +设置线程分离属性。分离状态应设置为PTHREAD_CREATE_DETAED或PTHREAD_CREATE_JOI无BLE。 + +**参数**: + +1. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +2. 分离属性detachstate。 + +**输出**: + +- 0:设置成功。 +- EINVAL:attr指向没有初始化的线程对象或分离状态的值无效。 + +#### pthread_create + +pthread_create( ) 函数创建一个新线程,其属性由 attr 指定。如果 attr 为 NULL,则使用默认属性。创建成功后,pthread_create( ) 应将创建的线程的ID存储在参数 thread 的位置。 + +**参数**: + +1. 指向线程[标识符](https://baike.baidu.com/item/标识符?fromModule=lemma_inlink)的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)thread。 +2. 指向一个线程属性结构的[指针](https://baike.baidu.com/item/指针?fromModule=lemma_inlink)attr。 +3. 线程处理函数的起始地址 start_routine。 +4. 运行函数的参数 arg。 + +**输出**: + +- 0:创建成功。 +- EINVAL:attr指定的属性无效。 +- EAGAIN:系统缺少创建新线程所需的资源,或者将超过系统对线程总数施加的限制。 +- EPERM:调用者没有权限。 + +#### pthread_cancel + +取消线程的执行。pthread_cancel( ) 函数应请求取消线程。目标线程的可取消状态和类型决定取消何时生效。当取消被操作时,应调用线程的取消处理程序。 + +**参数**:线程的ID thread。 + +**输出**: + +- 0:取消成功。 +- ESRCH:找不到与给定线程ID相对应的线程。 + +#### pthread_testcancel + +设置可取消状态。pthread_testcancel( ) 函数应在调用线程中创建一个取消点。如果禁用了可取消性,pthread_testcancel( )函数将无效。 + +**参数**:无 + +**输出**:无 + +#### pthread_setcancelstate + +pthread_setcancelstate() 将调用线程的可取消性状态设置为 state 中给出的值。线程以前的可取消性状态返回到oldstate所指向的缓冲区中。state状态的合法值为PTHREAD_CANCEL_E无BLE和PTHREAD_CANCEL_DISABLE。 + +**参数**: + +- 线程的可取消性状态 state。 +- 之前的可取消状态 oldstate。 + +**输出**: + +- 0:设置成功。 +- EINVAL:指定的状态不是 PTHREAD_CANCEL_E无BLE 或 PTHREAD_CANCEL_DISABLE。 + +#### pthread_setcanceltype + +pthread_setcanceltype( ) 函数应原子地将调用线程的可取消类型设置为指定的类型,并在oldtype引用的位置返回上一个可取消类型。类型的合法值为PTHREAD_CANCEL_DEFERRED和PTHREAD_CANCEL_ASYNCHRONOUS。 + +**输入**: + +- 线程的可取消类型type。 +- 之前的可取消类型oldtype。 + +**输出**: + +- 0:设置成功。 +- EINVAL:指定的类型不是PTHREAD_CANCEL_DEFERRED或PTHREAD_CANCEL_ASYNCHRONOUS。 + +#### pthread_exit + +线程的终止可以是调用 pthread_exit 或者该线程的例程结束。由此可看出,一个线程可以隐式退出,也可以显式调用 pthread_exit 函数来退出。pthread_exit 函数唯一的参数 value_ptr 是函数的返回代码,只要 pthread_join 中的第二个参数 value_ptr 不是NULL,这个值将被传递给 value_ptr。 + +**参数**:线程退出状态value_ptr,通常传NULL。 + +**输出**:None + +#### pthread_cleanup_push + +pthread_cleanup_push( ) 函数应将指定的取消处理程序推送到调用线程的取消堆栈上。pthread_cleanup_push必须和pthread_cleanup_pop同时使用。当push后,在线程退出前使用pop,便会调用清理函数。 + +**参数**: + +1. 取消处理程序入口地址 routine。 +2. 传递给处理函数的参数 arg。 + +**输出**:无 + +#### pthread_cleanup_pop + +pthread_cleanup_pop( ) 应删除调用线程取消处理程序,并可选择调用它(如果execut非零)。 + +**参数**:执行参数execut。 + +**输出**:无 + +#### pthread_setschedprio + +pthread_setschedprio( ) 函数应将线程 ID 指定的调度优先级设置为 prio 给出的值。如果 pthread_setschedprio( ) 函数失败,则目标线程的调度优先级不应更改。 + +**参数**: + +1. 线程ID:thread。 +2. 优先级:prio。 + +**输出**: + +- 0,设置成功。 +- EINVAL:prio对指定线程的调度策略无效。 +- ENOTSUP:试图将优先级设置为不支持的值。 +- EPERM:调用者没有设置指定线程的调度策略的权限。 +- EPERM:不允许将优先级修改为指定的值。 +- ESRCH:thread指定的线程不存在。 + +#### pthread_self + +pthread_self( ) 函数应返回调用线程的线程ID。 + +**参数**:无 + +**输出**:返回调用线程的线程ID。 + +#### pthread_equal + +此函数应比较线程ID t1和t2。 + +**参数**: + +1. 线程ID t1。 +2. 线程ID t2。 + +**输出**: + +- 如果t1和t2相等,pthread_equal( ) 函数应返回非零值。 +- 如果t1和t2不相等,应返回零。 +- 如果t1或t2不是有效的线程ID,则行为未定义。 + +#### sched_yield + +sched _ yield () 函数应强制正在运行的线程放弃处理器,并触发线程调度。 + +**参数**:无 + +**输出**:输出0时,成功完成;否则应返回值-1。 + +#### sched_get_priority_max + +sched_get_priority_max( ) 和 sched_get_priority_min( ) 函数应分别返回指定调度策略的优先级最大值或最小值。 + +**参数**:调度策略policy。 + +**输出**: + +- -1:失败。 +- 返回优先级最大值或最小值。 + +#### sched_get_priority_min + +返回指定调度策略的优先级最小值 + +**参数**:调度策略policy。 + +**输出**: + +- -1:失败。 +- 返回优先级最小值。 + +#### pthread_join + +pthread_join() 函数,以阻塞的方式等待 thread 指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且 thread 指定的线程必须是 joi无ble 的。当 pthread_join( ) 成功返回时,目标线程已终止。对指定同一目标线程的pthread_join( )的多个同时调用的结果未定义。如果调用pthread_join( ) 的线程被取消,则目标线程不应被分离 + +**参数**: + +1. 线程ID:thread。 +2. 退出线程:返回值value_ptr。 + +**输出**: + +- 0:成功完成。 +- ESRCH:找不到与给定ID相对应的线程。 +- EDEADLK:检测到死锁或thread的值指定调用线程。 +- EINVAL:thread指定的线程不是joi无ble的。 + +#### pthread_detach + +实现线程分离,即主线程与子线程分离,子线程结束后,资源自动回收。 + +**参数**:线程ID:thread。 + +**输出**: + +- 0:成功完成。 +- EINVAL:thread是分离线程。 +- ESRCH:给定线程ID指定的线程不存在。 + +#### pthread_key_create + +分配用于标识线程特定数据的键。pthread_key_create 第一个参数为指向一个键值的[指针](https://baike.baidu.com/item/指针/2878304?fromModule=lemma_inlink),第二个参数指明了一个 destructor 函数,如果这个参数不为空,那么当每个线程结束时,系统将调用这个函数来释放绑定在这个键上的内存块。 + +**参数**: + +1. 键值的[指针](https://baike.baidu.com/item/指针/2878304?fromModule=lemma_inlink)key。 +2. destructor 函数入口 destructor。 + +**输出**: + +- 0:创建成功。 +- EAGAIN:系统缺乏创建另一个特定于线程的数据密钥所需的资源,或者已超过系统对每个进程的密钥总数施加的限制。 +- ENOMEM:内存不足,无法创建密钥。 + +#### pthread_setspecific + +pthread_setspecific() 函数应将线程特定的 value 与通过先前调用 pthread_key_create( ) 获得的 key 关联起来。不同的线程可能会将不同的值绑定到相同的键上。这些值通常是指向已保留供调用线程使用的动态分配内存块的指针。 + +**参数**: + +1. 键值key。 +2. 指针value + +**输出**: + +- 0:设置成功。 +- ENOMEM:内存不足,无法将非NULL值与键关联。 +- EINVAL:key的值不合法。 + +#### pthread_getspecific + +将与key关联的数据读出来,返回数据类型为 void *,可以指向任何类型的数据。需要注意的是,在使用此返回的指针时,需满足是 void 类型,虽指向关联的数据地址处,但并不知道指向的数据类型,所以在具体使用时,要对其进行强制类型转换。 + +**参数**:键值key。 + +**输出**: + +- 返回与给定 key 关联的线程特定数据值。 +- NULL:没有线程特定的数据值与键关联。 + +#### pthread_key_delete + +销毁线程特定数据键。 + +**参数**:需要删除的键key。 + +**输出**: + +- 0:删除成功。 +- EINVAL:key值无效。 + +### 信号量管理 + +#### sem_init + +sem_init( ) 函数应初始化 sem 引用的匿名信号量。初始化信号量的值应为 value。在成功调用 sem_init( ) 后,信号量 TMO 可用于后续调用 sem_wait( )、sem_timedwait( )、sem_trywait( )、sem_post( )和sem_destroy( )。此信号量应保持可用,直到信号量被销毁。 + +**参数**: + +1. 指向信号量指针sem。 +2. 指明信号量的类型pshared。 +3. 信号量值的大小value。 + +**输出**: + +- 0:初始化成功。 +- EINVAL:值参数超过{SEM_VALUE_MAX}。 +- ENOSPC:初始化信号量所需的资源已耗尽,或已达到信号量的限制。 +- EPERM:缺乏初始化信号量的权限。 + +#### sem_destroy + +sem_destroy( ) 函数销毁 sem 指示的匿名信号量。只有使用 sem_init( ) 创建的信号量才能使用 sem_destroy( ) 销毁;使用命名信号量调用 sem_destroy( ) 的效果未定义。在 sem 被另一个对 sem_init( ) 的调用重新初始化之前,后续使用信号量 sem 的效果是未定义的。 + +**参数**:指向信号量指针sem。 + +**输出**: + +- 0:销毁成功。 +- EINVAL:sem不是有效的信号量。 +- EBUSY:信号量上当前有线程被阻止。 + +#### sem_open + +创建并初始化有名信号量。此信号量可用于后续对 sem_wait( )、sem_timedwait( )、sem_trywait( )、sem_post( )和sem_close() 的调用。 + +**参数**: + +1. 信号量名无me指针。 + +2. oflag参数控制信号量是创建还是仅通过调用sem_open( )访问。以下标志位可以在oflag中设置: + + - O_CREAT:如果信号量不存在,则此标志用于创建信号量。 + + - O_EXCL:如果设置了O_EXCL和O_CREAT,且信号量名称存在,sem_open( )将失败。如果设置了O_EXCL而未设置O_CREAT,则效果未定义。 + +3. 如果在oflag参数中指定了O_CREAT和O_EXCL以外的标志,则效果未指定。 + +**输出**: + +- 创建并初始化成功,返回信号量地址。 +- EACCES:创建命名信号量的权限被拒绝。 +- EEXIST:已设置O_CREAT和O_EXCL,且命名信号量已存在。 +- EINTR:sem_open( )操作被信号中断。 +- EINVAL:给定名称不支持sem_open( ),或在oflag中指定了O_CREAT,并且值大于最大值。 +- EMFILE:当前使用的信号量描述符或文件描述符太多。 +- E无METOOLONG:无me参数的长度超过{PATH_MAX},或者路径名组件的长度超过{无ME_MAX}。 +- ENFILE:系统中当前打开的信号量太多。 +- ENOENT:未设置O_CREAT且命名信号量不存在。 +- ENOSPC:没有足够的空间来创建新的命名信号量。 + +#### sem_close + +关闭一个命名信号量。未命名的信号量(由sem_init() 创建的信号量)调用 sem_close() 的效果未定义。sem_close() 函数应解除系统分配给此信号量的任何系统资源。此过程后续使用sem指示的信号量的影响未定义。 + +**参数**:信号量指针sem。 + +**输出**: + +- 0: 销毁成功。 +- EINVAL:sem参数不是有效的信号量描述符。 + +#### sem_wait + +sem_wait( ) 函数通过对 sem 引用的信号量执行信号量锁定操作来锁定该信号量。如果信号量值当前为零,则调用线程在锁定信号量或调用被信号中断之前,不会从对 sem_wait( ) 的调用返回。 + +**参数**:信号量指针sem。 + +**输出**: + +- 0:操作成功。 +- EAGAIN:信号量已被锁定,无法立即被 sem_trywait( ) 操作。 +- EDEADLK:检测到死锁条件。 +- EINTR:信号中断了此功能。 +- EINVAL:sem参数未引用有效的信号量。 + +#### sem_trywait + +只有当信号量当前未锁定时,即信号量值当前为正值,sem_trywait( ) 函数才应锁定 sem 引用的信号量。否则它不应锁定信号量。 + +**参数**:信号量指针sem。 + +**输出**: + +- 0:操作成功。 +- EAGAIN:信号量已被锁定,无法立即被sem_trywait( )操作。 +- EDEADLK:检测到死锁条件。 +- EINTR:信号中断了此功能。 +- EINVAL:sem参数未引用有效的信号量。 + +#### sem_timedwait + +sem_timedwait( ) 函数应锁定 sem 引用的信号量,就像 sem_wait( ) 函数一样。如果在不等待另一个线程执行sem_post( ) 解锁信号量的情况下无法锁定信号量,则在指定的超时到期时,此等待将终止。 + +**参数**: + +1. 信号量指针sem。 +2. 阻塞时间指针abs_timeout。 + +**输出**: + +- 0:操作成功。 +- EINVAL:线程可能会阻塞,abs_timeout 指定的纳秒值小于0或大于等于1000 million。 +- ETIMEDOUT:在指定的超时到期之前,无法锁定信号量。 +- EDEADLK:检测到死锁条件。 +- EINTR:信号中断了此功能。 +- EINVAL:sem参数未引用有效的信号量。 + +#### sem_post + +sem_post( ) 函数应通过对 sem 引用的信号量执行信号量解锁操作,当有线程阻塞在这个信号量上时,调用这个函数会使其中一个线程不在阻塞,选择机制是有线程的调度策略决定的。 + +**参数**:信号量指针sem。 + +**输出**: + +- 0:操作成功。 +- EINVAL:sem参数未引用有效的信号量。 + +#### sem_getvalue + +sem_getvalue( ) 函数获取 sem 引用的信号量的值,而不影响信号量的状态。获取的 sval 值表示在调用期间某个未指定时间发生的实际信号量值。 + +**参数**: + +1. 信号量指针sem。 +2. 信号量计数值指针sval。 + +**输出**: + +- 0:操作成功。 +- EINVAL:sem参数未引用有效的信号量。 + +### 互斥量管理 + +#### pthread_mutexattr_init + +pthread_mutexattr_init( ) 函数初始化互斥锁。如果调用 pthread_mutexattr_init( ) 指定已初始化的attr属性对象行为未定义。 + +**参数**:互斥锁属性对象指针attr。 + +**输出**: + +- 0:操作成功。 +- ENOMEM:内存不足,无法初始化互斥属性对象。 + +#### pthread_mutexattr_destroy + + 注销一个互斥锁。销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。 + +**参数**:互斥锁属性对象指针attr。 + +**输出**: + +- 0:操作成功。 +- EINVAL:attr指定的值无效。 + +#### pthread_mutexattr_settype + +pthread_mutexattr_settype( ) 函数设置互斥 type 属性。默认值为 PTHREAD_MUTEX_DEFAULT。有效的互斥类型包括: + +PTHREAD_MUTEX_NORMAL:此类型的互斥锁不会检测死锁。 + +- 如果线程在不解除互斥锁的情况下尝试重新锁定该互斥锁,则会产生死锁。 +- 如果尝试解除由其他线程锁定的互斥锁,会产生不确定的行为。 +- 如果尝试解除锁定的互斥锁未锁定,则会产生不确定的行为。 + +PTHREAD_MUTEX_ERRORCHECK:此类型的互斥锁可提供错误检查。 + +- 如果线程在不解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则会返回错误。 +- 如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。 +- 如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。 + +PTHREAD_MUTEX_RECURSIVE: + +- 如果线程在不解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则可成功锁定该互斥锁。 与 PTHREAD_MUTEX_NORMAL 类型的互斥锁不同,对此类型互斥锁进行重新锁定时不会产生死锁情况。多次锁定互斥锁需要进行相同次数的解除锁定才可以释放该锁,然后其他线程才能获取该互斥锁。 +- 如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。 +- 如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。 + +PTHREAD_MUTEX_DEFAULT: + +- 如果尝试以[递归](https://baike.baidu.com/item/递归?fromModule=lemma_inlink)方式锁定此类型的互斥锁,则会产生不确定的行为。 +- 对于不是由调用线程锁定的此类型互斥锁,如果尝试对它解除锁定,则会产生不确定的行为。 +- 对于尚未锁定的此类型互斥锁,如果尝试对它解除锁定,也会产生不确定的行为。 + +**参数**: + +1. 互斥锁属性对象指针attr。 +2. 互斥锁类型type。 + +**输出**: + +- 0:操作成功。 +- EINVAL:attr指定的值无效,或type无效。 + +#### pthread_mutexattr_gettype + +pthread_mutexattr_gettype() 可用来获取由 pthread_mutexattr_settype() 设置的互斥锁的 type 属性。 + +**参数**: + +1. 互斥锁属性对象指针attr。 +2. 互斥锁类型指针type。 + +**输出**: + +- 0:操作成功。 +- EINVAL:attr指定的值无效。 + +#### pthread_mutexattr_setprioceiling + +pthread_mutexattr_setprioceiling() 可用来设置互斥锁属性对象的优先级上限属性。 + +**参数**: + +1. 互斥锁属性对象指针attr。 +2. 优先级上限prioceiling。 + +**输出**: + +- 0:操作成功。 +- EINVAL:attr或prioceiling指定的值无效。 + +#### pthread_mutexattr_getprioceiling + +pthread_mutexattr_getprioceiling() 可用来获取互斥锁属性对象的优先级上限属性。 + +**参数**: + +1. 互斥锁属性对象指针attr。 +2. 优先级上限指针prioceiling。 + +**输出**: + +- 0:操作成功。 +- EINVAL:attr指定的值无效。 + +#### pthread_mutexattr_setprotocol + +pthread_mutexattr_setprotocol() 可用来设置互斥锁属性对象的协议属性。定义的 protocol 可以为以下值之一: + +- PTHREAD_PRIO_NONE +- PTHREAD_PRIO_INHERIT +- PTHREAD_PRIO_PROTECT。 + +**参数**: + +1. 互斥锁属性对象指针 attr。 +2. 互斥锁属性对象的协议 protocol。 + +**输出**: + +- 0:操作成功。 +- ENOTSUP:协议指定的值不支持。 +- EINVAL:attr指定的值无效。 +- EPERM:调用者没有权限。 + +#### pthread_mutexattr_getprotocol + +pthread_mutexattr_getprotocol() 获取互斥锁属性对象的协议属性。 + +**参数**: + +1. 互斥锁属性对象指针attr。 +2. 互斥锁属性对象的协议指针protocol。 + +**输出**: + +- 0:操作成功。 +- EINVAL:attr指定的值无效。 +- EPERM:调用者没有权限。 + +#### pthread_mutex_init + +pthread_mutex_init( ) 函数初始化互斥锁,属性由 attr 指定。如果 attr 为NULL,则使用默认互斥属性。 + +**参数**: + +1. 互斥锁指针mutex。 +2. 互斥锁属性对象指针attr。 + +**输出**: + +- 0:操作成功。 +- EAGAIN:缺少初始化互斥锁所需的资源(内存除外)。 +- ENOMEM:内存不足,无法初始化互斥体。 +- EPERM:没有执行操作的权限。 +- EBUSY:互斥锁已经初始化但尚未销毁。 +- EINVAL:attr指定的值无效。 + +#### pthread_mutex_destroy + +pthread_mutex_destroy () 用于注销一个互斥锁。销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。 + +**参数**:互斥锁指针mutex。 + +**输出**: + +- 0:操作成功。 +- EBUSY:锁当前未处于开放状态。 +- EINVAL:mutex指定的值无效。 + +#### pthread_mutex_lock + +当pthread_mutex_lock() 返回时,该[互斥锁](https://baike.baidu.com/item/互斥锁/841823?fromModule=lemma_inlink)已被锁定。[线程](https://baike.baidu.com/item/线程/103101?fromModule=lemma_inlink)调用该函数让互斥锁上锁,如果该互斥锁已被另一个线程锁定和拥有,则调用该线程将阻塞,直到该互斥锁变为可用为止。 + +**参数**:互斥锁指针mutex。 + +**输出**: + +- 0:操作成功。 +- EINVAL:mutex指定的值未初始化。 +- EAGAIN:无法获取互斥锁。 +- EDEADLK:当前线程已经拥有互斥锁。 + +#### pthread_mutex_trylock + +pthread_mutex_trylock() 语义与 pthread_mutex_lock() 类似,不同点在于锁已经被占据时返回 EBUSY, 而非挂起等待。 + +**参数**:互斥锁指针mutex。 + +**输出**: + +- 0,操作成功。 +- EBUSY:mutex指定的锁已经被占据。 +- EINVAL:mutex指定的值未初始化。 +- EAGAIN:无法获取互斥锁。 +- EDEADLK:当前线程已经拥有互斥锁。 + +#### pthread_mutex_timedlock + +pthread_mutex_timedlock() 语义与pthread_mutex_lock() 类似,不同点在于锁已经被占据时增加一个超时时间,等待超时返回错误码。 + +**参数**: + +1. 互斥锁指针mutex。 +2. 超时时间指针abs_timeout。 + +**输出**: + +- 0:操作成功。 +- EINVAL:mutex指定的值未初始化,abs_timeout指定的纳秒值小于0或大于等于1000 million。 +- ETIMEDOUT:等待超时。 +- EAGAIN:无法获取互斥锁。 +- EDEADLK:当前线程已经拥有互斥锁。 + +#### pthread_mutex_unlock + +释放互斥锁。 + +**参数**:互斥锁指针mutex。 + +**输出**: + +- 0:操作成功。 +- EINVAL:mutex指定的值未初始化。 +- EPERM:当前线程不拥有互斥锁。 + +### 读写锁编程 + +#### pthread_rwlock_init + +pthread_rwlock_init( ) 初始化读写锁。如果 attr 为 NULL,则使用默认的读写锁属性。一旦初始化,锁可以使用任何次数,而无需重新初始化。调用 pthread_rwlock_init( ) 指定已初始化的读写锁行为未定义。如果在没有初始化的情况下使用读写锁,则结果是未定义的。 + +**参数**: + +1. 读写锁指针rwlock。 +2. 读写锁属性指针attr。 + +**输出**: + +- 0:操作成功。 +- EAGAIN:系统缺少初始化读写锁所需的资源(内存除外)。 +- ENOMEM:内存不足,无法初始化读写锁。 +- EPERM:没有执行操作的权限。 +- EBUSY:rwlock是以已初始化但尚未销毁的读写锁。 +- EINVAL:attr指定的值无效。 + +#### pthread_rwlock_destroy + +pthread_rwlock_destroy( ) 函数应销毁 rwlock 引用的读写锁,并释放锁使用的资源。在再次调用pthread_rwlock_init( ) 重新初始化锁之前,后续使用锁的行为未定义。如果在任何线程持有 rwlock 时调用pthread_rwlock_destroy( ) 行为未定义。尝试销毁未初始化的读写锁行为未定义。 + +**参数**:读写锁指针rwlock。 + +**输出**: + +- 0:操作成功。 +- EBUSY: rwlock引用的对象被锁定时销毁该对象。 +- EINVAL:attr指定的值无效。 + +#### pthread_rwlock_rdlock + +pthread_rwlock_rdlock( ) 函数应将读锁应用于rwlock引用的读写锁。 + +**参数**:读写锁指针rwlock。 + +**输出**: + +- 0:操作成功。 +- EINVAL:rwlock是未初始化的读写锁。 +- EAGAIN:无法获取读锁,因为已超过rwlock的最大读锁数。 +- EDEADLK:检测到死锁条件或当前线程已拥有写锁。 + +#### pthread_rwlock_tryrdlock + +pthread_rwlock_tryrdlock( ) 函数语义与pthread_rwlock_rdlock( ) 类似。在任何情况下,pthread_rwlock_tryrdlock( ) 函数都不会阻塞;它会一直获取锁,或者失败并立即返回。 + +**参数**:读写锁指针rwlock。 + +**输出**: + +- 0:操作成功。 +- EINVAL:rwlock是未初始化的读写锁。 +- EAGAIN:无法获取读锁,因为已超过rwlock的最大读锁数。 +- EBUSY:无法获取读写锁以进行读取,因为写入程序持有该锁。 + +#### pthread_rwlock_timedrdlock + +pthread_rwlock_timedrdlock()语义与pthread_rwlock_rdlock ()类似,不同的是在锁已经被占据时增加一个超时时间,等待超时返回错误码。 + +**参数**: + +1. 读写锁指针rwlock。 +2. 超时时间指针abs_timeout。 + +**输出**: + +- 0:操作成功。 +- ETIMEDOUT:在指定的超时到期之前,无法获取锁。 +- EAGAIN:无法获取读锁,超过锁的最大读锁数量。 +- EDEADLK:检测到死锁条件或调用线程已在rwlock上持有写锁。 +- EINVAL:rwlock指定的锁未初始化,或者abs_timeout纳秒值小于0或大于等于1000 million。 + +#### pthread_rwlock_wrlock + +pthread_rwlock_wrlock( ) 函数将写锁应用于 rwlock 引用的读写锁。如果没有其他线程持有读写锁 rwlock,调用线程将获得写锁。否则,线程应阻塞,直到它能够获得锁。如果调用线程在调用时持有读写锁(无论是读锁还是写锁),则调用线程可能会死锁。 + +**参数**:读写锁指针rwlock。 + +**输出**: + +- 0:操作成功。 +- EINVAL:rwlock指定的值未初始化。 +- EDEADLK:检测到死锁情况,或者当前线程已经拥有用于写入或读取的读写锁。 + +#### pthread_rwlock_trywrlock + +pthread_rwlock_trywrlock( ) 函数类似 pthread_rwlock_wrlock( ),但如果任何线程当前持有rwlock(用于读取或写入,该函数将失败)。 + +**参数**:读写锁指针rwlock。 + +**输出**: + +- 0:操作成功。 +- EBUSY:无法获取读写锁以进行写入,因为它已被锁定以进行读取或写入。 +- EINVAL:rwlock指定的值未初始化。 + +#### pthread_rwlock_timedwrlock + +pthread_rwlock_timedwrlock()语义与pthread_rwlock_wrlock ()类似,不同的是在锁已经被占据时增加一个超时时间,等待超时返回错误码。 + +**参数**: + +1. 读写锁指针rwlock。 +2. 超时时间指针abs_timeout。 + +**输出**: + +- 0:操作成功。 +- ETIMEDOUT:在指定的超时到期之前,无法获取锁。 +- EAGAIN:无法获取读锁,超过锁的最大读锁数量。 +- EDEADLK:检测到死锁条件或调用线程已在rwlock上持有写锁。 +- EINVAL;rwlock指定的锁未初始化,或者abs_timeout纳秒值小于0或大于等于1000 million。 + +#### pthread_rwlock_unlock + +pthread_rwlock_unlock( )函数释放rwlock引用的读写锁上持有的锁。如果读写锁rwlock未被调用线程持有,则结果未定义。 + +**参数**:读写锁指针rwlock。 + +**输出**: + +- 0:操作成功。 +- EINVAL:rwlock指定的锁未初始化。 +- EPERM:当前线程不持有读写锁。 + +### 时钟管理 + +#### clock_gettime + +clock_gettime()函数应返回指定时钟的当前值tp。 + +**参数**: + +- 时钟类型clock_id。 +- timespec结构体指针tp。 + +**输出**: + +- 0:操作成功。 +- EINVAL:clock_id不合法。 + +#### clock_settime + +clock_settime()函数应将指定的clock_id设置为tp指定的值。 + +**参数**: + +1. 时钟类型clock_id。 +2. timespec结构体指针tp。 + +**输出**: + +- 0:操作成功。 +- EINVAL:clock_id不合法,或tp参数指定的纳秒值小于0或大于等于1000 million。 +- EPERM:没有设置指定时钟的权限。 + +#### clock_getres + +clock_getres()返回时钟的分辨率。如果参数res不为NULL,则指定时钟的分辨率应存储在res指向的位置。如果res为NULL,则不返回时钟分辨率。如果clock_settime( )的时间参数不是res的倍数,则该值将被截断为res的倍数。 + +**参数**: + +1. 时钟类型clock_id。 +2. timespec结构体指针res。 + +**输出**: + +- 0:操作成功。 +- EINVAL:clock_id不合法。 + +#### nanosleep + +无nosleep()函数应导致当前线程暂停执行,直到rqtp参数指定的时间间隔过去或信号传递到调用线程。挂起时间可能比请求的长,因为参数值被四舍五入到睡眠分辨率的整数倍,或者因为系统调度了其他活动。但是,除被信号中断外,暂停时间不得小于rqtp规定的时间。 + +如果rmtp参数是非NULL,则更新其为剩余的时间量(请求的时间减去实际睡眠时间)。如果rmtp参数为NULL,则不返回剩余时间。 + +**参数**: + +1. timespec结构体指针rqtp。 +2. timespec结构体指针rmtp。 + +**输出**: + +- 0:操作成功。 +- EINVAL:rqtp参数指定的纳秒值小于0或大于等于1000 million。 +- EINTR:信号中断。 + +#### sleep + +sleep()函数应导致调用线程暂停执行,直到参数seconds指定的实时秒数过去或信号被传递到调用线程。由于系统安排了其他活动,暂停时间可能比请求的要长。 + +**参数**: 秒数seconds。 + +**输出**: + +- 0:操作成功。 +- 如果由于信号的传递而返回,则返回值应为“未睡眠”量,以秒为单位。 + +#### timer_create + +timer_create( )函数使用指定的时钟clock_id作为时序基创建计时器,在timerid引用的位置返回计时器ID,用于标识计时器。在删除计时器之前,此计时器ID在调用过程中应是唯一的。 + +**参数**: + +1. 时钟类型clock_id。 +2. sigevent结构体指针evp。 +3. 定时器ID指针timerid。 + +**输出**: + +- 0:操作成功。 +- EINVAL:clock_id不合法。 +- EAGAIN:系统缺少足够的资源来满足请求。 +- EINVAL:指定的时钟ID未定义。 +- ENOTSUP:不支持创建附加到clock_id时钟上的计时器。 + +#### timer_delete + +删除定时器。 + +**参数**:定时器ID指针timerid。 + +**输出**: + +- 0:操作成功。 +- EINVAL:timerid不合法。 + +#### timer_settime + +如果value的it_value成员非0,timer_settime( )函数从value参数的it_value成员设置timerid指定的计时器的到期时间。如果在调用timer_settime( )时指定的计时器已启用,则此调用应将下次到期的时间重置为指定的值。如果value的it_value成员为0,则应解除计时器。 + +**参数**: + +1. 定时器ID timerid。 +2. 计时器的特征flag。 +3. itimerspec结构体指针value。 +4. itimerspec结构体指针ovalue。返回上一次计时器设置超时时间。 + +**输出**: + +- 0:操作成功。 +- EINVAL:timerid不合法。 + +#### timer_gettime + +timer_gettime() 函数存储定时器 timerid 的剩余时间以及间隔。value 的 it_value 成员包含计时器到期前的时间量,如果计时器已解除,则为零。value 的 it_interval 成员将包含 timer_settime() 上次设置的间隔时间。 + +**参数**: + +1. 定时器ID timerid。 +2. itimerspec结构体指针value。 + +**输出**: + +- 0:操作成功。 +- EINVAL:timerid不合法。 + +### 内存管理 + +#### malloc + +malloc ( ) 分配大小(以字节为单位)size 的未使用的空间。 + +**参数**:大小size。 + +**输出**:分配成功时,返回指向分配空间的指针。 + +- 如果size 为0,则返回空指针或可以成功传递给 free( ) 的唯一指针。 +- 否则它将返回一个空指针,并设置 errno 来指示错误:ENOMEM 存储空间不足。 + +#### free + +Free()函数释放ptr指向的空间,即可供进一步分配。如果ptr是空指针,则不发生任何操作。如果空间已被对free( )或realloc ( )的调用释放,则行为未定义。 + +**参数**:指针ptr。 + +**输出**:无 + + \ No newline at end of file diff --git "a/docs/zh/docs/UniProton/UniProton\347\224\250\346\210\267\346\214\207\345\215\227-\346\246\202\350\277\260.md" "b/docs/zh/docs/UniProton/UniProton\347\224\250\346\210\267\346\214\207\345\215\227-\346\246\202\350\277\260.md" new file mode 100644 index 000000000..576741cb5 --- /dev/null +++ "b/docs/zh/docs/UniProton/UniProton\347\224\250\346\210\267\346\214\207\345\215\227-\346\246\202\350\277\260.md" @@ -0,0 +1,12 @@ +# UniProton用户指南 + +## 介绍 + +UniProton是基于openEuler社区面向嵌入式场景的操作系统,旨在成为一个高质量的为上层业务软件屏蔽底层硬件差异,并提供强大的调试功能的操作系统平台。使业务软件可以在不同的硬件平台之间快速移植,方便产品芯片选型,降低硬件采购成本和软件维护成本。 + +本文档主要用于介绍UniProton的基本功能和接口说明,便于开发人员了解基本的UniProton操作系统知识。 + +## 编译教程 + +相关编译教程,可参考:https://gitee.com/openeuler/UniProton/blob/master/doc/UniProton_build.md。 + diff --git a/docs/zh/docs/UniProton/figures/FCS.png b/docs/zh/docs/UniProton/figures/FCS.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b1a514b92da33322485c83deaa2359494522b7 GIT binary patch literal 19278 zcmeHvcT|&G(=Q+vq?@B6AczG76+}AH6uT5PASg|U6zN4ufDlv;5d~2}O27mQL_k19 zdQ$>KdK5zFks2XFfDl3mA@>P-)bqaY`tG;Bd;hp=-NUja&n~lP&z||sZ}wx%1+&w_ zn-J zaK&*w@L9n3%#{Eh9uX|}H!sfT)pZ`8bE9WZ9J2_qpB^;4d*BL6VOda7d3S=KhJC7Y z(v^w#5`k@+Ei$>Sw~mywy)7Y1e08nLObTke@oKK`+gw)M#?op{oCGA6c(}V?GdlB% z^?pbOy`5UGld7;)d^vgZSp^#HmMkMH@$vCm?Z+eGYP%Oi073pQ|3td3&L`J~U$P?> zC@6!^d09eR*75L^nM#E+So11xjDLJ|o;hC2ukIT;pR|#O$2YBc;LivFw=X>7heUaJ zzGyxv7i4e2zvpeXk>TNa@1+#5eR*HTt#yf|dOSRl{T36-3+Ij2ZQSnz1%xlnZngWG z9JxW{!q7bM(HopviC5tjmd>ae=jGuU$T|}I%z;l*+vxv=iIunE!>jFmYAWIT4WG_X z=wTm14-txR8dEz_I*mc{X{9a@=TuLQ7{+3vJlkjyA$ zyD~BJ$uCV%oOs(12t-@K%;$&YHeNMh$KHtF`XEah^on4tmI*{eDOJ|p8;&4(t%exQ z`nOVN=IN|Tb(%T541NW#hEXO@c*AD>y%D;_q*|qxCCBQamHhJ6O3MmP+3MZ*`??#b zPUV+4R~;}oluf(!0|=3+^ZV@25!!?prmTbZCz;!E!D*yCMAJ&}B-wCiI(O5S30W34 zRD)mG)Ovn+)$zz-i3o=CG4RI@$mx*B3^ScwRZQJO9kN!V`d8eIz^t3EsF$-H_UY}I z8J#SjFmlm2NXw=Kt$r1PDt6{(9bI&uy5=A-`AI~a}{-S61{Kt?6^r?@cIqn=iY_6ne4cI zYmOhDEWP>LCgbQY&!V>Yaa1?#PERQ_WmQ`06-;OBUOdILj2$jldWIbfyz%;EhWgg) zCeS{c3B@iQjf@*U#0~09j;UcZ<$;Z;+_Kizsj*0x+yX*AMfurJA$9JTH(f`iH0%w+ z?G0GEA8z8}P-BJl{n)q^F*U?T4vCfWUyPLBxHaJx*71pPbc~-ECB*9RHs1bxUvDcT zTA9KbDUnmv@saxune)S`2r<>$3D%91WC?PjPPpe-Vf7w$-ODo<7YYW**}UiUrKh1r z3CjJOmCXfAQ8PYe=BnbHs2EQJcmpr!Q%JfU;;ayF z+Xi=j`~uKM$(N(hAN#l4Nr(Nv*iZcjZ-H0kT7ELt-9_G71izd zvB>K#D*3R!U899)T+}H)YbzVdmRDV9+7TSBK+cR-S?nL5C9CC4dJrED9}n(#CY4Ys z&i^{T?M_xkY9=G?YKjj87P}x8;__qI%o0(nv!yJ{3Ns_M>AAh{Z9p_RyaZoKi4WG% z3kwCiixpDR53p`Oa$NaVX5eiIs;htIQ4}xr!B%bC)UXb7PDHQk(D4UVh_+U!<*8&t z8TV4w!)oeh>df-CSCDnc@DzsuvaZ=5=}L=|_X4*wE~
ljbuJ#NO#-UDQJIpDX
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

literal 0
HcmV?d00001

diff --git a/docs/zh/docs/UniProton/figures/MemoryRelease.png b/docs/zh/docs/UniProton/figures/MemoryRelease.png
new file mode 100644
index 0000000000000000000000000000000000000000..f91c89bb02311f104949e2af42cddc4a3faaaca3
GIT binary patch
literal 10618
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
b55LZ8wvv0OYDU-yz(0L$W374(=lK5xTFYw6

literal 0
HcmV?d00001

diff --git a/docs/zh/docs/UniProton/figures/post_semaphore.png b/docs/zh/docs/UniProton/figures/post_semaphore.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa08d76dafd335b60838dda08db61ccadd8c6b8d
GIT binary patch
literal 26707
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

!lB6}pF< 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 xr5d<>eo