Nuttx之nxsched_add_blocked

聲明:此處代碼分析,來源與 nuttx 12.8.0版本。

在分析之前,需要一圖鎮樓。

/***************************************************************************** Name: nxsched_add_blocked** Description:*   This function adds a TCB to one of the blocked state task lists as*   inferred from task_state.** Input Parameters:*   btcb - Points to the TCB that is blocked*   task_state - identifies the state of the blocked task** Returned Value:*   None** Assumptions:* - The caller has established a critical section before*   calling this function.*****************************************************************************/void nxsched_add_blocked(FAR struct tcb_s *btcb, tstate_t task_state)
{FAR dq_queue_t *tasklist;/* Make sure that we received a valid blocked state */DEBUGASSERT(task_state >= FIRST_BLOCKED_STATE &&task_state <= LAST_BLOCKED_STATE);/* Make sure the TCB's state corresponds to the list */btcb->task_state = task_state;/* Add the TCB to the blocked task list associated with this state. */tasklist = TLIST_BLOCKED(btcb);/* Determine if the task is to be added to a prioritized task list. */if (TLIST_ISPRIORITIZED(task_state)){/* Add the task to a prioritized list */nxsched_add_prioritized(btcb, tasklist);}else{/* Add the task to a non-prioritized list */dq_addlast((FAR dq_entry_t *)btcb, tasklist);}
}

顯然,此函數的作用是依據task_state,將btcb放入阻塞隊列。

既然是放入隊列,首先是要找到具體的隊列。

 /* Make sure the TCB's state corresponds to the list */btcb->task_state = task_state;/* Add the TCB to the blocked task list associated with this state. */tasklist = TLIST_BLOCKED(btcb);

TLIST_BLOCKED在sched.h中的定義如下。

/* List attribute flags */#define TLIST_ATTR_PRIORITIZED   (1 << 0) /* Bit 0: List is prioritized */
#define TLIST_ATTR_INDEXED       (1 << 1) /* Bit 1: List is indexed by CPU */
#define TLIST_ATTR_RUNNABLE      (1 << 2) /* Bit 2: List includes running tasks */
#define TLIST_ATTR_OFFSET        (1 << 3) /* Bit 3: Pointer of task list is offset */#define __TLIST_ATTR(s)          g_tasklisttable[s].attr
#define TLIST_ISPRIORITIZED(s)   ((__TLIST_ATTR(s) & TLIST_ATTR_PRIORITIZED) != 0)
#define TLIST_ISINDEXED(s)       ((__TLIST_ATTR(s) & TLIST_ATTR_INDEXED) != 0)
#define TLIST_ISRUNNABLE(s)      ((__TLIST_ATTR(s) & TLIST_ATTR_RUNNABLE) != 0)
#define TLIST_ISOFFSET(s)        ((__TLIST_ATTR(s) & TLIST_ATTR_OFFSET) != 0)#define __TLIST_HEAD(t) \(TLIST_ISOFFSET((t)->task_state) ? (FAR dq_queue_t *)((FAR uint8_t *)((t)->waitobj) + \(uintptr_t)g_tasklisttable[(t)->task_state].list) : g_tasklisttable[(t)->task_state].list)#ifdef CONFIG_SMP
#  define TLIST_HEAD(t,c) \((TLIST_ISINDEXED((t)->task_state)) ? (&(__TLIST_HEAD(t))[c]) : __TLIST_HEAD(t))
#  define TLIST_BLOCKED(t)       __TLIST_HEAD(t)
#else
#  define TLIST_HEAD(t)          __TLIST_HEAD(t)
#  define TLIST_BLOCKED(t)       __TLIST_HEAD(t)
#endif

在計算__TLIST_HEAD的時候,會有一個TLIST_ISOFFSET的判斷。那什么隊列會符合要求呢?根據定義,我們知道當g_tasklisttable[s].attr &TLIST_ATTR_OFFSET? != 0 就滿足條件。

那,具體是什么隊列呢?

