A SRQ resource allocation method, device and medium based on activity state classification

By introducing the classification management of active QP lists and idle QP lists in the RDMA network card and dynamically updating the queue pair ownership, the problem of imprecise resource allocation in the existing technology is solved, and efficient and stable SRQ resource allocation is achieved, thereby improving system performance and resource utilization.

CN122220113APending Publication Date: 2026-06-16BEIJING YUNMAI XINLIAN TECH CO LTD

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
BEIJING YUNMAI XINLIAN TECH CO LTD
Filing Date
2026-04-22
Publication Date
2026-06-16

Smart Images

  • Figure CN122220113A_ABST
    Figure CN122220113A_ABST
Patent Text Reader

Abstract

The application provides a SRQ resource allocation method and device based on activity state classification and a medium, relates to the technical field of SRQ resource allocation, and the method comprises the following steps: maintaining a cache queue of a software SRQ object and an active QP chain table and an idle QP chain table associated with the software SRQ object in a kernel driver; dynamically updating the ownership of a queue pair node between the active QP chain table and the idle QP chain table; preferentially selecting a target queue pair from the active QP chain table; selecting the target queue pair from the active QP chain table for allocation; when the active QP chain table is empty, selecting a target queue pair from the idle QP chain table for allocation; and taking out a corresponding number of receiving work request nodes from the head of the cache queue according to the number of descriptors that need to be supplemented in the selected target queue pair and issuing the receiving work request nodes to the hardware receiving queue of the target queue pair. According to the application, the queue pair can be classified and managed according to the historical activity state, the scheduling cost is reduced, and the resource allocation accuracy is improved.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention relates to the field of SRQ resource allocation technology, and in particular to an SRQ resource allocation method, device and medium based on activity status classification. Background Technology

[0002] In existing RDMA network cards, software simulation schemes for shared receive queues (SRQs) typically use a single linked list to manage all bound queue pairs. Each time a receive request needs to be allocated, all queue pairs are sorted, and the most in-demand queue pair is selected for replenishment. However, as the number of queue pairs increases, frequent full sorting operations incur significant CPU overhead, impacting overall system performance. Furthermore, existing schemes lack awareness of long-term queue pair activity patterns, failing to distinguish between suddenly active and consistently idle queue pairs. This results in imprecise resource allocation strategies—suddenly active queue pairs may experience performance degradation due to failure to acquire resources promptly, while consistently idle queue pairs may be misjudged as active due to occasional bursts, consuming excessive resources. Therefore, a method is needed that can classify and manage queue pairs based on their historical activity status, reducing scheduling overhead and improving resource allocation accuracy. Summary of the Invention

[0003] To address the aforementioned technical problems, the technical solution adopted by this invention is as follows: According to a first aspect of this application, an SRQ resource allocation method based on activity status classification is provided, the method comprising the following steps: H100 maintains a cache queue of software SRQ objects in the kernel driver, as well as an active QP list and an idle QP list associated with the software SRQ objects; the cache queue is used to cache nodes that receive work requests, the active QP list is used to record queue pairs that are currently receiving frequently, and the idle QP list is used to record queue pairs that are currently receiving less frequently. H200: Obtain the reception completion history data for each queue pair, and dynamically update the association of queue pair nodes between the active QP list and the idle QP list based on the comparison result of the reception completion history data and the preset threshold. H300, in response to the need to retrieve a receive job request from the cache queue and assign it to a queue pair, prioritizes selecting a target queue pair from the active QP list; H400: When the active QP list is not empty, a target queue pair is selected from the active QP list for allocation; when the active QP list is empty, a target queue pair is selected from the idle QP list for allocation. H500 retrieves the corresponding number of receive work request nodes from the head of the cache queue based on the number of descriptors that need to be supplemented for the selected target queue pair, and sends them to the hardware receive queue of the target queue pair.

[0004] According to another aspect of this application, a non-transitory computer-readable storage medium is also provided, wherein at least one instruction or at least one program is stored in the storage medium, and the at least one instruction or at least one program is loaded and executed by a processor to implement the above-described SRQ resource allocation method based on activity state classification.

[0005] According to another aspect of this application, an electronic device is also provided, including a processor and the aforementioned non-transitory computer-readable storage medium.

[0006] The present invention has at least the following beneficial effects: The SRQ resource allocation method based on activity state classification of this invention, compared with the prior art, firstly, by dividing queue pairs into active and idle lists and prioritizing allocation of receiving work requests from the active list, it avoids full sorting of all queue pairs during each allocation, significantly reducing scheduling overhead and improving system scalability; secondly, by dynamically updating queue pair affiliation based on multi-dimensional historical data of receiving completion (frequency, time interval, burst volume, etc.), it can accurately identify the long-term activity patterns and short-term burst behaviors of queue pairs, achieving refined resource scheduling; thirdly, the conversion of idle queue pairs to active queue pairs is triggered by an "OR condition," ensuring that suddenly active queue pairs can obtain resources in a timely manner, avoiding performance jitter; the conversion of active queue pairs to idle queue pairs is triggered by an "AND condition," avoiding frequent oscillations of queue pairs due to brief periods of idleness, improving system stability; fourthly, it supports configurable thresholds, allowing flexible adjustment of activity judgment criteria according to different application scenarios, exhibiting good adaptability and scalability; and it can classify and manage queue pairs according to their historical activity states, reducing scheduling overhead and improving the accuracy of resource allocation. Attached Figure Description

[0007] To more clearly illustrate the technical solutions in the embodiments of the present invention, the accompanying drawings used in the description of the embodiments will be briefly introduced below. Obviously, the accompanying drawings described below are only some embodiments of the present invention. For those skilled in the art, other drawings can be obtained based on these drawings without creative effort.

[0008] Figure 1 A flowchart of an SRQ resource allocation method based on activity state classification provided in an embodiment of the present invention. Detailed Implementation

[0009] The technical solutions of the embodiments of the present invention will be clearly and completely described below with reference to the accompanying drawings. Obviously, the described embodiments are only some embodiments of the present invention, and not all embodiments. Based on the embodiments of the present invention, all other embodiments obtained by those skilled in the art without creative effort are within the scope of protection of the present invention.

[0010] It should be noted that, based on this disclosure, those skilled in the art will understand that one aspect described herein can be implemented independently of any other aspect, and two or more of these aspects can be combined in various ways. For example, any number of aspects set forth herein can be used to implement the device and / or practice the method. Furthermore, this device and / or practice the method can be implemented using other structures and / or functionalities besides one or more of the aspects set forth herein.

[0011] Example 1: This embodiment, based on Embodiments 2 and 3, further introduces an active / idle doubly linked list for classifying and managing queue pairs (QPs). It dynamically adjusts the allocation of QPs based on historical data of completed reception, and prioritizes serving active QPs during allocation, thereby reducing scheduling overhead and improving resource utilization efficiency. Those skilled in the art can understand the technical details of this embodiment by referring to the relevant descriptions in Embodiments 2 and 3.

[0012] The following will refer to Figure 1 The flowchart shown illustrates an SRQ resource allocation method based on activity state classification, which introduces such a method.

[0013] The SRQ resource allocation method based on activity status classification includes the following steps: H100 maintains a cache queue of software SRQ objects in the kernel driver, as well as an active QP list and an idle QP list associated with the software SRQ objects; the cache queue is used to cache nodes that receive work requests, the active QP list is used to record queue pairs that are currently receiving frequently, and the idle QP list is used to record queue pairs that are currently receiving less frequently.

[0014] Furthermore, step H100 includes the following steps: H110 allocates an active QP linked list head (active_list) and an idle QP linked list head (idle_list) for each software SRQ object, and initializes active_list and idle_list as empty linked lists.

[0015] Allocate two linked list heads for each software SRQ object: active_qp_list (active QP list) and idle_qp_list (idle QP list), and call INIT_LIST_HEAD to initialize them as empty linked lists.

[0016] H120, in response to the specified binding to the software SRQ object when the queue pair is created, allocates a queue pair node for the corresponding queue pair; the queue pair node at least contains a pointer to the corresponding queue pair and an activity status identifier, and initially adds the corresponding queue pair node to the idle QP linked list.

[0017] When the upper-layer application creates a queue pair and specifies that it is bound to this SRQ (see step S400 in Example 2), after allocating a QP node, the node is added to the tail of the idle QP linked list via list_add_tail. The node contains at least a pointer to the corresponding QP's private structure and adds an activity status flag. It is initially placed in the idle linked list because the newly created QP has not yet received any receiving activity.

[0018] H130, maintain a historical data field for receiving completion in the private data structure of the queue pair node; the historical data field for receiving completion includes the queue pair creation timestamp, the most recent receiving completion timestamp, the two most recent receiving completion timestamps, the number of completions generated within the most recent time interval, the total number of completions, and the maximum number of completions in a single instance.

[0019] Add a field for receiving completion history data to the QP private structure (struct xsc_ib_qp), including: create_time: Recorded when QP is created (e.g., kmet_get_ns()).

[0020] last_recv_time: The timestamp of the most recent completion event, updated each time a CQE is processed.

[0021] prev_recv_time: The last_recv_time of the previous time, used to calculate the interval.

[0022] num_last_wcs: The number of CQEs between the two most recent reception completions.

[0023] total_wcs: Total number of CQEs.

[0024] max_wcs_per_poll: The maximum number of CQEs obtained in a single poll (reflecting burst capability).

[0025] These fields are initialized to 0 or creation time.

[0026] The doubly linked list approach for classifying and managing QPs lays the foundation for subsequent scheduling based on activity status. Initializing QPs into the free list is logical, and historical data fields provide quantitative basis for status determination. This data structure is compatible with embodiments two and three, and existing fields (such as rq_avail) can be reused.

[0027] H200: Obtain the reception completion history data for each queue pair, and dynamically update the association of queue pair nodes between the active QP list and the idle QP list based on the comparison result of the reception completion history data and the preset threshold.

[0028] Furthermore, step H200 includes the following steps: H210 periodically or after each processing of a receive completion event, updates the receive completion history data for each queue node.

[0029] Each time a receive completion event is processed (i.e., when polling CQ to obtain CQE), the historical data of the corresponding QP is updated: Assign the value of last_recv_time to prev_recv_time.

[0030] Assign the current timestamp to last_recv_time.

[0031] Set num_last_wcs to the number of CQEs obtained in this poll (or accumulate and then reset).

[0032] total_wcs is the cumulative number of CQEs in this instance.

[0033] If the number of CQEs this time is greater than max_wcs_per_poll, then update it.

[0034] This update can be performed in the function that drives the polling CQ, as in step S621 of Example 2.

[0035] H220: For queue pairs in the idle QP list, check the corresponding received completion history data. If any of the following conditions are met, move the corresponding queue pair from the idle QP list to the active QP list: The long-term frequency obtained by dividing the total number of completed tasks by the time interval from creation to the most recent completion exceeds a preset first threshold. The short-term frequency obtained by dividing the number of completions generated within the time interval between the two most recent reception completions by this time interval exceeds the preset second threshold. The time difference between the current timestamp and the most recent received completion timestamp is less than the preset third threshold. The maximum number of items completed in a single instance exceeds the preset fourth threshold.

