LAPI_Util 子例程

用途

充当 此类数据收集/散点操作 (如注册和保留) , (用于更新 UDP 端口信息) 以及获取指向与共享 LAPI 锁定相关联的锁定和发信号功能的指针的包装程序函数。

可用性库 (liblapi_r.a)

C 语法

#include <lapi.h>
 
int LAPI_Util(hndl, util_cmd)
lapi_handle_t hndl;
lapi_util_t *util_cmd;

FORTRAN 语法

include 'lapif.h'
 
LAPI_UTIL(hndl, util_cmd, ierror)
INTEGER hndl
TYPE (LAPI_UTIL_T) :: util_cmd
INTEGER ierror

描述

Type of call: 数据收集/散点程序 (DGSP) , UDP 端口信息和锁定共享实用程序

此子例程用于多个不同的操作,这些操作由命令结构开头的命令类型值指示。 lapi_util_t 结构定义为:
typedef union {
    lapi_util_type_t    Util_type;  
    lapi_reg_dgsp_t     RegDgsp;    
    lapi_dref_dgsp_t    DrefDgsp;   
    lapi_resv_dgsp_t    ResvDgsp;   
    lapi_reg_ddm_t      DdmFunc;    
    lapi_add_udp_port_t Udp;        
    lapi_pack_dgsp_t    PackDgsp;   
    lapi_unpack_dgsp_t  UnpackDgsp;
    lapi_thread_func_t  ThreadFunc;
} lapi_util_t;
枚举类型 lapi_util_type_t 具有以下值:
表 1。 lapi_util_type_t 类型
Util_type 的值 由 LAPI_Util 解释的联合成员
LAPI_REGISTER_DGSP lapi_reg_dgsp_t
LAPI_UNRESERVE_DGSP lapi_dref_dgsp_t
LAPI_RESERVE_DGSP lapi_resv_dgsp_t
LAPI_REG_DDM_FUNC lapi_reg_ddm_t
LAPI_ADD_UDP_DEST_PORT lapi_add_udp_port_t
LAPI_DGSP_PACK lapi_pack_dgsp_t
LAPI_DGSP_UNPACK lapi_unpack_dgsp_t
LAPI_GET_THREAD_FUNC lapi_thread_func_t
未针对命令类型 LAPI_REGISTER_DGSPLAPI_RESERVE_DGSPLAPI_UNRESERVE_DGSP检查 hndl

LAPI_REGISTER_DGSP

您可以使用此操作来注册已创建的 LAPI DGSP。 要注册 LAPI DGSP ,必须传入 lapi_dgsp_descr_t idgsp 。 LAPI 返回用于将来所有 LAPI 调用的句柄 (lapi_dg_handle_t dgsp_handle)。 注册操作返回的 dgsp_handle 标识为 lapi_dg_handle_t 类型,这是执行 DGSP 的 LAPI_XferLAPI_Util 调用的相应类型。 对于 LAPI 用户需要对高速缓存的 DGSP 中包含的信息进行只读访问的情况,此返回的 dgsp_handle 也定义为可级联到指向 lapi_dgsp_descr_t 的指针。 注册操作将 DGSP 交付到 LAPI ,以用于将来的消息发送,接收,打包和解包操作。 LAPI 创建自己的 DGSP 副本,并通过引用计数对其进行保护。 依赖于 LAPI 中高速缓存的 DGSP 的所有内部 LAPI 操作通过在开始依赖 DGSP 时增加引用计数并在该依赖关系结束时减少计数来确保 DGSP 的保留。 DGSP 一旦注册,就可以从任何 LAPI 实例中使用。 LAPI_Term 不会废弃任何 DGSP。

您可以注册 DGSP ,使用 DGSP 启动一个或多个 LAPI 操作,然后将其取消保留,而不必担心依赖 DGSP 的 LAPI 操作将何时使用它完成。 请参阅 LAPI_RESERVE_DGSPLAPI_UNRESERVE_DGSP 以获取更多信息。