static void tasklist_initialize(void)
{....../* TSTATE_WAIT_SEM */tlist[TSTATE_WAIT_SEM].list = (FAR void *)offsetof(sem_t, waitlist);tlist[TSTATE_WAIT_SEM].attr = TLIST_ATTR_PRIORITIZED |TLIST_ATTR_OFFSET;....../* TSTATE_WAIT_MQNOTEMPTY */tlist[TSTATE_WAIT_MQNOTEMPTY].list =(FAR void *)offsetof(struct mqueue_inode_s, cmn.waitfornotempty);tlist[TSTATE_WAIT_MQNOTEMPTY].attr = TLIST_ATTR_PRIORITIZED |TLIST_ATTR_OFFSET;/* TSTATE_WAIT_MQNOTFULL */tlist[TSTATE_WAIT_MQNOTFULL].list =(FAR void *)offsetof(struct mqueue_inode_s, cmn.waitfornotfull);tlist[TSTATE_WAIT_MQNOTFULL].attr = TLIST_ATTR_PRIORITIZED |TLIST_ATTR_OFFSET;......}

顯然,信號量和消息隊列會符合要求。

那么,

(FAR dq_queue_t *)((FAR uint8_t *)((t)->waitobj) + (uintptr_t)g_tasklisttable[(t)->task_state].list)具體指向那里呢?

為回答此問題,我們需要弄清楚對于信號量和消息隊列來說,waitobj 和g_tasklisttable[(t)->task_state].list各指代什么意思。

對于g_tasklisttable[(t)->task_state].list,由上述代碼可知,g_tasklisttable[TSTATE_WAIT_SEM].list 是 struct mqueue_inode_s結構體中,waitlist的偏移量。

struct sem_s
{......dq_queue_t waitlist;......}typedef struct sem_s sem_t;

對于g_tasklisttable[(t)->task_state].list,由上述代碼可知,g_tasklisttable[TSTATE_WAIT_MQNOTEMPTY].list 是 sem_t結構體中,mn.waitfornotempty的偏移量。

struct mqueue_inode_s
{struct mqueue_cmn_s cmn;    /* Common prologue */......
}struct mqueue_cmn_s
{dq_queue_t waitfornotempty; /* Task list waiting for not empty */dq_queue_t waitfornotfull;  /* Task list waiting for not full */......
};

g_tasklisttable[TSTATE_WAIT_MQNOTFULL].list 同理。

waitobj的定義如下。

struct tcb_s
{..../* POSIX Semaphore and Message Queue Control Fields ***********************/FAR void *waitobj;                     /* Object thread waiting on        */......
}

那么,waitobj的賦值是什么呢?

int nxmq_wait_receive(FAR struct mqueue_inode_s *msgq,FAR struct mqueue_msg_s **rcvmsg,FAR const struct timespec *abstime,sclock_t ticks)
{......FAR struct tcb_s *rtcb = this_task();......rtcb->waitobj = msgq;......
}

對于信號量,waitobj同理。可見,waitobj指代的是具體等待的信號量或者消息隊列。

那,為什么要這樣呢?答案就藏在數據結構的定義里。

以sem_t來說,

struct sem_s
{......dq_queue_t waitlist;......}typedef struct sem_s sem_t;

有人可能會問,這能說明什么?這能說明,對于每一個sem_t實例來說,他們都有各自的隊列。與之對應的g_tasklisttable.list中存放的是偏移值。

為什么這樣設計呢??

這樣設計實現了所有阻塞類型的統一管理。

找到具體的隊列之后,調用nxsched_add_prioritized或dq_addlast 將tcb_s加入隊列。

除了,信號量和消息隊列,還有哪些阻塞隊列呢?