[0036] For a QP node in the free list, if any of the following conditions are met, then it is moved to the active list: The frequency has exceeded the threshold for a long period: total_wcs / (last_recv_time-create_time) > THRESHOLD1. This indicates that the average receive rate of this QP since its creation is relatively high.

[0037] A short-term frequency exceeding the threshold: num_last_wcs / (last_recv_time-prev_recv_time) > THRESHOLD2. This indicates a high rate between the two most recent receptions, possibly due to processing burst traffic.

[0038] The most recent reception time is very close: current_time - last_recv_time < THRESHOLD3. This indicates that data has just been received and is likely to continue to be received soon.

[0039] Strong single-burst capability: max_wcs_per_poll > THRESHOLD4. This indicates that the QP has the ability to handle a large number of receptions at once and should be allocated resources.

[0040] H230, for queue pairs in the active QP list, check the corresponding receive completion history data: if all of the following conditions are met simultaneously, move the queue pair from the active QP list to the idle QP list: The long-term frequency obtained by dividing the total number of completed tasks by the time interval from creation to the current time is lower than the preset fifth threshold. The short-term frequency obtained by dividing the number of completions generated within the time interval between the two most recent reception completions by this time interval is lower than the preset sixth threshold. The time difference between the current timestamp and the most recent received completion timestamp is greater than the preset seventh threshold.

[0041] For a QP node in the active list, if all of the following conditions are met, it is moved to the free list: Long-term frequency below the threshold: total_wcs / (current_time-create_time) < THRESHOLD5.

[0042] Short-term frequency below the threshold: num_last_wcs / (last_recv_time - prev_recv_time) < THRESHOLD6.

[0043] No reception for a long time: current_time - last_recv_time > THRESHOLD7.

[0044] All thresholds (THRESHOLD1~7) can be set to default values ​​(such as empirical values), and can also be dynamically configured by user space via sysfs or ioctl interfaces to adapt to different application scenarios.

[0045] The "Idle → Active" condition uses an "OR" condition to ensure that suddenly active QPs can obtain resources in a timely manner, avoiding performance fluctuations; the "Active → Idle" condition uses an "AND" condition to ensure that QPs are only removed after they are truly idle, preventing frequent oscillations. Multi-dimensional indicators are used to comprehensively judge and accurately reflect the actual activity status of QPs. Configurable thresholds enhance the flexibility and adaptability of the method.

[0046] The actual activity status of QPs is comprehensively judged by multi-dimensional indicators. The "OR condition" for idle → active ensures that QPs with sudden activity can obtain resources in a timely manner, avoiding performance jitter; the "AND condition" for active → idle ensures that QPs are removed only after they are truly idle, preventing frequent oscillations. The configurable threshold enhances the flexibility of the method. This judgment mechanism is independent of cache queue operations and can be seamlessly integrated with the WR management in Examples 2 and 3.

[0047] H300, in response to the need to retrieve a receive job request from the cache queue and assign it to a queue pair, prioritizes selecting the target queue pair from the active QP list.

[0048] Furthermore, the triggering conditions in step H300 for retrieving a receive job request from the cache queue and assigning it to the queue pair include: H310, detected that the queue pair of bound software SRQ objects has switched from the RESET state to the INIT state.

[0049] When the state of a QP bound to an SRQ changes from RESET to INIT, an allocation operation is triggered. This condition is the same as step S510 in Embodiment 2 and is the basic trigger point.

[0050] H320: The number of nodes receiving work requests in the cache queue has exceeded the preset high watermark, and there are queue pairs that need to be replenished with receive descriptors.

[0051] When the number of Write-Write (WR) entries in the cache queue exceeds a preset high-water mark (e.g., max_wr*0.8), and at least one QP has an rq_avail less than rq_depth (i.e., it needs replenishment), allocation is triggered. This mechanism can be checked after each post_srq_recv or driven by a timer, with the aim of promptly distributing cached WR entries to QPs that require them, thus avoiding cache accumulation.

[0052] H330, a timer timeout was detected, triggering a periodic allocation check.

[0053] Set up a kernel timer to periodically (e.g., every 10ms) check and trigger allocation. This is especially important for scenarios where there are no events for a long time but there is still demand, ensuring that resources are not idle.

[0054] Multiple complementary triggering conditions ensure timely allocation of Write Buffers (WRs) in various scenarios. QP state switching guarantees the initial filling when a QP is ready; high-water mark triggering prevents cache overflow; and timer triggering provides a fallback to avoid omissions. These triggering mechanisms are compatible with the allocation logic in Examples 1 and 2.

[0055] H400: When the active QP list is not empty, a target queue pair is selected from the active QP list for allocation; when the active QP list is empty, a target queue pair is selected from the idle QP list for allocation.

[0056] Furthermore, step H400 includes the following steps: H410, check if the active QP list is empty: if the active QP list is not empty, take the first queue pair node from the head of the active QP list as the target queue pair.

[0057] First, check if the active QP linked list is empty. If not, retrieve the first node from the head of the linked list as the target queue pair. Use `list_first_entry` to retrieve the node and remove it from the linked list (`list_del`) or simply view it (depending on whether it needs to be retained in the linked list later). This example suggests keeping the node in the linked list, only retrieving the pointer for allocation, and leaving the node in the original linked list after allocation, awaiting the next determination.

[0058] H420: If the active QP list is empty, check if the free QP list is not empty. If the free QP list is not empty, take the first queue pair node from the head of the free QP list as the target queue pair.

[0059] If the active list is empty, check the free list. If it is not empty, take the first node from the head of the free list as the target queue pair.

[0060] H430: If both the active QP list and the free QP list are empty, then no allocation operation will be performed this time, and the process will return directly.

[0061] If both linked lists are empty, it means that no QP is bound to the SRQ, or all QPs have been destroyed, so return directly without performing allocation.

[0062] Prioritizing selection from the active list ensures that resources flow to the QPs most likely to be needed, reducing traversal and sorting overhead. Idle QPs are only considered when no active QP exists, guaranteeing fairness. This selection method is simple and efficient, with a time complexity of O(1).

[0063] H500 retrieves the corresponding number of receive work request nodes from the head of the cache queue based on the number of descriptors that need to be supplemented for the selected target queue pair, and sends them to the hardware receive queue of the target queue pair.

[0064] Furthermore, step H500 includes the following steps: H510: Obtain the preset depth rq_depth of the target queue relative to the hardware receive queue and the current number of remaining available descriptors rq_avail; calculate the number of receive descriptors to be supplemented need_cnt = rq_depth - rq_avail.

[0065] Obtain the preset depth rq_depth of the hardware receive queue of the target QP and the current remaining available descriptors rq_avail. The number of descriptors to be supplemented is need_cnt = rq_depth - rq_avail. rq_depth is set when the QP is bound to the SRQ (see step S430 in Embodiment 2), and rq_avail is maintained by the driver (see steps S530 and S613 in Embodiment 2).

[0066] H520: Get the number of nodes currently receiving work requests in the cache queue, cache_cnt. Take the smaller value between need_cnt and cache_cnt as the number of nodes n to be retrieved this time.

[0067] Get the current number of write operations (WR) in the cache queue, cache_cnt (i.e., wr_num). Take the smaller value between need_cnt and cache_cnt as the number of nodes to retrieve this time, n=min(need_cnt, cache_cnt). If need_cnt==0 or cache_cnt==0, then do not perform the retrieval this time (you can return early).

[0068] H530 starts from the first node pointed to by the head pointer head_wr of the cache queue, and takes out n nodes in sequence along the next pointer to form a linked list to be sent; updates head_wr to the first node of the remaining linked list; if the remaining linked list is empty, sets tail_wr to empty and subtracts n from the cache count wr_num.

[0069] This operation is exactly the same as step Q300 in Example 3: Starting from the first node pointed to by the head pointer head_wr of the cache queue, traverse along the next pointer to locate the nth node.

[0070] Temporarily store the next pointer of the nth node and set it to NULL, then disconnect the linked list to be retrieved from the remaining linked list.

[0071] Update head_wr to the first node of the remaining linked list; if all nodes are retrieved, set both head_wr and tail_wr to NULL.

[0072] Update the cache count wr_num by subtracting n.

[0073] For specific pointer operations, please refer to steps Q310-Q340 in Example 3.

[0074] H540 calls the hardware delivery interface to write n nodes from the delivery list into the hardware receive queue of the target queue pair, and updates the current remaining available descriptor count rq_avail of the target queue pair by n.

[0075] The hardware delivery interface (such as xsc_post_recv) is invoked to sequentially write the retrieved n nodes into the target QP's hardware receive queue circular buffer, update the tail pointer, and trigger the doorbell. This process is the same as step S612 in Embodiment 2.

[0076] Meanwhile, the n nodes issued are managed through the private head pointer srq_head_wr and tail pointer srq_tail_wr of the target QP, forming the incomplete WR linked list of the QP (see step Q400 in Example 3).

[0077] Finally, update the target QP's rq_avail by subtracting n, i.e., rq_avail = rq_avail - n, to reflect the number of newly occupied descriptors in the hardware RQ.

[0078] This step fully reuses the core mechanisms of Embodiments 2 and 3: on-demand calculation of retrieval quantity, zero-copy linked list truncation, hardware deployment, and private linked list management. Combined with doubly linked list classification, it achieves efficient and accurate resource allocation.

[0079] Furthermore, after step H500, the method further includes the following steps: H610, in response to the failure of the target queue to destroy or send a receiving work request in the corresponding private linked list, retrieves the entire incomplete node linked list pointed to by srq_head_wr to srq_tail_wr in the private linked list of the target queue.

[0080] When the target queue is destroyed (e.g., by an application calling ibv_destroy_qp) or when the WR in its private linked list fails to be issued (e.g., by a hardware error), retrieve the entire incomplete node linked list pointed to by srq_head_wr to srq_tail_wr in the private linked list of that QP. See steps Q510-Q520 in Example 3 for specific operations.

[0081] H620, return the entire incomplete node list to the cache queue, and append the returned list to the tail or head of the cache queue according to the current state of the cache queue.

[0082] Return the entire incomplete node list to the SRQ's cache queue. Depending on the current state of the cache queue, it can be appended to the tail (maintaining FIFO order) or the head (prioritizing reuse). For specific operations, see steps Q620-Q640 in Example 3.

[0083] H630 updates the head pointer head_wr, tail pointer tail_wr, and cache count wr_num of the cache queue, and sets the head and tail pointers of the private linked list of the target queue pair to null.

[0084] Update the head_wr, tail_wr, and wr_num of the cache queue, and set the head and tail pointers of the private linked list of this QP to null. See step Q650 in Example 3 for details.

[0085] The return mechanism ensures that unfinished write operations (WRs) can be reclaimed and reused when a QP is destroyed or encounters an anomaly, thus preventing memory leaks. This mechanism is completely consistent with Implementation Example 3, guaranteeing the integrity of the overall solution.