通常,使用 dgsp 参数创建并传递到 LAPI_REGISTER_DGSP 调用的 DGSP 将在 LAPI 生成并高速缓存其自己的副本后废弃。 由于 DGSP 创建很复杂,可能会发生用户错误,但在数据传输时进行广泛的错误检查会损害性能。 开发用于创建 DGSP 的代码时,可以通过设置 LAPI_VERIFY_DGSP 环境变量在注册点调用额外的验证。 LAPI_Util 将返回任何检测到的错误。 存在且在注册时未检测到的任何错误都将导致数据传输期间出现问题。 在数据传输期间检测到的任何错误都将由异步错误处理程序报告。 分段故障是发生故障的 DGSP 的一个常见症状。 如果正在使用多个 DGSP ,那么异步错误处理程序将无法识别导致该错误的 DGSP。 有关异步错误处理的更多信息,请参阅 LAPI_Init

LAPI_REGISTER_DGSP 使用 lapi_reg_dgsp_t 命令结构。
表 2。 lapi_reg_dgsp_t 字段
lapi_reg_dgsp_t 字段 lapi_reg_dgsp_t 字段类型 lapi_reg_dgsp_t 用法
Util_type lapi_util_type_t LAPI_REGISTER_DGSP
idgsp lapi_dgsp_descr_t IN-指向 DGSP 程序的指针
dgsp_handle lapi_dg_handle_t 已注册 DGSP 程序的 OUT-handle
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_RESERVE_DGSP

您可以使用此操作来保留 DGSP。 提供此操作是因为 LAPI 客户机可能会高速缓存 LAPI DGSP 句柄以供将来使用。 客户机需要确保在使用高速缓存的句柄之前不会废弃 DGSP。 DGSP 句柄 (定义为指向已在 LAPI 中高速缓存的 DGSP 描述的指针) 将传递到此操作。 DGSP 句柄也定义为结构指针,以便客户机程序可以直接访问 DGSP 中的信息。 除非客户机可以确定 DGSP 在被访问时不会被另一个线程 "取消保留" ,否则客户机应该用自己的保留/取消保留操作将访问窗口括起来。 客户机不会修改高速缓存的 DGSP ,但 LAPI 无法强制实施此操作。 保留操作将增大用户引用计数,从而保护 DGSP ,直到发生取消保留操作为止。 这是必需的,因为放置预留的线程将期望能够使用或检查高速缓存的 DGSP ,直到它发出取消预留调用 (这会减少用户引用计数) ,即使与原始注册操作匹配的取消预留操作发生在此窗口中的其他某个线程上。

LAPI_RESERVE_DGSP 使用 lapi_resv_dgsp_t 命令结构。
表 3。 lapi_resv_dgsp_t 字段
lapi_resv_dgsp_t 字段 lapi_resv_dgsp_t 字段类型 lapi_resv_dgsp_t 用法
Util_type lapi_util_type_t LAPI_RESERVE_DGSP
dgsp_handle lapi_dg_handle_t 已注册 DGSP 程序的 OUT-handle
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_UNRESERVE_DGSP

您可以使用此操作来注销或取消保留 DGSP。 此操作将减少用户引用计数。 如果外部和内部引用计数为零,那么此操作允许 LAPI 释放 DGSP。 所有减少引用计数的操作都会导致 LAPI 检查这些计数是否都已变为 0 ,如果已变为,请处置 DGSP。 多个内部 LAPI 活动增加并减少第二个引用计数。 高速缓存的 DGSP 仅在所有依赖于它的活动 (内部和外部) 并使用引用计数来保留它们的引用时才可使用。 DGSP 句柄将作为值参数传递到 LAPI ,并且 LAPI 不会使调用者的句柄失效。 您有责任不再使用此句柄,因为在执行取消保留操作时,您已指示不再计入剩余有效的句柄。

LAPI_UNRESERVE_DGSP 使用 lapi_dref_dgsp_t 命令结构。
表 4。 lapi_dref_dgsp_t 字段
lapi_dref_dgsp_t 字段 lapi_dref_dgsp_t 字段类型 lapi_dref_dgsp_t 用法
Util_type lapi_util_type_t LAPI_UNRESERVE_DGSP
dgsp_handle lapi_dg_handle_t 已注册 DGSP 程序的 OUT-handle
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_REG_DDM_FUNC