enum tstate_e
{......TSTATE_TASK_INACTIVE,       /* BLOCKED      - Initialized but not yet activated */TSTATE_WAIT_SEM,            /* BLOCKED      - Waiting for a semaphore */TSTATE_WAIT_SIG,            /* BLOCKED      - Waiting for a signal */
#if !defined(CONFIG_DISABLE_MQUEUE) || !defined(CONFIG_DISABLE_MQUEUE_SYSV)TSTATE_WAIT_MQNOTEMPTY,     /* BLOCKED      - Waiting for a MQ to become not empty. */TSTATE_WAIT_MQNOTFULL,      /* BLOCKED      - Waiting for a MQ to become not full. */
#endif
#ifdef CONFIG_LEGACY_PAGINGTSTATE_WAIT_PAGEFILL,       /* BLOCKED      - Waiting for page fill */
#endif
#ifdef CONFIG_SIG_SIGSTOP_ACTIONTSTATE_TASK_STOPPED,        /* BLOCKED      - Waiting for SIGCONT */
#endif......
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88490.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88490.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88490.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 包含虛擬環境venv項目的移動

python 包含虛擬環境venv項目的移動 在ubuntu環境下&#xff0c;移動一個包含venv虛擬環境的項目后&#xff0c;在執行時會報錯: 錯誤1&#xff1a; Traceback (most recent call last):File "app.py", line 2, in <module>from flask import Flask, request…

WPF中實現TreeView的SelectedItem雙向綁定到ViewModel

WPF中實現TreeView的SelectedItem雙向綁定到ViewModel WPF中實現TreeView的SelectedItem雙向綁定到ViewModel問題背景解決方案一&#xff1a;附加行為&#xff08;推薦&#xff09;實現步驟優點 解決方案二&#xff1a;通過IsSelected屬性綁定實現步驟注意事項 兩種方案對比補充…

類型轉換運算符重載

C 類型轉換函數詳解 類型轉換函數是C中用于實現類類型與其他類型之間相互轉換的特殊成員函數&#xff0c;分為兩種主要形式&#xff1a;轉換構造函數和類型轉換運算符。 1. 轉換構造函數 (Conversion Constructor) 基本概念 轉換構造函數是一種特殊的構造函數&#xff0c;它…

ES10(ES2019)新特性整理

一、Array.prototype.flat() 和 flatMap()&#xff08;數組扁平化&#xff09; &#xff08;1&#xff09;flat(depth) 將嵌套數組“拉平”到指定深度&#xff08;默認 depth1&#xff09;。 const arr [1, [2, [3]]]; arr.flat(); // [1, 2, [3]]&#xff08;默認深度 …

基于 LCD1602 的超聲波測距儀設計與實現:從原理到應用

具體材料可在主頁資源里下載 超聲波測距技術作為非接觸式測量的重要手段&#xff0c;在工業檢測、智能家居、機器人避障等領域有著廣泛應用。本文將詳細介紹一款基于 STC89C51 單片機與 LCD1602 顯示屏的超聲波測距系統&#xff0c;從硬件架構到軟件實現&#xff0c;完整呈現一…

2.5G/5G/10G自協商An

IEEE 802.3 協議中&#xff0c;**2.5GBASE-T、5GBASE-T 和 10GBASE-T** 的鏈路自協商&#xff08;auto-negotiation&#xff0c;簡稱 AN&#xff09;是在物理層&#xff08;PHY&#xff09;完成的。它的作用是&#xff1a; * **讓連接雙方&#xff08;主機和對端&#xff09;自…

閑庭信步使用SV搭建圖像測試平臺:第五課——使用task

&#xff08;本系列只需要modelsim即可完成數字圖像的處理&#xff0c;每個工程都搭建了全自動化的仿真環境&#xff0c;只需要雙擊top_tb.bat文件就可以完成整個的仿真&#xff0c;大大降低了初學者的門檻&#xff01;&#xff01;&#xff01;&#xff01;如需要該系列的工程…

Android數據庫GreenDao的使用

簡介 GreenDao 是一個輕量級的對象關系映射&#xff08;ORM&#xff09;庫&#xff0c;用于簡化 Android 應用中的數據庫操作。它提供了以下主要功能&#xff1a; 簡化數據庫操作&#xff1a;通過注解定義實體類&#xff0c;GreenDao 自動生成 DAO&#xff08;數據訪問對象&a…

24小時留言板

title: 24小時留言板 date: 2025-06-25 23:32:53 tags: 代碼工具 24小時留言板 核心效果如圖所示 代碼解析 # TodoController 代碼解析## 整體架構 這是一個基于Spring WebFlux的響應式控制器&#xff0c;結合Redis發布\訂閱機制實現實時更新的待辦事項系統。關鍵組件包括&a…

深入理解Redis整數集合(intset)的升級策略:內存優化的核心魔法

引言 作為Redis中最節省內存的數據結構之一&#xff0c;整數集合&#xff08;intset&#xff09; 專門用于高效存儲整型數據。但你可能不知道&#xff0c;它背后藏著一個精妙的「動態升級」機制——能在不浪費內存的前提下&#xff0c;靈活適配不同大小的整數。今天我們就來扒…

高性能計算(HPC)集群和工作流:intel-oneapi-hpc-toolkit安裝與使用

成功安裝了 Intel oneAPI HPC Toolkit&#xff01;這個工具包包含了很多強大的工具&#xff0c;可以幫助你優化和加速高性能計算&#xff08;HPC&#xff09;任務&#xff0c;特別是在使用 Intel 的硬件&#xff08;如 Xeon 處理器和 GPU&#xff09;時。 接下來&#xff0c;…

QT vscode cmake 編譯 undefined reference to `vtable for 問題解決

編譯時出現undefined reference to vtable for 問題&#xff0c;是沒有添加頭文件到目標&#xff0c;添加即可&#xff1a; 如果使用的是qt5, 沒有qt_add_executable, 使用qt 5的 自動處理即可&#xff1a; # 啟用 Qt 自動處理功能 set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC …

linux內核奔潰轉儲之kexec、kdump

一、kexec是什么&#xff1f; kexec 是 Linux 內核提供的一種關鍵技術&#xff0c;允許系統?在不經過完整硬件重啟&#xff08;BIOS/UEFI 初始化&#xff09;的情況下&#xff0c;直接從當前正在運行的內核加載并啟動另一個新內核?。以下是其核心要點&#xff1a; ?定義與核…

標題:2025金融護網行動實戰指南:從合規防御到智能免疫的體系化進階

引言 2025年&#xff0c;隨著《中國人民銀行業務領域網絡安全事件報告管理辦法》正式實施&#xff0c;金融護網行動已從“合規檢查”升級為“能力對抗”。面對AI驅動的自適應攻擊、勒索病毒與黑灰產協同威脅&#xff0c;金融機構需構建“技術-管理-人才”三位一體的智能防御體…

NEO4j的安裝部署

windows neo4j新版本安裝需要部署jdk17&#xff0c;下面這個版本是jdk8最新的支持版本 neo4j-community-3.5.9-windows.zipIndex of /doc/neo4j/3.5.9/ 啟動 dos面板中啟動 neo4j.bat console linux neo4j新版本安裝需要部署jdk17&#xff0c;下面這個版本是jdk8最新的支…

八股文——JAVA基礎:說一下C++與java的區別

首先&#xff0c;c與java都是面向對象編程&#xff0c;都包含封裝、繼承、多態的特性。但是c多繼承&#xff0c;而java只能單繼承與多實現。 其次&#xff0c;java無法直接訪問內存&#xff0c;java通過引用對向&#xff0c;比如new一個對象&#xff0c;拿到的對象實例實際上是…

Vue3 Composition API 深度解析:告別Options API的局限性

目錄 一、為什么需要Composition API&#xff1f; 二、核心概念&#xff1a;setup() 函數 三、響應式核心&#xff1a;ref() 和 reactive() 1. ref - 處理基本類型/對象 2. reactive - 處理對象 四、生命周期鉤子新寫法 五、強大的邏輯復用&#xff1a;組合式函數 六、響…

IoT/HCIP實驗-5/基于NB-IoT的智慧農業實驗(平臺側開發+端側編碼+基礎調試分析)

文章目錄 概述擴展板 E53_IA1智慧農業平臺測開發功能定義/模型開發編解碼插件開發-消息編解碼插件開發-關聯編解碼插件開發-部署注冊實際設備 智慧農業端側編碼工程配置數據結構定義數據收集任務數據上報任務設備接入過程正確設置接入參數命令響應任務 程序調試其他 概述 本實…

多網絡環境vmware虛擬機配置

環境&#xff1a;一臺臺式機、一臺筆記本、筆記本中安裝虛擬機。臺式機及筆記本都使用wifi連接。 實現效果&#xff1a;虛擬機采用固定ip方式&#xff0c;臺式機可以直接連接虛擬機。 1、VMware環境配置 臺式機ip&#xff1a;192.168.31.43 筆記本ip&#xff1a;192.168.31.…

ZArchiver×亞矩云手機:云端文件管理的“超維解壓”革命

在數字化辦公與移動應用生態中&#xff0c;文件壓縮與解壓是高頻剛需場景&#xff0c;但傳統本地工具受限于設備性能、存儲空間及跨平臺協作痛點。ZArchiver&#xff08;輕量級壓縮工具&#xff09;與亞矩云手機的結合&#xff0c;通過“云端算力虛擬化環境”的創新模式&#x…