[0086] Example 2: This embodiment provides a basic implementation framework for software-simulated SRQ, providing a runtime environment and context for the resource allocation method in Embodiment 1. In Embodiment 1, the receiving work request nodes in the cache queue originate from the release of the upper-layer application. The target queue needs to calculate the number of descriptors to be replenished based on the real-time status of the hardware receiving queue. After the WR is issued, the completion status needs to be tracked and exceptions need to be handled and reclaimed. This embodiment describes in detail the creation of software SRQ objects, deep copy caching of WR, QP binding and hardware RQ depth settings, the complete WR issuance process from cache to hardware, and the completion handling and exception reclamation mechanisms. The cache queue maintained in step H100 of Embodiment 1, the WR retrieval and issuance operations involved in step H500, and the return of incomplete WRs in steps H610-H630 are all defined and implemented in this embodiment. Those skilled in the art should understand the underlying support mechanism of each step in Embodiment 1 in conjunction with this embodiment.

[0087] This embodiment proposes a method for simulating SRQ in software at the driver layer for RDMA network cards where the hardware does not support shared receive queues (SRQ). By creating software SRQ objects in the kernel driver, managing the buffering of receive work requests (WR), the binding of queue pairs (QP), and the dynamic distribution of WR, upper-layer applications can call standard verbs interfaces as if using hardware SRQ, without modifying application code. This method enables the sharing and on-demand allocation of receive resources among multiple QPs, improving resource utilization and avoiding compatibility issues caused by hardware incompatibility.