可以使用此操作来注册数据分发管理器 (DDM) 功能。 它与 DGSM CONTROL 指令一起工作。 主要用于 MPI_Accumulate,但 LAPI 客户机可以提供任何 DDM 功能。 它还用于建立回调函数,用于处理正在分散到目标端的用户缓冲区中的数据。

本机 LAPI 用户可以安装回调,而不会影响为 MPI_Accumulate注册的一个 MPI。 回调函数的函数原型为:
typedef long ddm_func_t (        /* return number of bytes processed */
        void      *in,           /* pointer to inbound data          */
        void      *inout,        /* pointer to destination space     */
        long      bytes,         /* number of bytes inbound          */
        int       operand,       /* CONTROL operand value            */
        int       operation      /* CONTROL operation value          */
);

DDM 功能在消息数据到达和目标缓冲区之间起作用。 最常见的用法是将入站数据与目标缓冲区中已有的数据进行组合。 例如,如果目标缓冲区是整数数组,并且入局消息由整数组成,那么可以写入 DDM 函数以将每个入局整数添加到缓冲区中已存在的值。 DDM 函数的 操作数操作 字段允许一个 DDM 函数通过为这些字段提供适当的值来支持具有 CONTROL 指令的一系列操作。

有关 DGSP 编程的更多信息,请参阅 RSCT for AIX 5L: LAPI Programming Guide

LAPI_REG_DDM_FUNC 使用 lapi_reg_ddm_t 命令结构。 每个调用都将替换先前的函数指针 (如果有)。
表 5。 lapi_reg_ddm_t 字段
lapi_reg_ddm_t 字段 lapi_reg_ddm_t 字段类型 lapi_reg_ddm_t 用法
Util_type lapi_util_type_t LAPI_REG_DDM_FUNC
ddm_func ddm_func_t * IN-DDM 函数指针
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_DGSP_PACK

您可以使用此操作从 DGSP 控制下的用户缓冲区将数据收集到包缓冲区。 单个缓冲区可由一系列调用打包。 调用者提供一个 位置 值,该值初始化为缓冲区内的起始偏移量。 每个打包操作都会调整 位置,因此下一个打包操作可以从先前打包操作结束的位置开始。 通常,一系列包操作以初始化为 0位置 开头,但任何偏移量都有效。 没有从一个包操作到下一个包操作的状态。 每个打包操作在其传递的 DGSP 开始时开始。

LAPI_DGSP_PACK 使用 lapi_pack_dgsp_t 命令结构。
表 6。 lapi_pack_dgsp_t 字段
lapi_pack_dgsp_t 字段 lapi_pack_dgsp_t 字段类型 lapi_pack_dgsp_t 用法
Util_type lapi_util_type_t LAPI_DGSP_PACK
dgsp_handle lapi_dg_handle_t 已注册 DGSP 程序的 OUT-handle
in_buf void * 要打包的 IN 源缓冲区
bytes ulong IN-要打包的字节数
out_buf void * OUT-包的输出缓冲区
输出大小 ulong IN-输出缓冲区大小 (以字节计)
位置 ulong IN/OUT-当前缓冲区偏移量
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_DGSP_UNPACK

您可以使用此操作将数据从压缩缓冲区分散到 DGSP 控制下的用户缓冲区。 可以通过一系列调用来解包单个缓冲区。 调用者提供一个 position 值,该值初始化为打包缓冲区中的起始偏移量。 每个解包操作都会调整 位置,因此下一个解包操作可以从先前解包操作结束的位置开始。 通常,一系列解包操作以初始化为 0位置 开头,但任何偏移量都有效。 没有从一个解包操作到下一个解包操作的状态。 每个解包操作在其传递的 DGSP 开始时开始。

LAPI_DGSP_UNPACK 使用 lapi_unpack_dgsp_t 命令结构。
表 7。 lapi_unpack_dgsp_t 字段
lapi_unpack_dgsp_t 字段 lapi_unpack_dgsp_t 字段类型 lapi_unpack_dgsp_t 用法
Util_type lapi_util_type_t LAPI_DGSP_UNPACK
dgsp_handle lapi_dg_handle_t 已注册 DGSP 程序的 OUT-handle
buf void * 用于解包的 IN 源缓冲区
in_size ulong IN-源缓冲区大小 (以字节为单位)
out_buf void * OUT-用于解包的输出缓冲区
bytes ulong IN-要解包的字节数
输出大小 ulong IN-输出缓冲区大小 (以字节计)
位置 ulong IN/OUT-当前缓冲区偏移量
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_ADD_UDP_DEST_PORT

您可以使用此操作来更新有关目标任务的 UDP 端口信息。 当您编写了自己的 UDP 处理程序 (udp_hndlr) 并且需要支持失败任务的恢复时,可以使用此操作。 不能在 POE 运行时环境下使用此操作。

LAPI_ADD_UDP_DEST_PORT 使用 lapi_add_udp_port_t 命令结构。
表 8。 lapi_add_udp_port_t 字段
lapi_add_udp_port_t 字段 lapi_add_udp_port_t 字段类型 lapi_add_udp_port_t 用法
Util_type lapi_util_type_t LAPI_ADD_UDP_DEST_PORT
tgt uint IN-目标任务标识
udp_port lapi_udp_t * 目标的 IN-UDP 端口信息
实例数 uint IN-UDP 的实例数
in_usr_func lapi_usr_fcall_t 仅用于调试
状态 lapi_status_t OUT-未来支持

LAPI_GET_THREAD_FUNC

您可以使用此操作来检索各种 共享锁定和发信号 功能。 仅在初始化 LAPI 之后以及终止 LAPI 之前,这些函数的检索才有效。 在 LAPI 终止后,不应调用任何这些函数。

LAPI_GET_THREAD_FUNC 使用 lapi_thread_func_t 命令结构。
表 9。 lapi_thread_func_t 字段
lapi_thread_func_t 字段 lapi_thread_func_t 字段类型 lapi_thread_func_t 用法
Util_type lapi_util_type_t LAPI_GET_THREAD_FUNC
互斥锁定 lapi_mutex_lock_t OUT-互斥锁 函数指针
互斥解锁 lapi_mutex_unlock_t OUT-mutex 解锁 函数指针
mutex_trylock lapi_mutex_trylock_t OUT-mutex try lock 函数指针
互斥对象 lapi_mutex_getowner_t OUT-mutex 获取所有者 函数指针
cond_wait lapi_cond_wait_t OUT- condition wait 函数指针
cond_timedwait lapi_cond_timedwait_t OUT- condition 定时等待 函数指针
cond_signal lapi_cond_signal_t OUT- condition signal 函数指针
cond_init lapi_cond_init_t OUT-initialize 条件 函数指针
cond_destroy lapi_cond_destroy_t OUT-destroy 条件 函数指针

LAPI 使用 pthread 库进行线程标识管理。 因此,您可以使用 pthread_self() 来获取正在运行的线程标识,并使用 lapi_mutex_getowner_t 来获取拥有共享锁定的线程标识。 然后,可以使用 pthread_equal() 来查看两者是否相同。

互斥线程函数

LAPI_GET_THREAD_FUNC 包含以下互斥线程函数 :mutex lock , mutex unlock , mutex try lock 和 mutex get owner。