[0088] To implement this method, the following key data structures are defined in the kernel driver: / / Software SRQ object struct xsc_srq { u32 srqn; / / Unique index struct list_head srq_qp_list; / / Head of the associated QP linked list struct ib_recv_wr *head_wr; / / Head pointer of the buffer queue struct ib_recv_wr *tail_wr; / / Tail pointer of the buffer queue int wr_num; / / Current number of WR cache entries int max_wr; / / Maximum number of write buffers (from SRQ attribute) / / ... other fields }; / / QP extension structure (embedded in the driver's private QP structure) struct xsc_ib_qp { struct ib_qp ibqp; struct list_head qp_node; / / QP linked list used to attach SRQs struct xsc_srq*srq; / / Bound SRQ struct ib_recv_wr*srq_head_wr; / / Head of the private incomplete WR linked list struct ib_recv_wr*srq_tail_wr; / / Private unfinished WR linked list tail int rq_depth; / / Hardware RQ depth int rq_avail; / / Number of currently available descriptors (software tracking) / / ... Other fields }; The method for simulating an SRQ in this RDMA network card may include the following steps: S100. Create a software SRQ object in the kernel driver. The software SRQ object includes: a cache queue for caching received work requests (WRs), a QP linked list for recording associated queue pairs, and an index for uniquely identifying the software SRQ object.

[0089] In this embodiment, when the upper-layer application enters the kernel through an ibv_create_srq call, the driver first allocates a memory of a struct xsc_srq structure.

[0090] Initialize this structure: set head_wr and tail_wr to NULL, set wr_num to 0, and initialize the head of the srq_qp_list linked list.

[0091] Record the maximum number of WRs max_wr in the SRQ attributes. This value will be used for subsequent cache queue capacity control and QP depth calculation.

[0092] Allocate an idle index as srqn through a global bitmap (such as g_xres.srq_tbl) to ensure that each SRQ has a unique identifier.

[0093] Return srqn to the user space for subsequent operations to reference this SRQ.

[0094] By creating a software SRQ object in the kernel and allocating a unique index, it provides a basic data structure for all subsequent SRQ-related operations. This object is independent of the hardware, enabling the driver layer to maintain a complete SRQ state even if the hardware does not support SRQ. The bitmap allocation method ensures the uniqueness and efficient management of the index, avoiding conflicts.

[0095] S200. In response to an SRQ creation request initiated by the upper-layer application, allocate an index for uniquely identifying the software SRQ object for the upper-layer application, and initialize the cache queue and the QP linked list to be empty.

[0096] When the user space calls ibv_create_srq, after being encapsulated by libibverbs, it enters the corresponding xsc_ib_create_srq function in the kernel driver.

[0097] The driver first checks the incoming attributes: if srq_type is not IB_SRQT_BASIC or max_wr exceeds the maximum value supported by the hardware (such as 1 << XSC_MAX_SRQ_LOG_SIZE), an error is returned.

[0098] The udata parameter determines whether it is a user-mode SRQ or a kernel-mode SRQ (the latter is used internally by the kernel).

[0099] For user-space SRQ, the srqn allocated in step S100 is returned to user space through a response structure so that the index can be passed during subsequent user-space operations.

[0100] For kernel-mode SRQs, the cache queue (e.g., xsrq_cache_wr[srqn]) and QP list are initialized in preparation for receiving WRs. Regardless of the type, the cache queue and QP list must be initialized to empty.

[0101] This step creates and initializes SRQs, distinguishing between user-space and kernel-space SRQs to provide flexible support for different use cases. Validity checks prevent resource abuse and ensure the reasonableness of SRQ attributes. A unique index is returned to user space, ensuring that all subsequent operations (such as post_recv and destroy) can accurately locate the corresponding kernel object.

[0102] S300, in response to the receive job request publish operation initiated by the upper layer application, copies the content of the receive job request WR issued by the user into the kernel memory, and stores the copied WR at the tail of the cache queue.

[0103] Furthermore, step S300 includes the following steps: S310 links several copied WRs together into a linked list using their corresponding next pointers.

[0104] S320: Based on the current state of the cache queue, append the linked list to the tail of the queue, update the head pointer head_wr and tail pointer tail_wr of the cache queue, and increment the current cache count wr_num.

[0105] In this embodiment, when the application calls ibv_post_srq_recv to submit a batch of WRs, the driver enters the xsc_ib_post_srq_recv function.

[0106] To prevent data tampering caused by users reusing WR memory, the driver needs to perform a deep copy of the user-provided WR linked list into kernel memory. Specifically, this involves traversing the user-provided WR linked list (connected via next pointers), and for each WR node: Allocate kernel memory (such as kmalloc) in a size equal to struct ib_recv_wr plus any additional private data.

[0107] Copy all fields of the original WR, including the receive buffer address, length, sge array, etc.; recursively copy multiple possible sge, but usually sge is embedded in the WR structure and can be copied directly; connect the copied WR nodes through their next pointers to form a new linked list, and record the head and tail of the linked list.

[0108] Append the new linked list to the tail of the SRQ cache queue: If the cache queue is currently empty (head_wr == NULL), then head_wr and tail_wr are set to point to the head and tail of the new linked list, respectively; if the queue is not empty, then tail_wr->next is set to point to the head of the new linked list, and tail_wr is updated to point to the tail of the new linked list; the wr_num counter is incremented, and the number of WRs copied in this operation is added; if the cache queue is full (wr_num reaches max_wr), then an error is returned and handled by the upper layer.

[0109] The deep copy mechanism completely solves the data consistency problem caused by user-space memory reuse, ensuring the stability of the write-write (WR) content during subsequent hardware access. Organizing the cache using a linked list makes append and retrieval operations efficient and eliminates the need for memory movement. Maintaining head and tail pointers and a counter provides an accurate queue state for subsequent dynamic allocation.

[0110] S400, in response to specifying binding to the software SRQ object when the queue pair is created, adds the node of the queue pair bound to the software SRQ object to the QP linked list, and sets the depth of the hardware receive queue bound to the software SRQ object queue pair according to the capacity of the software SRQ object.

[0111] Furthermore, step S400 includes the following steps: S410, responding to the upper-layer application creating a queue pair QP a When specifying binding to the software SRQ object, and QP a For kernel-mode queue pairs, for QP a Allocate a queue for node NU a .

[0112] When an upper-layer application creates a queue pair via ibv_create_qp and sets the srq field in the QP attribute (struct ibv_qp_init_attr) to point to an already created software SRQ, the kernel driver enters the xsc_ib_create_qp function.

[0113] The driver first determines the type of the QP: distinguishing between a user-mode QP and a kernel-mode QP using the udata parameter. For kernel-mode QPs (i.e., QPs used internally by the kernel or directly managed by the kernel driver), the following operations are performed: Allocate a queue pair node data structure NUa This node is typically defined as follows: struct srq_qp_node{ struct list_head entry; / / Linked list node, used to attach the SRQ's QP linked list. struct xsc_ib_qp*qp; / / Pointer to the actual QP structure / / Optional statistical information fields, such as creation timestamp, etc. }; Set NUa->qp to point to the QP structure currently being created (struct xsc_ib_qp, i.e., the driver's private QP extension structure).

[0114] It should be noted that if the QP is a user-space QP, information may need to be passed between user space and kernel space, but node allocation and management are still performed in the kernel.

[0115] Each QP bound to an SRQ requires a separate node so that the SRQ can record and manage all associated QPs. The node must contain at least a pointer to the QP so that when the SRQ needs to issue a WR to the QP, it can use this pointer to find the target QP's private data (such as hardware RQ status, private linked lists, etc.).

[0116] By assigning an independent node to each bound QP, SRQ can dynamically maintain the set of associated QPs, supporting the on-demand addition and removal of QPs. Nodes store only necessary information, resulting in low memory overhead, and the linked list structure allows for efficient traversal.

[0117] S420, NU a Add it to the tail of the QP linked list of the software SRQ object using the list_add_tail operation; NU a At least contains pointers to QP a The pointer.

[0118] Retrieve the head of the QP linked list maintained in the software SRQ object, i.e., srq_qp_list in struct xsc_srq. Call the kernel linked list operation function list_add_tail(&NU a ->entry,&srq->srq_qp_list), will move node NU a Add it to the end of the linked list. This operation ensures the order of the newly added QP in the linked list (sorted by binding time), facilitating subsequent traversal.

[0119] Adding nodes to the tail of the linked list preserves the chronological order of QP bindings. In some scenarios, QPs bound earlier may have a certain priority; at the same time, the insertion operation at the tail of the linked list has an O(1) complexity, which does not affect performance. The linked list structure itself supports subsequent traversal, sorting, and deletion operations.

[0120] By using linked list management, SRQ can obtain all currently bound QPs at any time, providing a candidate set for subsequent WR allocation. Insertion at the tail of the linked list is simple and efficient, and supports subsequent dynamic sorting (such as sorting to supplement the quantity as needed), meeting the needs of different allocation strategies.

[0121] S430, obtain the maximum WR capacity srq_max_wr of the software SRQ object, and the maximum depth of the receive queue for a single queue pair supported by the hardware, hw_max_rq_depth, and take the smaller value of srq_max_wr and hw_max_rq_depth as the QP. a The preset depth of the hardware receive queue is rq_depth.

[0122] Retrieve the maximum receive queue (WR) capacity `srq_max_wr` from the software SRQ object. This value is specified by the user when the SRQ is created and represents the total number of receive WRs that the SRQ can accommodate. Retrieve the maximum receive queue depth for a single queue pair supported by the hardware from the hardware capability register or driver configuration, `hw_max_rq_depth`. Different hardware may have different limitations; for example, some network cards have a maximum RQ depth of 128, 256, or 1024 per QP. Take the smaller of these two values ​​as the default hardware receive queue depth for this QP: `rq_depth = min(srq_max_wr, hw_max_rq_depth)`.

[0123] Store rq_depth in the rq_depth field of QP’s private extended structure xsc_ib_qp, and initialize rq_avail=rq_depth (representing the number of currently available descriptors).

[0124] For example: if the maximum SRQ capacity is 1024 and the maximum hardware depth is 128, then the actual RQ depth of this QP is set to 128; if the maximum SRQ capacity is 64 and the maximum hardware depth is 128, then it is set to 64.

[0125] Although QPs are bound to SRQs and share the receive buffer, each QP still needs its own independent receive queue (RQ) at the hardware level because the hardware can only retrieve WQEs from the RQ. Therefore, a reasonable depth must be set for the RQ of each QP. This depth cannot exceed the total capacity of the SRQ (otherwise it may consume too many shared resources) nor exceed hardware limitations. Taking a smaller value ensures hardware feasibility while avoiding a single QP consuming too many shared WR resources.

[0126] By dynamically calculating the RQ depth of each QP, a balance between shared resources and hardware limitations is achieved. This ensures that the hardware can function normally while preventing a single QP from monopolizing the WR resources of the SRQ due to excessive depth, thus laying the foundation for fair sharing among multiple QPs.

[0127] S440, write rq_depth to QP a The hardware receive queue configuration register is used to complete the hardware receive queue depth setting.

[0128] The hardware abstraction layer interface is invoked to write the calculated `rq_depth` value to the hardware receive queue configuration register of the QP. Specific operations depend on the hardware implementation and may include: finding the context index of the QP in the hardware; writing the configuration value to the specified register address or doorbell page via PIO or DMA; and setting other relevant parameters (such as WQE size, ring buffer base address, etc.), which can be completed in other steps of QP creation.

[0129] After a successful write, the circular buffer depth of the hardware receive queue is determined as rq_depth, and the hardware will subsequently manage receive descriptors based on this depth. Simultaneously, the driver records this depth in a private structure of the QP and initializes the software-tracked available descriptor count rq_avail.

[0130] The hardware receive queue depth must be configured before QP activation and is generally not dynamically changeable once configured (unless the QP is destroyed and rebuilt). Therefore, it is necessary to complete this configuration during the QP creation phase. Only after this configuration is written to the hardware can it correctly manage and use the RQ.

[0131] Writing the depth to the hardware completes the implementation of software strategy into hardware configuration. The hardware manages the receive descriptor according to the preset depth, and the driver tracks rq_avail to ensure consistency, providing an accurate basis for subsequent dynamic WR allocation. Simultaneously, this configuration ensures that the hardware can correctly process receive requests and will not cause errors due to improper depth settings.

[0132] S500, in response to the queue pair with bound software SRQ objects switching to the ready state, a number of WRs are taken from the head of the cache queue; wherein, the number of WRs taken is determined according to the number of currently available descriptors in the hardware receive queue of the corresponding queue pair.

[0133] When the QP state changes from RESET to INIT (via the modify_qp operation), the driver checks whether the QP is bound to an SRQ. If so, the WR delivery process is triggered, entering the delivery logic (or a separate function) within xsc_ib_post_srq_recv.

[0134] Furthermore, step S500 includes the following steps: S510 If the state of the queue pair of the bound software SRQ object is detected to switch from the RESET state to the INIT state, the operation of retrieving WR from the cache queue is triggered.

[0135] In the QP state change handling function, if the new state is INIT and the old state is RESET, and the QP is bound to SRQ, the dispatch function is called.

[0136] S520: Obtain the current remaining available descriptor count rq_avail of the target queue to the hardware receive queue, and the preset depth rq_depth of the target queue to the hardware receive queue, and determine the number of receive descriptors to be supplemented as rq_depth-rq_avail based on rq_avail and rq_depth; the target queue pair is a queue pair that has been bound to a software SRQ object.

[0137] Obtain the target QP's rq_depth and current rq_avail (the number of remaining available descriptors traced by the software). The padding amount needs to be equal to rq_depth minus rq_avail. It should be noted that rq_avail is initially set to rq_depth, decreasing as the WR (Write-Ahead Message) is sent and increasing upon completion of reception.

[0138] S530, get the current number of WRs cached in the cache queue, cache_avail, and take the smaller value between rq_depth-rq_avail and cache_avail as the number of WRs n to be retrieved this time.

[0139] Get the current count wr_num (i.e., cache_avail) of the SRQ cache queue. Take the smaller value between need and cache_avail as the actual number of items to be retrieved, n. If need == 0 or cache_avail == 0, then no retrieval is performed this time.

[0140] S540: Starting from the first WR node pointed to by the head pointer head_wr of the cache queue, n WR nodes are taken out sequentially along the next pointer to form a linked list of WR nodes to be issued; the head pointer head_wr of the cache queue is updated to point to the first node of the remaining linked list. If the remaining linked list is empty, the tail pointer tail_wr is updated to be empty at the same time, and the cache count wr_num is reduced.

[0141] Starting from `head_wr`, iterate through the `next` pointers to locate the `n`th node. Temporarily store the `next` pointer of the `n`th node and set it to NULL, severing its connection with the remaining linked list. Update `head_wr` to the `n+1`th node (i.e., the head of the remaining linked list). If `n` equals the original linked list length, both `head_wr` and `tail_wr` are set to NULL. Update `wr_num` by subtracting `n`.

[0142] S550: The n extracted WR nodes are managed by the target queue through the private head pointer srq_head_wr and tail pointer srq_tail_wr, forming the target queue's private incomplete WR linked list, and the length of the incomplete WR linked list is recorded.

[0143] The extracted linked list of n nodes is managed using QP's `srq_head_wr` and `srq_tail_wr`: If the QP's private linked list is empty (`srq_head_wr == NULL`), then `srq_head_wr` and `srq_tail_wr` are set to point to the head and tail of the linked list, respectively. If it is not empty, then the original `srq_tail_wr->next` is set to point to the head of the new linked list, and `srq_tail_wr` is updated to point to the tail of the new linked list. It should be noted that at this point, these nodes are not yet written to the hardware; they are only recorded as having been allocated to the QP.

[0144] This step enables dynamic allocation of Write Controllers (WRs) from the cache to the Query Buffer (QP). By calculating the required replenishment quantity, it ensures that the allocation matches the actual needs of the QP, avoiding over-allocation or under-allocation. Truncation from the cache head guarantees the WR's first-in-first-out (FIFO) order (if necessary). Transferring nodes to the QP's private linked list enables tracking of allocated but incomplete WRs, laying the foundation for subsequent completion processing and exception handling. The triggering timing is chosen when the QP enters the INIT state, meeting hardware requirements and avoiding operation in an invalid state.

[0145] S600 sends the retrieved WR to the hardware receive queue of the corresponding queue pair, and records the sent WR as the private incomplete WR of the corresponding queue pair until the hardware completes and generates a completion event, after which it is released.

[0146] After step S550, the hardware delivery interface is called to actually write the WR in the QP private linked list into the hardware RQ.

[0147] Furthermore, step S600 includes the following steps: S611, retrieve the WR list LR to be sent from the head of the buffer queue; LR contains n WR nodes, each WR node contains the address, length and control information of the receive buffer.

[0148] The linked list obtained in step S550 is the linked list to be sent down, denoted as LR.

[0149] S612 calls the hardware delivery interface to sequentially write the n WR nodes in LR into the circular buffer of the hardware receive queue of the target queue pair. Each time a WR node is written, the tail pointer of the hardware receive queue is updated, and a doorbell is triggered to notify the hardware that a new receive request is available.

[0150] For each WR node in the LR, it is converted to hardware WQE format and written to the hardware RQ ring buffer of the target QP (usually a pre-mapped DMA memory).

[0151] Each time a WQE is written, the tail pointer of the hardware RQ is updated (by writing to a register or memory mapping), and finally a doorbell is triggered to notify the hardware of a new receive request. It should be noted that multiple WQEs may be written at once and then the doorbell is triggered all at once to optimize performance.

[0152] S613, manage the private head pointer srq_head_wr and tail pointer srq_tail_wr of the n WR nodes issued this time through the corresponding queue; if the queue is empty of the private linked list, then srq_head_wr and srq_tail_wr point to the first and last WR nodes respectively; if it is not empty, then the next pointer of the node originally pointed to by srq_tail_wr is pointed to the first WR node issued this time, and srq_tail_wr is updated to the last WR node issued this time, while the length count of the private linked list of the queue is incremented.

[0153] In fact, step S550 has already added the nodes to the private linked list. It's important to emphasize that these nodes have already been deployed to the hardware and are awaiting completion events. Updating the QP's rq_avail by subtracting n reflects the reduction in available descriptors in the hardware RQ.

[0154] Furthermore, step S600 also includes the following steps: S621, in response to polling the completion queue and obtaining the reception completion event CQE, parse the corresponding WR identifier from the CQE, search for a matching WR node starting from the head of the private linked list of the queue; if a match is found, remove the WR node from the private linked list, update srq_head_wr to point to the next node, and release the kernel memory occupied by the WR node.

[0155] When the hardware completes receiving and generates a CQE, the driver processes it while polling the CQ (e.g., ibv_poll_cq). The corresponding WR identifier (e.g., WQE index or user context) is parsed from the CQE. A matching WR node is searched for from the head of the QP private linked list. Due to FIFO characteristics, the first node is usually the earliest issued, and the search proceeds sequentially. Once found, the node is removed from the private linked list: srq_head_wr is updated to point to the next node; if the linked list is empty after removal, srq_tail_wr is set to NULL. The kernel memory occupied by this node is released (since the process is complete). Simultaneously, rq_avail is updated and incremented by 1, indicating that a descriptor has been released in the hardware RQ.

[0156] S622, in response to the queue pair destruction operation, check if the queue pair's private linked list is empty; if not empty, return the entire incomplete WR linked list pointed to by srq_head_wr to srq_tail_wr to the cache queue of the software SRQ object.

[0157] S623, based on the current state of the cache queue, append the return list to the tail or head of the cache queue, update the head pointer head_wr, tail pointer tail_wr and cache count wr_num of the cache queue, and set the head and tail pointers of the private linked list of the queue pair to null.

[0158] When a QP is destroyed, check if its private linked list is empty. If it is not empty, it means there are unfinished Writes (WRs) (e.g., a CQE was not generated due to a QP error). Return the entire private linked list (srq_head_wr to srq_tail_wr) to the SRQ cache queue. The return strategy can be: append to the tail of the cache queue (maintaining the original order) or to the head (preferential use), which can be chosen according to the design. Update the head_wr, tail_wr, and wr_num of the cache queue. Set the head and tail pointers of the QP's private linked list to null, and remove the QP node from the SRQ's srq_qp_list.

[0159] This step completes the final deployment of Write-Registers (WRs) from software to hardware and manages their entire lifecycle. Tracking incomplete WRs using a private linked list ensures accurate matching and resource release during completion event handling. The return mechanism during QP destruction ensures no resource leakage, and the cache queue can reuse these WRs. Simultaneously, real-time updates to `rq_avail` provide accurate data for subsequent allocation. The entire process achieves a secure and efficient flow of WRs.

[0160] Furthermore, when multiple queue pairs simultaneously meet the retrieval conditions, step S500 further includes: S560 sorts the queue pairs that meet the conditions from largest to smallest according to the corresponding number of replenishment required, and takes out WRs from the cache queue in turn for allocation.

[0161] When multiple QPs are simultaneously in a state that requires additional WRs (e.g., multiple QPs simultaneously enter INIT or simultaneously generate receive complete events), and there are enough WRs in the buffer queue, the driver needs to sort the candidate QPs to determine the allocation order.

[0162] In step S500, all QPs that meet the conditions are obtained (this can be done by iterating through the SRQ's srq_qp_list and checking if their rq_avail is less than rq_depth). These QPs are then sorted in descending order of their replenishment quantity (rq_depth - rq_avail). The larger the replenishment quantity, the scarcer the QP is, and it should be allocated first. The sorting algorithm can use the kernel's list_sort, passing in a custom comparison function. Then, WRs are sequentially retrieved from the cache queue and allocated to each QP until the cache is exhausted or all QPs are satisfied.

[0163] By prioritizing multiple QPs, resources are ensured to be allocated preferentially to the most scarce QPs, preventing some QPs from starving due to prolonged lack of replenishment. This dynamic priority scheduling improves the overall system's receiving performance, and is particularly suitable for scenarios with uneven load.

[0164] Example 3: Building upon Example 1, this example further focuses on the pointer control mechanism between the cache queue and the private linked list of the queue pair, enabling zero-copy transfer of receiving work requests in kernel memory. The H500 step in Example 1 requires retrieving the receiving work request node from the head of the cache queue and sending it to the hardware receiving queue of the target queue pair, while simultaneously tracking its incomplete status. This example maintains the head pointer `head_wr` and tail pointer `tail_wr` of the cache queue, and the private head pointer `srq_head_wr` and tail pointer `srq_tail_wr` of the queue pair, combined with linked list truncation, appending, and returning operations, achieving efficient transfer of WR from the cache queue to the QP private linked list, and ensuring complete resource recovery when the QP is destroyed or the sending fails. This pointer control mechanism can serve as a specific implementation of the H500 step in Example 1, is fully compatible with Example 1, and can be used alone or in combination with Example 1.

[0165] Q100 maintains a cache queue of software SRQ objects in the kernel driver; the cache queue consists of multiple receiving work request nodes linked together by the next pointer, each receiving work request node is a node generated by deep copying in kernel memory and contains receiving buffer information, and the cache queue records the head pointer head_wr and the tail pointer tail_wr.

[0166] The struct xsc_srq structure is allocated and initialized during kernel driver initialization or when a software SRQ object is created.

[0167] The buffer queue consists of multiple nodes that receive work requests linked together by the next pointer. Each node is a struct ib_recv_wr structure generated by a deep copy in kernel memory, containing information such as the address and length of the receive buffer and the SGE array (see step S300 in Example 2 for the deep copy process).

[0168] The cache queue records the head pointer `head_wr` and the tail pointer `tail_wr`, both initially NULL. It also maintains a counter `wr_num`, initially set to 0. The maximum capacity of the cache queue is determined by the SRQ attribute `max_wr`, stored in the `max_wr` field.

[0169] By managing WR nodes using a linked list structure and combining head and tail pointers, efficient FIFO access operations are achieved without moving data. Deep copying ensures data security and lays the foundation for subsequent pointer operations.

[0170] Q200: When it is necessary to retrieve a number of receive work requests from the cache queue and allocate them to the target queue pair, the number of nodes n retrieved this time is determined according to the number of descriptors that the target queue pair needs to supplement in the hardware receive queue.

[0171] Furthermore, step Q200 includes the following steps: Q210: Obtain the current number of available descriptors rq_avail for the target queue relative to the hardware receive queue, and the preset depth rq_depth for the target queue relative to the hardware receive queue. Calculate the number of receive descriptors to be supplemented by subtracting rq_avail from rq_depth.

[0172] When it is necessary to retrieve a WR from the buffer queue and allocate it to the target queue pair, the following steps are first taken: First, the number of remaining available descriptors in the hardware receive queue of the target queue pair, rq_avail (this value is maintained by the driver decrementing by 1 each time a WR is issued and incrementing by 1 each time a receive operation is completed), and the preset depth of the queue pair, rq_depth (calculated based on SRQ capacity and hardware limitations during QP creation, see step S430 in Example 2). The required replenishment amount is need = rq_depth - rq_avail. For example, if rq_depth = 16 and the current rq_avail = 3, then need = 13.

[0173] Q220: Get the number of nodes currently cached in the cache queue, cache_avail. Take the smaller value between the number of receive descriptors that need to be supplemented and cache_avail as the number of nodes to be retrieved this time, n.

[0174] Get the current number of write operations (WRs) in the cache queue, cache_avail (i.e., wr_num). Take the smaller value between need and cache_avail as the number of nodes to retrieve this time, n = min(need, cache_avail). For example, if need = 13 and cache_avail = 20, then n = 13; if cache_avail = 5, then n = 5.

[0175] Q230: If the number of receive descriptors to be supplemented is 0 or cache_avail is 0, then no retrieval operation will be performed this time, and the operation will be returned directly.

[0176] If need == 0 (i.e., the target queue already has enough descriptors) or cache_avail == 0 (the cache queue is empty), then the retrieval operation is not performed this time, and the operation is returned directly. This avoids unnecessary linked list operations.

[0177] The above steps, through dynamic calculation of the required replenishment quantity and the actual available quantity, ensure that the number of WRs retrieved each time satisfies the actual needs of the queue pairs without exceeding the supply capacity of the cache queue. On-demand allocation avoids resource waste and prevents starvation in other queue pairs due to over-allocation. Pre-checking for null conditions reduces invalid operations and improves efficiency.

[0178] Q300: Starting from the node pointed to by head_wr, extract n nodes sequentially along the next pointer, and update head_wr to the first node of the remaining linked list. If the remaining linked list is empty, set tail_wr to null at the same time.

[0179] Furthermore, step Q300 includes the following steps: Q310: Starting from the first node receiving a work request, which is pointed to by the head pointer head_wr of the cache queue, traverse the linked list along the next pointer and record the position of the nth node.

[0180] Starting from the first node pointed to by head_wr in the cache queue, traverse the linked list along the next pointer, recording the position of the nth node. For example, if n=3, then traverse to the third node, denoted as node_n.

[0181] Q320: Temporarily store the next pointer of the nth node and set it to NULL to disconnect the linked list to be retrieved from the remaining linked list.

[0182] The next pointer of node_n is temporarily set to NULL, so that the list from head_wr to node_n becomes an independent list to be retrieved, and the node that node_n->next originally pointed to becomes the first node of the remaining list.

[0183] Q330 updates the head pointer head_wr of the cache queue to the next node of the nth node; if n equals the current total number of nodes in the cache queue, then both head_wr and tail_wr are set to NULL.

[0184] Update the head_wr of the cache queue to the next node of node_n (i.e., the first node of the remaining linked list). If n equals the current total number of nodes in the cache queue (i.e., all nodes have been retrieved), the remaining linked list is empty, and in this case, set both head_wr and tail_wr to NULL.

[0185] Q340, Update the cache count of the cache queue wr_num = wr_num - n.

[0186] Subtract n from the cache count wr_num, i.e., wr_num = wr_num - n.

[0187] For example: Suppose the cache queue originally has 5 nodes, with the head pointer pointing to node A, and the order A→B→C→D→E, and the tail pointer pointing to E, with wr_num=5. If n=3, then A, B, and C are retrieved. After the operation, the head pointer points to D, the tail pointer still points to E, and wr_num=2. If n=5, all nodes are retrieved, then both the head and tail pointers are set to NULL, and wr_num=0.

[0188] Linked list slicing is achieved through pointer operations, eliminating the need for memory copying and achieving a time complexity of O(n) (traversing n nodes). After updating the head and tail pointers and the count, the cache queue state accurately reflects the remaining resources. This zero-copy approach significantly improves performance, making it particularly suitable for scenarios with frequent write-and-reset allocations.

[0189] Q400: The extracted n nodes are managed by the target queue through the private head pointer srq_head_wr and tail pointer srq_tail_wr, forming a target queue private unfinished receiving work request list; if the target queue private list is empty, a new list is created directly; otherwise, the extracted list is appended to the tail of the original private list and the tail pointer is updated.

[0190] Furthermore, the Q400 includes the following steps: Q410, obtain the distribution linked list LB composed of n nodes that receive work requests; the head node of LB is the first node taken from the cache queue, and the tail node is the nth node with the corresponding next pointer set to NULL.

[0191] The n nodes extracted in step Q300 form an independent linked list, denoted as LB (the descending linked list). The head node of LB is the first node that head_wr originally pointed to, and the tail node is the nth node whose next pointer is NULL.

[0192] Q420: Get the private linked list status of the target queue pair; if srq_head_wr of the target queue pair is NULL, then set srq_head_wr and srq_tail_wr to point to the head node and tail node of LB respectively.

[0193] Obtain the private linked list status of the target queue pair, i.e., check if its srq_head_wr is NULL. If it is NULL, it means that the queue pair currently has no incomplete writes (WRs), then directly set srq_head_wr and srq_tail_wr to point to the head node and tail node of the LB, respectively.

[0194] Q430, if the private linked list of the target queue is not empty, then the next pointer of the tail node originally pointed to by srq_tail_wr is pointed to the head node of LB, and srq_tail_wr is updated to the tail node of the distributed linked list.

[0195] If the private linked list is not empty, the next pointer of the tail node originally pointed to by srq_tail_wr is set to the head node of LB, thus appending LB to the tail of the private linked list. Then, srq_tail_wr is updated to the tail node of LB, i.e., the last WR node.

[0196] Q440, add a length counter for the private linked list in the target queue, and record the total number of nodes that have not yet completed receiving work requests.

[0197] Increase the length count of the private linked list in this queue and record the total number of WRs that are not yet completed, so as to facilitate subsequent processing or statistics.

[0198] For example: Suppose the target queue has existing nodes X→Y in the private linked list, srq_head_wr=X, srq_tail_wr=Y, and Y's next=NULL. The linked list LB issued this time is A→B→C. After appending, Y's next points to A, and srq_tail_wr is updated to C, forming the linked list X→Y→A→B→C.

[0199] By managing allocated but incomplete WRs using head and tail pointers of a private linked list, precise tracking of the WR lifecycle is achieved. Append operations only require modifying pointers, without traversal, resulting in a time complexity of O(1). In this way, when a subsequent receive completion event occurs, a matching WR can be quickly found from the head and released, while also providing a complete basis for reclamation in abnormal situations (such as QP destruction).

[0200] Q500, when the target queue fails to destroy or send a receiving work request in the corresponding private linked list, the entire unfinished node linked list pointed to by srq_head_wr to srq_tail_wr in the private linked list of the target queue is returned to the cache queue.

[0201] Furthermore, step Q500 includes the following steps: Q510, in response to a target queue destruction operation or a failure to receive a work request in the private linked list, obtain the current srq_head_wr and srq_tail_wr pointers for the target queue.

[0202] The return operation is triggered under the following two circumstances: The target queue is destroyed (e.g., when the application calls ibv_destroy_qp).

[0203] The WR in the private list failed to be issued (e.g., the hardware RQ was full, preventing issuance, or the hardware returned an error).

[0204] At this point, obtain the current srq_head_wr and srq_tail_wr pointers for this queue.

[0205] Q520. If srq_head_wr is not NULL, then it is confirmed that there is an incomplete receiving work request node list. The head node pointer of the incomplete receiving work request node list is temporarily stored as return_head, and the tail node pointer is temporarily stored as return_tail.

[0206] If srq_head_wr is not NULL, it means there is an incomplete linked list of WR nodes. The head node pointer of this linked list is temporarily stored as return_head, and the tail node pointer is temporarily stored as return_tail, for later return.

[0207] Q530 sets both srq_head_wr and srq_tail_wr of the target queue pair to NULL and clears the private linked list length count to zero to prevent repeated access during the return process.

[0208] Set both srq_head_wr and srq_tail_wr of the target queue pair to NULL, and clear the private linked list length count to zero. This step must be completed before returning the queue to prevent it from being accessed by other concurrent operations (such as completion event handling) during the return process.

[0209] By promptly detecting anomalies and destruction events, incomplete write operations are ensured to be reclaimed, preventing memory leaks. Clearing private linked list pointers prevents concurrent access risks and provides a safe premise for subsequent return operations.

[0210] Q600 appends the return list to the tail or head of the cache queue according to the current state of the cache queue, and updates the head_wr, tail_wr and cache count wr_num of the cache queue.

[0211] Furthermore, step Q600 includes the following steps: Q610: Get the current head_wr and tail_wr pointers and cache count wr_num of the cache queue.

[0212] Q620, Determine the current state of the cache queue: If head_wr is NULL, then set head_wr and tail_wr to the head node return_head and tail node return_tail of the return list, respectively.

[0213] If head_wr is NULL, it means the cache queue is empty. In this case, head_wr and tail_wr are directly set to point to the head node return_head and the tail node return_tail of the return list, respectively.

[0214] Q630: If the cache queue is not empty and the tail append strategy is adopted, then the next pointer of the tail node originally pointed to by tail_wr is set to return_head, and tail_wr is updated to return_tail.

[0215] If the cache queue is not empty and the system is configured with a tail-append strategy (the default strategy), then the next pointer of the tail node originally pointed to by tail_wr is set to return_head, and tail_wr is updated to return_tail. In this way, the return list is appended to the tail of the cache queue, maintaining the original FIFO order.

[0216] Q640: If the cache queue is not empty and the head append strategy is adopted, then the next pointer of return_tail is set to the current head_wr, and head_wr is updated to return_head.

[0217] If a head-append strategy is adopted (e.g., to prioritize the recently returned WR), then the next pointer of return_tail is set to point to the current head_wr, and head_wr is updated to return_head. This inserts the return list into the head of the cache queue.

[0218] Q650, update wr_num = wr_num + n; n is the number of nodes in the returned linked list.

[0219] Add the number of nodes to be returned to the linked list (i.e., n, which can be obtained from the length of the linked list) to wr_num, i.e., wr_num = wr_num + n.

[0220] For example: Assume the original cache queue has nodes M→N, head_wr=M, tail_wr=N, and wr_num=2. The returned linked list is A→B→C (3 nodes). If appending to the tail is used, then N's next pointer points to A, tail_wr is updated to C, and the queue becomes M→N→A→B→C, with wr_num=5. If appending to the head is used, then C's next pointer points to M, head_wr is updated to A, and the queue becomes A→B→C→M→N, with wr_num=5.

[0221] The return operation is also completed through pointer adjustment, eliminating the need for memory copying. It supports either tail or head appending strategies, which can be flexibly configured according to system load characteristics. For example, for bursty traffic, the head appending strategy can be selected to prioritize the use of recently reclaimed resources. After updating the count, the cache queue status is accurate, providing a basis for subsequent allocation.

[0222] Furthermore, in step Q200, when it is necessary to retrieve several receive work requests from the cache queue and assign them to the target queue pair, the method further includes the following steps: Q240, maintain a single QP linked list srq_qp_list consisting of all queue pairs associated with the software SRQ object.

[0223] In the software SRQ object, a single QP linked list srq_qp_list is maintained to record all queue pairs (nodes contain pointers to QPs and related states) that are bound to the SRQ.

[0224] Q250: When a receive job request needs to be retrieved from the cache queue, iterate through srq_qp_list to obtain the number of currently available descriptors for each queue relative to the hardware receive queue.

[0225] When it is necessary to retrieve WRs from the cache queue and allocate them to the queue pair (for example, when multiple QPs are in a state that needs to be replenished at the same time), traverse srq_qp_list and get the number of currently available descriptors rq_avail for each node corresponding to its QP.

[0226] Q260, Sort the queue pairs in srq_qp_list in ascending order of the number of remaining available descriptors, and select the queue pair at the head of the list after sorting as the target queue pair.

[0227] Sort the linked list nodes in ascending order of `rq_avail` (i.e., the most scarce nodes are placed first), and select the queue pair at the head of the sorted list as the target queue pair for this allocation. The sorting can be done using the kernel's `list_sort` function.

[0228] All associated QPs are managed by a single linked list and sorted based on real-time demand, ensuring that the most scarce queue pairs are prioritized for each allocation. This effectively prevents some QPs from starving due to long-term lack of replenishment and improves overall receiving performance.

[0229] Furthermore, sorting the nodes in the queue of srq_qp_list according to the number of remaining available descriptors in ascending order includes the following steps: Q261 calls the kernel-provided list_sort function to perform merge sorting on srq_qp_list; the comparison function used for sorting is cmp_flush_wge_cnt, which compares the number of currently available descriptors for nodes in the two queues and returns the node with the smaller number of descriptors in the queue.

[0230] The `list_sort` function provided by the Linux kernel is called to sort `srq_qp_list`. This function is implemented as a merge sort, with a time complexity of O(nlogn), and is stable and suitable for linked list structures. A custom comparison function `cmp_flush_wge_cnt` is passed in.

[0231] Q262, after sorting, the head of srq_qp_list is the queue pair that most needs to be supplemented to receive work requests.

[0232] The `cmp_flush_wge_cnt` function takes pointers to nodes of two queue pairs, extracts the current remaining available descriptor count `rq_avail` for the corresponding QP, and compares them. If the `rq_avail` of the first node is less than that of the second node, it returns a negative value, indicating that the first node should be placed first. After sorting, the head of the linked list is the node with the smallest `rq_avail`, which is the queue pair that most needs to be replenished with WR.

[0233] By utilizing standard kernel sorting functions, the implementation is simplified, ensuring both reliability and performance. Custom comparison functions allow for flexible adaptation to different sorting needs (e.g., future expansion to sorting based on required quantity). After sorting, the target can be directly retrieved from the head, resulting in high allocation efficiency.

[0234] Example 4: This embodiment provides an SRQ resource allocation method based on sorting a single QP linked list, which complements the doubly linked list classification method in Embodiment 1. Embodiment 1 reduces scheduling overhead through active / idle doubly linked list classification, while this embodiment maintains a single QP linked list and sorts all queue pairs by the number of remaining available descriptors before each allocation, prioritizing the most scarce queue pairs to avoid starvation. Steps R200-R500 in this embodiment can be considered an alternative implementation of steps H300-H500 in Embodiment 1; that is, first traversing the single linked list to obtain the remaining available descriptors, sorting them, selecting the target queue pair, and then performing WR retrieval and allocation. Those skilled in the art can choose or combine these two allocation strategies according to actual application scenarios to balance scheduling efficiency and resource utilization.

[0235] R100 maintains a cache queue and a QP linked list for software SRQ objects in the kernel driver; the cache queue is used to cache nodes that receive work requests, and the QP linked list is used to record all queue pairs of nodes bound to software SRQ objects.

[0236] In the kernel driver, a cache queue is maintained for each software SRQ object to cache the nodes that receive work requests (WR nodes). The cache queue is organized in the same way as in Examples 2 and 3: multiple WR nodes are linked together into a linked list through next pointers, and the head pointer head_wr, tail pointer tail_wr, and count wr_num are recorded.

[0237] Simultaneously, a QP linked list srq_qp_list is maintained to record all queue pairs bound to this SRQ. Each node contains a pointer to the corresponding QP private structure (struct xsc_ib_qp).

[0238] The QP linked list is initially empty. When a queue pair is created and bound to the SRQ, the node is added to the tail of the linked list via list_add_tail (see step S400 in Example 2).

[0239] A cache queue centrally manages write-writable (WR) data, while a QP linked list records all consumers, providing the foundational data structure for subsequent dynamic allocation. The linked list structure supports efficient traversal, sorting, and node addition and deletion.

[0240] R200, in response to the need to retrieve receive job requests from the buffer queue and assign them to queue pairs, traverses the QP linked list to obtain the current number of remaining available descriptors for the hardware receive queue of each queue pair.

[0241] Furthermore, step R200 includes the following steps: R210, in response to the queue pair state of the bound software SRQ object switching from the RESET state to the INIT state, triggers the operation of retrieving the receive job request from the cache queue.

[0242] When a queue pair bound to an SRQ switches from the RESET state to the INIT state, a write-receive (WR) operation is triggered, retrieving the write-receiver from the buffer queue. This is because the QP can only receive WRs in the INIT state or higher; issuing them in the RESET state would result in a hardware error. This trigger is detected and executed within the QP state modification function (such as modify_qp).

[0243] R220, traverse the single QP linked list, and for each queue pair node in the linked list, read the current number of remaining available descriptors rq_avail in the hardware receive queue from the corresponding private data structure. rq_avail is updated in real time by the driver decrementing by 1 each time a receive work request is issued and incrementing by 1 each time a receive completion event is processed.

[0244] Traverse the SRQ's QP linked list srq_qp_list. For each queue pair node in the linked list, read the current number of available hardware receive descriptors rq_avail from its corresponding QP private structure (struct xsc_ib_qp).

[0245] How rq_avail is maintained: The initial value is equal to the hardware RQ depth rq_depth of the QP (see step S430 in Example 2).

[0246] Each time a receive WR is successfully sent to the hardware, rq_avail is decremented by 1 (indicating that a descriptor is occupied).

[0247] Each time a receive complete event (CQE) is processed, rq_avail is incremented by 1 (indicating the release of a descriptor).

[0248] This value is atomically updated by the driver in the corresponding operation to ensure accuracy.

[0249] R230 temporarily stores the number of currently available descriptors for each queue pair node in a temporary field of the corresponding queue pair node for subsequent sorting.

[0250] The rq_avail value of each queue node is temporarily stored in a temporary field of that node (or read directly in the comparison function) for subsequent sorting.

[0251] By maintaining `rq_avail` in real time, the driver can accurately grasp the resource availability level of each QP. Allocation is triggered when a QP enters the ready state, ensuring the legitimacy of the WR (Write-Off) timing. Traversing the linked list to retrieve data provides the initial basis for subsequent sorting.

[0252] R300 sorts the queue nodes in the QP linked list in ascending order of the number of remaining available descriptors.

[0253] Furthermore, step R300 includes the following steps: R310 calls the kernel-provided list_sort function to sort the QP linked list. The list_sort function uses the merge sort algorithm.

[0254] The `list_sort` function provided by the Linux kernel is called to sort `srq_qp_list`. This function is implemented as a merge sort, with a time complexity of O(nlogn), is suitable for linked list structures, and is stable and reliable.

[0255] In R320, a custom comparison function `cmp_flush_wge_cnt` is passed into the `list_sort` function. The comparison function `cmp_flush_wge_cnt` reads the number of remaining available descriptors for each of the two queue pairs to be compared. If the number of remaining available descriptors for the first node is less than that for the second node, it returns a negative value indicating that the first node should be ranked first.

[0256] The `list_sort` function takes a custom comparison function `cmp_flush_wge_cnt` as input. This function receives pointers to two queue pairs and extracts their respective `rq_avail` values ​​(which can be obtained from the `QP` pointers stored in the nodes). Comparison rules: If node A's rq_avail is less than node B's rq_avail, return a negative value, indicating that A should be listed before B.

[0257] If they are equal, return 0 to maintain the original order (merge sort is stable).

[0258] If it is greater than, return a positive value.

[0259] R330, after sorting, the head node of the QP linked list is the queue pair with the smallest number of remaining available descriptors, that is, the target queue pair that most needs to be supplemented to receive work requests.

[0260] After sorting, the head node of srq_qp_list represents the queue pair with the smallest number of remaining available descriptors, which is the target queue pair most in need of receiving write descriptors. Subsequent allocations will target this pair.

[0261] For example: Suppose there are three QPs in the linked list, with rq_avail values ​​of 5, 2, and 8 respectively. After sorting, the order is: the QP with rq_avail=2 is first, the QP with rq_avail=5 is second, and the QP with rq_avail=8 is third.

[0262] By sorting, each allocation prioritizes the most scarce QPs, effectively preventing some QPs from starving due to prolonged lack of replenishment and improving overall receiving performance. Utilizing standard kernel sorting functions, the implementation is simple, efficient, and highly scalable.

[0263] R400 selects a target queue pair from the head of the sorted QP linked list, and retrieves the corresponding number of receive work request nodes from the head of the cache queue according to the number of descriptors that need to be supplemented in the target queue pair.

[0264] Furthermore, step R400 includes the following steps: R410: Obtain the preset depth rq_depth of the target queue to the hardware receive queue. Subtract the number of currently available descriptors rq_avail from rq_depth to obtain the number of receive descriptors that need to be supplemented, need_cnt.

[0265] To obtain the target QP's hardware receive queue preset depth rq_depth and the current remaining available descriptors rq_avail, the required padding quantity is need_cnt = rq_depth - rq_avail. For example, if rq_depth = 16 and the current rq_avail = 3, then need_cnt = 13.

[0266] R420: Get the number of nodes currently receiving work requests in the cache queue, cache_cnt. Take the smaller value between need_cnt and cache_cnt as the number of nodes n to be retrieved this time.

[0267] Get the current number of write operations (WR) in the cache queue, cache_cnt (i.e., wr_num). Take the smaller value between need_cnt and cache_cnt as the number of nodes to retrieve this time, n=min(need_cnt, cache_cnt). If need_cnt==0 or cache_cnt==0, then do not perform a retrieval this time.

[0268] R430 starts from the first node pointed to by the head pointer head_wr of the cache queue, and takes out n nodes in sequence along the next pointer to form a linked list to be sent; updates head_wr to the first node of the remaining linked list; if the remaining linked list is empty, sets tail_wr to null and subtracts n from the cache count wr_num.

[0269] This operation is exactly the same as step Q300 in Example 3: traverse from head_wr and locate the nth node. Cut the linked list, separating the first n nodes. Update head_wr to point to the head of the remaining linked list; if all nodes have been retrieved, set tail_wr to NULL. Update wr_num by subtracting n. For detailed pointer operations, please refer to steps Q310-Q340 in Example 3.

[0270] The number of items retrieved is calculated on demand to ensure that the allocation matches the actual needs of QP, avoiding waste. Linked list slicing operations are zero-copy, efficient and accurate. After updating the cache queue state, the latest data is provided for subsequent allocations.

[0271] R500 sends the retrieved receive work request node to the hardware receive queue of the target queue pair and updates the head pointer and cache count of the cache queue.

[0272] Furthermore, step R500 includes the following steps: R510 calls the hardware posting interface xsc_post_recv to sequentially write the n retrieved receiving work request nodes into the hardware receiving queue circular buffer of the target queue pair. Each time a node is written, the tail pointer of the hardware receiving queue is updated, and a doorbell is triggered to notify the hardware that a new receiving request is available.

[0273] The hardware delivery function provided by the driver (such as xsc_post_recv) is called to sequentially write the retrieved n WR nodes into the target QP's hardware receive queue circular buffer. After each node is written, the tail pointer of the hardware RQ is updated, and finally, a doorbell is triggered to notify the hardware that a new receive request is available. This process is the same as step S612 in Embodiment 2.

[0274] R520 manages the n nodes distributed through the target queue using the private head pointer srq_head_wr and tail pointer srq_tail_wr, forming a private incomplete receiving work request list for the target queue, and incrementing the private list length count.

[0275] The n distributed nodes are managed through the target QP's private head pointer srq_head_wr and tail pointer srq_tail_wr, forming the incomplete WR linked list of that QP. The specific operation is the same as step Q400 in Example 3: if the private linked list is empty, it is created directly. If it is not empty, it is appended to the tail and the tail pointer is updated. The private linked list length count is incremented.

[0276] R530 updates the current number of available descriptors in the target queue pair by subtracting the number of nodes n sent this time from the current number of available descriptors in the target queue pair to reflect the occupancy of newly added receive descriptors in the hardware receive queue.

[0277] Subtracting n from the target QP's rq_avail, i.e., rq_avail = rq_avail - n, reflects the number of newly occupied descriptors in the hardware RQ. This value will be used for subsequent allocation decisions.

[0278] The final distribution of Write-Ups (WRs) from software to hardware is completed, and incomplete WRs are tracked through a private linked list, laying the foundation for completion processing and abnormal garbage collection. Real-time updates to `rq_avail` ensure the accuracy of subsequent sorting and allocation.

[0279] Furthermore, the QP linked list includes an active QP linked list and an idle QP linked list; the following steps are also included before step R200: R110 maintains an active QP linked list and an idle QP linked list in the software SRQ object, and initially places newly bound queue pairs to the software SRQ object into the idle QP linked list.

[0280] The software SRQ object maintains two linked list heads: active_qp_list (active QP list) and idle_qp_list (idle QP list). Newly bound queue pairs are initially placed into the idle list.

[0281] R120, obtain the reception completion history data for each queue pair; the history data includes at least one of the following: queue pair creation time, most recent reception completion timestamp, number of completions generated within the time interval between the two most recent reception completions, total number of completions, and maximum number of completions in a single instance.

[0282] Each time a Complete Receive Event (CQE) is processed, the historical data field of the corresponding QP is updated: last_recv_time: Records the current timestamp.

[0283] prev_recv_time: Moves the old last_recv_time to this field for calculating the interval.

[0284] num_last_wcs: The number of completions between the two most recent reception completions (obtainable from the CQE count).

[0285] total_wcs: Total number of completed tasks.

[0286] max_wcs_per_poll: The maximum number of CQEs obtained in a single polling session.

[0287] create_time: Recorded when QP is created.

[0288] R130: Based on the comparison result of the received historical data and the preset threshold, dynamically update the queue pair node's affiliation between the active QP list and the idle QP list.

[0289] Furthermore, the dynamic update of the queue's node affiliation in step R130 includes the following steps: R131: For queue pairs in the idle QP list, check the corresponding received history data. If any of the following conditions are met, move the corresponding queue pair from the idle QP list to the active QP list: The long-term frequency obtained by dividing the total number of completed tasks by the time interval from creation to the most recent completion exceeds a preset first threshold. The number of completions generated within the time interval between the two most recent reception completions, divided by the time interval between the two most recent reception completions, results in a short-term frequency that exceeds a preset second threshold. The time difference between the current timestamp and the most recent received completion timestamp is less than the preset third threshold. The maximum number of items completed in a single transaction exceeds the preset fourth threshold. For a QP node in the free list, if any of the following conditions are met, then it is moved to the active list: The frequency has exceeded the threshold for a long period: total_wcs / (last_recv_time-create_time) > THRESHOLD1. This indicates that the average receive rate of this QP since its creation is relatively high.

[0290] A short-term frequency exceeding the threshold: num_last_wcs / (last_recv_time-prev_recv_time) > THRESHOLD2. This indicates a high rate between the two most recent receptions, possibly due to processing burst traffic.

[0291] The most recent reception time is very close: current_time - last_recv_time < THRESHOLD3. This indicates that data has just been received and is likely to continue to be received soon.

[0292] Strong single-burst capability: max_wcs_per_poll > THRESHOLD4. This indicates that the QP has the ability to handle a large number of receptions at once and should be allocated resources.

[0293] R132: For queue pairs in the active QP list, check the corresponding received history data. If all of the following conditions are met simultaneously, move the corresponding queue pair from the active QP list to the idle QP list: The long-term frequency obtained by dividing the total number of completed tasks by the time interval from creation to the current time is lower than the preset fifth threshold. The number of completions generated within the time interval between the two most recent reception completions, divided by the time interval between the two most recent reception completions, yields a short-term frequency that is lower than the preset sixth threshold. The time difference between the current timestamp and the most recent received completion timestamp is greater than the preset seventh threshold.

[0294] For a QP node in the active list, if all of the following conditions are met, it is moved to the free list: Long-term frequency below the threshold: total_wcs / (current_time-create_time) < THRESHOLD5.

[0295] Short-term frequency below the threshold: num_last_wcs / (last_recv_time - prev_recv_time) < THRESHOLD6.

[0296] No reception for a long time: current_time - last_recv_time > THRESHOLD7.

[0297] All thresholds (THRESHOLD1~7) can be set to default values ​​(such as empirical values), and can also be dynamically configured by user space via sysfs or ioctl interfaces to adapt to different application scenarios.

[0298] The "Idle → Active" condition uses an "OR" condition to ensure that suddenly active QPs can obtain resources in a timely manner, avoiding performance fluctuations; the "Active → Idle" condition uses an "AND" condition to ensure that QPs are only removed after they are truly idle, preventing frequent oscillations. Multi-dimensional indicators are used to comprehensively judge and accurately reflect the actual activity status of QPs. Configurable thresholds enhance the flexibility and adaptability of the method.

[0299] R140, the step R200 of traversing the QP linked list includes: firstly traversing the active QP linked list; if the active QP linked list is not empty, then selecting queue pairs from the active QP linked list for subsequent processing; if the active QP linked list is empty, then selecting queue pairs from the idle QP linked list for subsequent processing.

[0300] In step R200, when it is necessary to traverse the QP linked list, the active linked list is traversed first instead. If the active linked list is not empty, queue pairs are selected from the active linked list for subsequent processing (sorting or direct allocation); if the active linked list is empty, then the free linked list is selected. This can significantly reduce the number of nodes to be sorted.

[0301] By categorizing QPs according to their activity status and prioritizing active QPs during allocation, the scheduling overhead is significantly reduced by avoiding a full sorting of all QPs each time, making it particularly suitable for scenarios with a large number of QPs. The collection of historical data provides a quantitative basis for status determination.

[0302] This embodiment achieves on-demand allocation through a single QP linked list sorting, prioritizing the most scarce QPs and effectively avoiding starvation. Furthermore, a doubly linked list dynamic classification is introduced, dividing QPs into active and idle categories based on historical activity data. Allocation prioritizes the active linked list, significantly reducing sorting overhead. These steps work closely together to form an efficient and scalable SRQ resource allocation scheme. Based on the above description and the relevant implementations of the first two embodiments, those skilled in the art can write corresponding kernel driver code to implement high-performance receive resource management on RDMA network cards whose hardware does not support SRQ.

[0303] Furthermore, although the steps of the method in this disclosure are described in a specific order in the accompanying drawings, this does not require or imply that the steps must be performed in that specific order, or that all the steps shown must be performed to achieve the desired result. Additional or alternative steps may be omitted, multiple steps may be combined into one step, and / or a step may be broken down into multiple steps.

[0304] Embodiments of the present invention also provide a non-transitory computer-readable storage medium that can be disposed in an electronic device to store at least one instruction or at least one program related to implementing a method in the method embodiments, wherein the at least one instruction or the at least one program is loaded and executed by the processor to implement the method provided in the above embodiments.

[0305] The program product may employ any combination of one or more readable media. A readable medium may be a readable signal medium or a readable storage medium. A readable storage medium may be, for example, but not limited to, an electrical, magnetic, optical, electromagnetic, infrared, or semiconductor system, apparatus, or device, or any combination thereof. More specific examples of readable storage media (a non-exhaustive list) include: an electrical connection having one or more wires, a portable disk, a hard disk, random access memory (RAM), read-only memory (ROM), erasable programmable read-only memory (EPROM or flash memory), optical fiber, portable compact disk read-only memory (CD-ROM), optical storage devices, magnetic storage devices, or any suitable combination thereof.

[0306] Computer-readable signal media may include data signals propagated in baseband or as part of a carrier wave, carrying readable program code. Such propagated data signals may take various forms, including but not limited to electromagnetic signals, optical signals, or any suitable combination thereof. A readable signal medium may also be any readable medium other than a readable storage medium, capable of sending, propagating, or transmitting programs for use by or in conjunction with an instruction execution system, apparatus, or device.

[0307] The program code contained on the readable medium may be transmitted using any suitable medium, including but not limited to wireless, wired, optical fiber, RF, etc., or any suitable combination thereof.

[0308] Program code for performing the operations of this application can be written in any combination of one or more programming languages, including object-oriented programming languages ​​such as Java and C++, and conventional procedural programming languages ​​such as C or similar languages. The program code can execute entirely on the user's computing device, partially on the user's device, as a standalone software package, partially on the user's computing device and partially on a remote computing device, or entirely on a remote computing device or server. In cases involving remote computing devices, the remote computing device can be connected to the user's computing device via any type of network, including a local area network (LAN) or a wide area network (WAN), or it can be connected to an external computing device (e.g., via the Internet using an Internet service provider).

[0309] Embodiments of the present invention also provide an electronic device, including a processor and the aforementioned non-transitory computer-readable storage medium.

[0310] The electronic device is merely an example and should not impose any limitations on the functionality and scope of use of the embodiments in this application.

[0311] Electronic devices are manifested in the form of general-purpose computing devices. Components of an electronic device may include, but are not limited to: at least one processor, at least one memory, and a bus connecting different system components (including memory and processor).

[0312] The memory stores program code that can be executed by the processor, causing the processor to perform the steps in the various embodiments described in this specification.

[0313] The memory may include readable media in the form of volatile memory, such as random access memory (RAM) and / or cache memory, and may further include read-only memory (ROM).

[0314] The memory may also include programs / utilities having a set (at least one) of program modules, including but not limited to: an operating system, one or more application programs, other program modules, and program data, each or some combination of these examples may include an implementation of a network environment.

[0315] A bus can represent one or more of several types of bus structures, including a memory bus or memory controller, a peripheral bus, a graphics acceleration port, a processor, or a local bus that uses any of the various bus structures.

[0316] Electronic devices can also communicate with one or more external devices (e.g., keyboards, pointing devices, Bluetooth devices, etc.), one or more devices that enable user interaction with the electronic device, and / or any device that enables the electronic device to communicate with one or more other computing devices (e.g., routers, modems, etc.). This communication can be achieved through input / output (I / O) interfaces. Furthermore, electronic devices can communicate with one or more networks (e.g., local area networks (LANs), wide area networks (WANs), and / or public networks, such as the Internet) via network adapters. The network adapter communicates with other modules of the electronic device via a bus. It should be understood that other hardware and / or software modules can be used in conjunction with the electronic device, including but not limited to: microcode, device drivers, redundant processors, external disk drive arrays, RAID systems, tape drives, and data backup storage systems.

[0317] From the above description of the embodiments, those skilled in the art will readily understand that the exemplary embodiments described herein can be implemented by software or by combining software with necessary hardware. Therefore, the technical solutions according to the embodiments of this disclosure can be embodied in the form of a software product, which can be stored in a non-volatile storage medium (such as a CD-ROM, USB flash drive, external hard drive, etc.) or on a network, including several instructions to cause a computing device (such as a personal computer, server, terminal device, or network device, etc.) to execute the methods according to the embodiments of this disclosure.

[0318] Embodiments of the present invention also provide a computer program product including program code, which, when the program product is run on an electronic device, causes the electronic device to perform the steps of the methods described above in various exemplary embodiments of the present invention.

[0319] While specific embodiments of the invention have been described in detail by way of examples, those skilled in the art should understand that the examples are for illustrative purposes only and are not intended to limit the scope of the invention. Those skilled in the art should also understand that various modifications can be made to the embodiments without departing from the scope and spirit of the invention.

Claims

1. An SRQ resource allocation method based on activity state classification, characterized in that, The method includes the following steps: H100 maintains a cache queue of software SRQ objects in the kernel driver, as well as an active QP list and an idle QP list associated with the software SRQ objects; the cache queue is used to cache nodes that receive work requests, the active QP list is used to record queue pairs that are currently receiving frequently, and the idle QP list is used to record queue pairs that are currently receiving less frequently. H200: Obtain the reception completion history data for each queue pair, and dynamically update the association of queue pair nodes between the active QP list and the idle QP list based on the comparison result of the reception completion history data and the preset threshold. H300, in response to the need to retrieve a receive job request from the cache queue and assign it to a queue pair, prioritizes selecting a target queue pair from the active QP list; H400: When the active QP list is not empty, a target queue pair is selected from the active QP list for allocation; when the active QP list is empty, a target queue pair is selected from the idle QP list for allocation. H500 retrieves the corresponding number of receive work request nodes from the head of the cache queue based on the number of descriptors that need to be supplemented for the selected target queue pair, and sends them to the hardware receive queue of the target queue pair.

2. The SRQ resource allocation method based on activity state classification according to claim 1, characterized in that, Step H100 includes the following steps: H110 allocates an active QP list head (active_list) and an idle QP list head (idle_list) to each software SRQ object, and initializes active_list and idle_list as empty lists; H120, in response to the specified binding to the software SRQ object when the queue pair is created, allocates a queue pair node for the corresponding queue pair; the queue pair node at least contains a pointer to the corresponding queue pair and an activity status identifier, and initially adds the corresponding queue pair node to the idle QP linked list; H130, maintain a historical data field for receiving completion in the private data structure of the queue pair node; the historical data field for receiving completion includes the queue pair creation timestamp, the most recent receiving completion timestamp, the two most recent receiving completion timestamps, the number of completions generated within the most recent time interval, the total number of completions, and the maximum number of completions in a single instance.

3. The SRQ resource allocation method based on activity state classification according to claim 1, characterized in that, Step H200 includes the following steps: H210, periodically or after each processing of a receive completion event, updates the receive completion history data for each queue node; H220: For queue pairs in the idle QP list, check the corresponding received completion history data. If any of the following conditions are met, move the corresponding queue pair from the idle QP list to the active QP list: The long-term frequency obtained by dividing the total number of completed tasks by the time interval from creation to the most recent completion exceeds a preset first threshold. The short-term frequency obtained by dividing the number of completions generated within the time interval between the two most recent reception completions by this time interval exceeds the preset second threshold. The time difference between the current timestamp and the most recent received completion timestamp is less than the preset third threshold. The maximum number of items completed in a single transaction exceeds the preset fourth threshold. H230, for queue pairs in the active QP list, check the corresponding receive completion history data: if all of the following conditions are met simultaneously, move the queue pair from the active QP list to the idle QP list: The long-term frequency obtained by dividing the total number of completed tasks by the time interval from creation to the current time is lower than the preset fifth threshold. The short-term frequency obtained by dividing the number of completions generated within the time interval between the two most recent reception completions by this time interval is lower than the preset sixth threshold. The time difference between the current timestamp and the most recent received completion timestamp is greater than the preset seventh threshold.

4. The SRQ resource allocation method based on activity state classification according to claim 1, characterized in that, The triggering conditions in step H300 for retrieving a receive job request from the cache queue and assigning it to the queue pair include: H310, detected that the queue pair of bound software SRQ objects has switched from the RESET state to the INIT state; H320: The number of nodes receiving work requests in the cache queue has exceeded the preset high watermark, and there are queue pairs that need to be supplemented with receive descriptors. H330, a timer timeout was detected, triggering a periodic allocation check.

5. The SRQ resource allocation method based on activity state classification according to claim 1, characterized in that, Step H400 includes the following steps: H410, check if the active QP list is empty: if the active QP list is not empty, take the first queue pair node from the head of the active QP list as the target queue pair. H420: If the active QP list is empty, check if the free QP list is not empty. If the free QP list is not empty, take the first queue pair node from the head of the free QP list as the target queue pair. H430: If both the active QP list and the free QP list are empty, then no allocation operation will be performed this time, and the process will return directly.

6. The SRQ resource allocation method based on activity state classification according to claim 1, characterized in that, Step H500 includes the following steps: H510, obtain the preset depth rq_depth of the target queue relative to the hardware receive queue and the number of currently remaining available descriptors rq_avail, and calculate the number of receive descriptors to be supplemented need_cnt=rq_depth-rq_avail; H520: Get the number of nodes receiving work requests currently cached in the cache queue, cache_cnt, and take the smaller value between need_cnt and cache_cnt as the number of nodes n retrieved this time. H530 starts from the first node pointed to by the head pointer head_wr of the cache queue, and takes out n nodes in sequence along the next pointer to form a linked list to be sent; updates head_wr to the first node of the remaining linked list; if the remaining linked list is empty, sets tail_wr to empty and subtracts n from the cache count wr_num. H540 calls the hardware delivery interface to write n nodes from the delivery list into the hardware receive queue of the target queue pair, and updates the current remaining available descriptor count rq_avail of the target queue pair by n.

7. The SRQ resource allocation method based on activity state classification according to claim 1, characterized in that, Following step H500, the method further includes the following steps: H610, in response to the failure of the target queue to destroy or send the receiving work request in the corresponding private linked list, obtain the entire unfinished node linked list pointed to by srq_head_wr to srq_tail_wr in the private linked list of the target queue; H620, return the entire incomplete node list to the cache queue, and append the returned list to the tail or head of the cache queue according to the current state of the cache queue; H630 updates the head pointer head_wr, tail pointer tail_wr, and cache count wr_num of the cache queue, and sets the head and tail pointers of the private linked list of the target queue pair to null.

8. A non-transitory computer-readable storage medium, wherein the storage medium stores at least one instruction or at least one program segment, characterized in that, The at least one instruction or the at least one program segment is loaded and executed by the processor to implement the SRQ resource allocation method based on activity state classification as described in any one of claims 1-7.

9. An electronic device, characterized in that, Includes a processor and the non-transitory computer-readable storage medium as described in claim 8.