Mutex lock function pointer
int (*lapi_mutex_lock_t)(lapi_handle_t hndl);
此函数获取与指定 LAPI 句柄关联的锁定。 如果锁定已由另一个线程挂起,那么调用将阻塞。 如果调用线程已持有锁定,那么可能会发生死锁。 您负责防止和检测死锁。
Parameters
INPUT
hndl
指定 LAPI 句柄。
Return values
0
指示已成功获取锁定。
EINVAL
如果由于 hndl 值不正确而导致锁定无效,那么将返回此值。
Mutex unlock function pointer
int (*lapi_mutex_unlock_t)(lapi_handle_t hndl);
此函数将释放与指定 LAPI 句柄关联的锁定。 线程应仅解锁其自己的锁定。
Parameters
INPUT
hndl
指定 LAPI 句柄。
Return values
0
指示锁定已成功释放。
EINVAL
如果由于 hndl 值不正确而导致锁定无效,那么将返回此值。
Mutex try lock function pointer
int (*lapi_mutex_trylock_t)(lapi_handle_t hndl);
此函数尝试获取与指定 LAPI 句柄关联的锁定, 但如果锁定已挂起,那么会立即返回
Parameters
INPUT
hndl
指定 LAPI 句柄。
Return values
0
指示已成功获取锁定。
EBUSY
指示正在挂起锁定。
EINVAL
如果由于 hndl 值不正确而导致锁定无效,那么将返回此值。
Mutex get owner function pointer
int (*lapi_mutex_getowner_t)(lapi_handle_t hndl, pthread_t *tid);
此函数获取当前持有与指定 LAPI 句柄关联的锁定的线程的 pthread 标识。 LAPI_NULL_THREAD_ID 指示在调用函数时未挂起锁定。
Parameters
INPUT
hndl
指定 LAPI 句柄。
输出
tid
是一个指针,用于保存要检索的 pthread 标识。
Return values
0
指示已成功检索锁定所有者。
EINVAL
如果由于 hndl 值不正确而导致锁定无效,那么将返回此值。

条件函数

LAPI_GET_THREAD_FUNC 包含以下 condition 函数: condition wait , condition timed wait , condition signal , initialize condition 和 destroy condition。

Condition wait function pointer
int (*lapi_cond_wait_t)(lapi_handle_t hndl, lapi_cond_t *cond);
此函数等待条件变量 (cond)。 在进行调用之前,用户必须持有与 LAPI 句柄 (hndl) 关联的锁定。 在返回调用时, LAPI 保证锁定仍处于挂起状态。 必须向同一条件变量上的并发 lapi_cond_wait_t 操作提供相同的 LAPI 句柄。
Parameters
INPUT
hndl
指定 LAPI 句柄。
连接
是要等待的条件变量的指针。
Return values
0
指示已向条件变量发出信号。
EINVAL
指示由 hndlcond 指定的值无效。
Condition timed wait function pointer
int (*lapi_cond_timedwait_t)(lapi_handle_t hndl, 
                             lapi_cond_t *cond, 
                             struct timespec *timeout);
此函数等待条件变量 (cond)。 在进行调用之前,用户必须持有与 LAPI 句柄 (hndl) 关联的锁定。 在返回调用时, LAPI 保证锁定仍处于挂起状态。 必须向同一条件变量上的并发 lapi_cond_timedwait_t 操作提供相同的 LAPI 句柄。
Parameters
INPUT
hndl
指定 LAPI 句柄。
连接
是要等待的条件变量的指针。
超时
是一个指向指定超时的绝对时间结构的指针。
Return values
0
指示已向条件变量发出信号。
ETIMEDOUT
指示已经过 timeout 指定的时间。
EINVAL
指示由 hndl cond指定的值。 或 timeout 无效。
Condition signal function pointer
int (*lapi_cond_wait_t)(lapi_handle_t hndl, lapi_cond_t *cond);
typedef int (*lapi_cond_signal_t)(lapi_handle_t hndl, lapi_cond_t *cond);
此函数对条件变量 (cond) 发出信号,以唤醒在条件上阻塞的线程。 如果有多个线程在条件变量上等待,那么将随机决定要唤醒的线程。
Parameters
INPUT
hndl
指定 LAPI 句柄。
连接
是指向要发出信号的条件变量的指针。
Return values
0
指示已向条件变量发出信号。
EINVAL
指示由 hndlcond 指定的值无效。
Initialize condition function pointer
int (*lapi_cond_init_t)(lapi_handle_t hndl, lapi_cond_t *cond);
此函数用于初始化条件变量。
Parameters
INPUT
hndl
指定 LAPI 句柄。
连接
是指向要初始化的条件变量的指针。
Return values
0
指示已成功初始化条件变量。
再次
指示系统缺少必要的资源 (内存除外) 来初始化另一个条件变量。
ENOMEM
指示没有足够的内存来初始化条件变量。
EINVAL
如果 hndl 值无效,那么将返回此值。
Destroy condition function pointer
int (*lapi_cond_destroy_t)(lapi_handle_t hndl, lapi_cond_t *cond);
此函数会破坏条件变量。
Parameters
INPUT
hndl
指定 LAPI 句柄。
连接
是指向要销毁的条件变量的指针。
Return values
0
指示已成功销毁条件变量。
EBUSY
指示实现在被引用 (例如在 lapi_cond_wait_tlapi_cond_timedwait_t 中被另一个线程使用时) 时检测到试图破坏 cond 所引用的对象。
EINVAL
指示由 hndlcond 指定的值无效。

参数

INPUT
hndl
指定 LAPI 句柄。
输入/输出
util_cmd
指定实用程序函数的命令类型。
输出
ierror
指定 FORTRAN 返回码。 这始终是最后一个参数。

返回值

成功 (LAPI_SUCCESS)
指示函数调用已成功完成。
LAPI_ERR_DGSP
指示传入的 DGSP 为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中) 或不是已注册的 DGSP。
LAPI_ERR_DGSP_ATOM
指示 DGSP 具有小于 0 或大于 MAX_ATOM_SIZE 的 atom_size
LAPI_ERR_DGSP_BRANCH
指示 DGSP 尝试了位于代码数组外部的分支。 这仅在验证方式下返回。
LAPI_ERR_DGSP_COPY_SZ
Is returned with DGSP validation turned on when MCOPY block < 0 or COPY instruction with bytes < 0. This is returned only in validation mode.
LAPI_ERR_DGSP_FREE
指示 LAPI 尝试释放无效或不再注册的 DGSP。 对于每个 LAPI_RESERVE_DGSP 操作,应该有一个 LAPI_UNRESERVE_DGSP 操作来关闭 LAPI_REGISTER_DGSP 操作和一个 LAPI_UNRESERVE_DGSP 操作。
LAPI_ERR_DGSP_OPC
指示 DGSP opcode 无效。 这仅在验证方式下返回。
LAPI_ERR_DGSP_STACK
指示 DGSP 的 GOSUB 深度大于分配的堆栈支持的 GOSUB 深度。 堆栈分配由 dgsp-> 深度成员指定。 这仅在验证方式下返回。
LAPI_ERR_HNDL_INVALID
指示传入的 hndl 无效 (未初始化或处于终止状态)。
已耗尽LAPI_ERR_MEMORY_死
指示 LAPI 无法从系统获取内存。
LAPI_ERR_UDP_PORT_INFO
指示 udp_port 信息指针为 NULL (在 C 中) 或 udp_port 的值为 LAPI_ADDR_NULL (在 FORTRAN 中)。
LAPI_ERR_UTIL_CMD
指示命令类型无效。

C 示例

  1. 要创建和注册 DGSP ,请执行以下操作:
    
    {
          /*
          ** DGSP code array.  DGSP instructions are stored
          ** as ints (with constants defined in lapi.h for
          ** the number of integers needed to store each
          ** instruction).  We will have one COPY and one ITERATE
          ** instruction in our DGSP.  We use LAPI's constants
          ** to allocate the appropriate storage.
          */
          int code[LAPI_DGSM_COPY_SIZE+LAPI_DGSM_ITERATE_SIZE];
    
          /* DGSP description */
          lapi_dgsp_descr_t dgsp_d;
    
          /*
          ** Data structure for the xfer call.
          */
          lapi_xfer_t   xfer_struct;
    
       
          /* DGSP data structures */
          lapi_dgsm_copy_t     *copy_p;   /* copy instruction    */
          lapi_dgsm_iterate_t  *iter_p;   /* iterate instruction */
          int                  *code_ptr; /* code pointer        */
    
          /* constant for holding code array info */
          int                   code_less_iterate_size;
    
          /* used for DGSP registration */
          lapi_reg_dgsp_t     reg_util;
    
    
          /*
          ** Set up dgsp description
          */
    
          /* set pointer to code array */
          dgsp_d.code = &code[0];
    
          /* set size of code array */
          dgsp_d.code_size = LAPI_DGSM_COPY_SIZE + LAPI_DGSM_ITERATE_SIZE;
    
          /* not using DGSP gosub instruction */
          dgsp_d.depth = 1;
    
          /*
          ** set density to show internal gaps in the
          ** DGSP data layout
          */
          dgsp_d.density = LAPI_DGSM_SPARSE;
    
          /* transfer 4 bytes at a time */
          dgsp_d.size = 4;
    
          /* advance the template by 8 for each iteration */
          dgsp_d.extent = 8;
    
          /*
          ** ext specifies the memory 'footprint' of
          ** data to be transferred. The lext specifies
          ** the offset from the base address to begin
          ** viewing the data.  The rext specifies the
          ** length from the base address to use.
          */
          dgsp_d.lext = 0;
          dgsp_d.rext = 4;
          /* atom size of 0 lets LAPI choose the packet size */
          dgsp_d.atom_size = 0;
    
          /*
          ** set up the copy instruction
          */
          copy_p = (lapi_dgsm_copy_t *)(dgsp_d.code);
          copy_p->opcode = LAPI_DGSM_COPY;
    
          /* copy 4 bytes at a time */
          copy_p->bytes = (long) 4;
    
          /* start at offset 0 */
          copy_p->offset = (long) 0;
    
          /* set code pointer to address of iterate instruction */
          code_less_iterate_size =  dgsp_d.code_size - LAPI_DGSM_ITERATE_SIZE;
          code_ptr = ((int *)(code))+code_less_iterate_size;
    
          /*
          ** Set up iterate instruction
          */
          iter_p = (lapi_dgsm_iterate_t *) code_ptr;
          iter_p->opcode = LAPI_DGSM_ITERATE;
          iter_p->iter_loc = (-code_less_iterate_size);
    
          /* Set up and do DGSP registration */
          reg_util.Util_type = LAPI_REGISTER_DGSP;
          reg_util.idgsp = &dgsp_d;
          LAPI_Util(hndl, (lapi_util_t *)&reg_util);
    
          /* 
          ** LAPI returns a usable DGSP handle in 
          ** reg_util.dgsp_handle
          ** Use this handle for subsequent reserve/unreserve
          ** and Xfer calls.  On the receive side, this
          ** handle can be returned by the header handler using the 
          ** return_info_t mechanism.  The DGSP will then be used for
          ** scattering data.
          */
          
    }
    
  2. 要保留 DGSP 句柄:
    
    {
    	
          reg_util.dgsp_handle = dgsp_handle;
    
          /* 
          ** dgsp_handle has already been created and
          ** registered as in the above example
          */
    
          reg_util.Util_type = LAPI_RESERVE_DGSP;
          LAPI_Util(hndl, (lapi_util_t *)&reg_util);
    
          /*
          ** LAPI's internal reference count to dgsp_handle
          ** will be incremented.  DGSP will
          ** remain available until an unreserve is
          ** done for each reserve, plus one more for
          ** the original registration.
          */
    
    }
    
  3. 要取消保留 DGSP 句柄:
    
    {
    	
          reg_util.dgsp_handle = dgsp_handle;
    
          /* 
          ** dgsp_handle has already created and
          ** registered as in the above example, and
          ** this thread no longer needs it.
          */
    
          reg_util.Util_type = LAPI_UNRESERVE_DGSP;
          LAPI_Util(hndl, (lapi_util_t *)&reg_util);
    
          /*
          ** An unreserve is required for each reserve,
          ** plus one more for the original registration.
          */
    
    }
    

位置

/usr/lib/liblapi_r.a

相关信息

子例程: LAPI_InitLAPI_Xfer