|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 28672 (0x7000) Types: Ada Source Notes: 03_class, FILE, R1k_Segment, e3_tag, generic, package V_Xtasking, seg_03bda6
└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000 └─ ⟦5a81ac88f⟧ »Space Info Vol 1« └─⟦this⟧
with V_I_Types; with V_I_Callout; with System; package V_Xtasking is pragma Suppress (All_Checks); -- PURPOSE : V_XTASKING (extended Tasking) provides operations which may -- be performed on Ada tasks. These services augment those -- defined by the language. -- -- The SUSPEND_TASK and RESUME_TASK operations directly affect -- task states. SUSPEND_TASK places a task in a suspended state -- similar to the execution of a simple accept statement. -- RESUME_TASK places a suspended task in a ready-to-run state. -- RESUME_TASK may only be used to resume a task previously -- suspended by SUSPEND_TASK. -- -- SUSPEND_TASK and RESUME_TASK have been declared as overloaded -- procedures to allow the user to select the method of error -- notification. If a result parameter is provided in the call, -- a result status will be returned in the parameter; otherwise, -- an exception will be raised if an error occurs. -- -- The V_SEMAPHORES and V_MAILBOXES packages also provide -- operations which affect the states of tasks. -- -- In addition to SUSPEND_TASK and RESUME_TASK, V_XTASKING -- provides operations to generate task id's for tasks, to -- determine the current task and to get and set the following -- task parameters: priority, time slice interval, user field, -- callable attribute and terminated attribute. (The attributes -- may not be set.) Additionally, V_XTASKING provides operations -- to get and set the global time slicing enabled configuration -- parameter. -- --\x09\x09\x09 Services to disable and enable task preemption are --\x09\x09\x09 provided. -- -- For cross versions, V_XTASKING provides a service to start --\x09\x09\x09 and terminate another separately linked program. It also has --\x09\x09\x09 services to get the program id of the current program or --\x09\x09\x09 for any task. -- -- Services are also provided that allow subprogram callouts -- resident in the user program to be installed for program and -- task events. A callout can be installed for the following -- program events: exit, unexpected exit (main program -- abandoned due to an unhandled exception) and --\x09\x09\x09 switch. A callout can be installed for the following task --\x09\x09\x09 events: creation, switch and completion. Additionally, user --\x09\x09\x09 defined storage can be allocated in the control block for --\x09\x09\x09 a task. -- -- -- NOTES : Tasking within the Nucleus is prioritized, pre-emptive, and -- optionally timesliced. The type task_id (defined in SYSTEM) is --\x09\x09\x09 used to supply the identity of a task to a V_XTASKING service. -- Objects of type task_id are used to identify tasks to -- extended tasking services. type task_id is defined in SYSTEM. An object -- of this type is obtained via the T'TASK_ID attribute. -- Null task constant Null_Task_Name : constant System.Task_Id := System.No_Task_Id; -- Objects of the type program_id are used to identify programs to -- extended tasking services. type program_id is defined in SYSTEM. -- Type for referencing user defined storage in a task control block. type Task_Storage_Id is private; No_Task_Storage_Id : constant Task_Storage_Id; -- Type of event that can have a callout installed via -- INSTALL_CALLOUT service. type Callout_Event_T is new V_I_Callout.Callout_Event_T; -- Type of user modifiable field stored in task's control block subtype User_Field_T is V_I_Types.User_Field_T; -- The following exceptions may be raised by the V_XTASKING services. Invalid_Suspend : exception; -- INVALID_SUSPEND is raised by SUSPEND_TASK if the task could not -- be suspended. This will occur if the task is not currently -- runnable. Invalid_Resume : exception; -- INVALID_RESUME is raised by RESUME_TASK if the task could not be -- resumed. This will occur if the task is not currently suspended. Unexpected_V_Xtasking_Error : exception; -- UNEXPECTED_V_XTASKING_ERROR may be raised if an unexpected -- error occurs in an V_XTASKING routine. -- The following type declares the result codes which may be returned -- by the non-exception-raising versions of the SUSPEND_TASK and -- RESUME_TASK routines. type Xtasking_Result is (Suspended, Resumed, Not_Suspended, Not_Resumed); -- SUSPEND_TASK returns SUSPENDED if the suspend operation succeeded, -- or NOT_SUPENDED if the operation failed. RESUME_TASK returns -- RESUMED if the resume operation succeeded, or NOT_RESUMED if the -- operation failed. function Id (Task_Address : in System.Task_Id) return System.Task_Id; pragma Inline_Only (Id); -- Purpose: To return an id for a task given the address of the -- task. Provides compatibility with earlier releases which --\x09\x09\x09 didn't have the T'TASK_ID attribute. -- -- Where: -- -- task_address is the address of a task obtained by applying -- the 'task_id attribute to a task name. -- -- \x09\x09\x09T'ADDRESS has been changed in 6.0 and later releases --\x09\x09\x09 \x09\x09to be the starting address of the task body's machine --\x09\x09\x09\x09\x09code. Therefore, the type of the task_address --\x09\x09\x09\x09\x09parameter has changed from system.address to --\x09\x09\x09\x09\x09system.task_id. -- --\x09Note:\x09 This function no longer needs to be called. The --\x09\x09\x09 T'TASK_ID attribute returns the id for a task which may be --\x09\x09\x09 used by the V_XTASKING services. generic type Task_Type is limited private; function V_Id (Task_Object : in Task_Type) return System.Task_Id; pragma Inline_Only (V_Id); -- Purpose: To return an id for a task given a task object of -- the task type used to instantiate the generic. -- -- Where: -- -- task_type is a task type. -- -- task_object is an object of the task type used to instantiate -- this generic. function Current_Task return System.Task_Id; pragma Inline_Only (Current_Task); -- Purpose: This function returns the task id of the current -- task. procedure Resume_Task (Task_Name : in System.Task_Id); procedure Resume_Task (Task_Name : in System.Task_Id; Result : out Xtasking_Result); pragma Inline_Only (Resume_Task); -- Purpose: RESUME_TASK causes the named task to be -- readied for execution. -- -- Where: -- -- task_name identifies the task to be readied for execution. -- -- -- Notes: This service may only be used to activate a -- task suspended by a call to SUSPEND_TASK. -- -- Exceptions/Results: -- -- INVALID_RESUME is raised (or result value NOT_RESUMED is returned) -- if the task was not in a suspended state. -- -- The result value RESUMED is returned if the task is resumed. procedure Suspend_Task (Task_Name : in System.Task_Id); procedure Suspend_Task (Task_Name : in System.Task_Id; Result : out Xtasking_Result); pragma Inline_Only (Suspend_Task); -- Purpose: SUSPEND_TASK causes a running task to become -- suspended. -- -- Where: -- -- task_name identifies the task to suspend. -- -- Notes: This primitive only suspends the currently executing task or -- any ready to run task. -- -- Exceptions/Results: -- -- INVALID_SUSPEND is raised (or result code NOT_SUSPENDED is returned) -- if task is not runnable. -- -- The result value SUSPENDED is returned if the task is suspended. function Current_Priority (Task_Name : in System.Task_Id := Current_Task) return System.Priority; pragma Inline_Only (Current_Priority); -- Purpose: This function returns the current priority of the -- specified task. -- -- Where: -- -- task_name indicates the id of the task whose priority is to -- be returned to the caller. Defaults to the current task. procedure Set_Priority (New_Priority : in System.Priority; Task_Name : in System.Task_Id := Current_Task); pragma Inline_Only (Set_Priority); -- Purpose: SET_PRIORITY sets the priority of the specified task to a -- new setting. Task scheduling is re-evaluated. -- -- Notes: this service should be used with extreme caution as it -- may interfere with the kernel's scheduling algorithm. -- -- Where: -- -- new_priority is the new priority setting. -- -- task_name indicates the id of the task whose priority is to be set. -- Defaults to the current task. function Current_Time_Slice (Task_Name : in System.Task_Id := Current_Task) return Duration; pragma Inline_Only (Current_Time_Slice); -- Purpose: This function returns the current time slice interval of the -- specified task. -- -- Where: -- -- task_name indicates the id of the task whose time slice interval is to -- be returned to the caller. Defaults to the current task. procedure Set_Time_Slice (New_Interval : in Duration; Task_Name : in System.Task_Id := Current_Task); pragma Inline_Only (Set_Time_Slice); -- Purpose: SET_TIME_SLICE sets the time slice interval of the -- specified task to a new value. -- -- Where: -- -- new_interval is the new time slice duration. An interval of 0.0 -- seconds disables time slicing for the task. -- -- task_name indicates the id of the task whose time slice interval -- is to be set. Defaults to the current task. function Current_User_Field (Task_Name : in System.Task_Id := Current_Task) return User_Field_T; pragma Inline_Only (Current_User_Field); -- Purpose: This function returns the current value for the user -- modifiable field of the specified task. -- -- Where: -- -- task_name indicates the id of the task whose user field value is to -- be returned to the caller. Defaults to the current task. procedure Set_User_Field (New_Value : in User_Field_T; Task_Name : in System.Task_Id := Current_Task); pragma Inline_Only (Set_User_Field); -- Purpose: SET_USER_FIELD sets the user modifiable field of the -- specified task to a new value. -- -- Where: -- -- new_value is the new value written to the user modifiable field. -- -- task_name indicates the id of the task whose user field value -- is to be set. Defaults to the current task. function Callable (Task_Name : in System.Task_Id) return Boolean; pragma Inline_Only (Callable); -- Purpose: This function returns the P'CALLABLE attribute for the -- specified task. Returns FALSE when the execution of the -- task is either completed or terminated, or when the task -- is abnormal. Returns TRUE otherwise. -- -- Where: -- -- task_name indicates the id of the task to get the P'CALLABLE -- attribute for. function Terminated (Task_Name : in System.Task_Id) return Boolean; pragma Inline_Only (Terminated); -- Purpose: This function returns the P'TERMINATED attribute for the -- specified task. Returns TRUE if the the task is -- terminated. Returns FALSE otherwise. -- -- Where: -- -- task_name indicates the id of the task to get the P'TERMINATED -- attribute for. function Current_Time_Slicing_Enabled return Boolean; pragma Inline_Only (Current_Time_Slicing_Enabled); -- Purpose: This function returns the current value for the kernel's -- TIME_SLICING_ENABLED configuration parameter. procedure Set_Time_Slicing_Enabled (New_Value : in Boolean := True); pragma Inline_Only (Set_Time_Slicing_Enabled); -- Purpose: SET_TIME_SLICING_ENABLED sets the kernel's -- TIME_SLICING_ENABLED configuration parameter. function Current_Exit_Disabled return Boolean; pragma Inline_Only (Current_Exit_Disabled); -- Purpose: This function returns the current value for the kernel's -- global variable, __EXIT_DISABLED_FLAG. When, TRUE, the --\x09\x09\x09\x09application program is inhibited from exiting. procedure Set_Exit_Disabled (New_Value : in Boolean := True); pragma Inline_Only (Set_Exit_Disabled); -- Purpose: SET_EXIT_DISABLED sets the kernel's global variable, --\x09\x09\x09\x09__EXIT_DISABLED_FLAG. This flag is initialized --\x09\x09\x09\x09to FALSE, which allows the application program to exit --\x09\x09\x09\x09when there are no tasks on either the run or delay queue. --\x09\x09\x09\x09This service is called, with new_value := TRUE, to --\x09\x09\x09 inhibit the program from exiting. Normally called --\x09\x09\x09\x09if the application program has attached ISRs. The program --\x09\x09\x09\x09may be allowed to exit with a subsequent call, where, --\x09\x09\x09\x09new_value := FALSE. function Start_Program (Link_Block_Address : in System.Address; Key : in System.Address := System.Memory_Address (1); Terminate_Callout : in System.Address := System.No_Addr) return System.Program_Id; pragma Inline_Only (Start_Program); -- Purpose: This service starts up another separately linked program -- identified by its link block. It assumes the program was -- previously loaded. It returns the program id of the -- just started program. -- -- This service isn't supported for self_hosted versions of -- V_XTASKING. -- -- Where: -- -- link_block_address is the address of the to be started program's -- LINK_BLOCK. Normally, this is the origin of the -- program. -- -- key \x09\x09\x09\x09 is a user defined value stored in the new program's --\x09\x09\x09\x09\x09\x09 control block. This key is passed to the --\x09\x09\x09\x09\x09\x09 PROGRAM_SWITCH_EVENT callouts. The key may be --\x09\x09\x09\x09\x09\x09 obtained by routines in the new program via --\x09\x09\x09\x09\x09 the GET_PROGRAM_KEY service. One use for the --\x09\x09\x09\x09\x09\x09 key is to have it point to a list of program --\x09\x09\x09\x09\x09\x09 arguments. The value for the main program's key is --\x09\x09\x09\x09\x09\x09 0 (system.NO_ADDR) -- -- terminate_callout is the address of the procedure to be called when --\x09\x09\x09\x09\x09\x09 the program exits or is terminated. A value of --\x09\x09\x09\x09\x09\x09 NO_ADDR indicates no callout. The callout --\x09\x09\x09\x09\x09\x09 procedure is called as follows: -- -- \x09\x09\x09\x09 \x09\x09procedure terminate_callout_proc --\x09\x09\x09\x09\x09\x09\x09\x09(program_name\x09: in program_id; -- \x09\x09\x09\x09 \x09\x09 key\x09\x09\x09: in address); -- -- \x09\x09\x09\x09\x09 terminate_callout_proc must be compiled with --\x09\x09\x09\x09\x09\x09 stack limit checking suppressed. The --\x09\x09\x09\x09\x09\x09 PROGRAM_SWITCH_EVENT callout isn't called before --\x09\x09\x09\x09\x09 \x09 the terminate_callout_proc is called. -- -- \x09\x09\x09\x09\x09\x09 Note, if the program is terminated via --\x09\x09\x09\x09\x09\x09 TERMINATE_PROGRAM and if the program has tasks --\x09\x09\x09\x09\x09\x09 in rendezvous with tasks in other programs, then, --\x09\x09\x09\x09\x09\x09 terminate_callout_proc may be called after --\x09\x09\x09\x09\x09\x09 TERMINATE_PROGRAM returns. function Current_Program return System.Program_Id; pragma Inline_Only (Current_Program); -- Purpose: This function returns the program id of the current -- program. function Get_Program (Task_Name : in System.Task_Id) return System.Program_Id; pragma Inline_Only (Get_Program); -- Purpose: This function returns the program id for the specified -- task. -- -- Where: -- -- task_name indicates the id of the task to get program id for. procedure Terminate_Program (Status : in Integer; Program_Name : in System.Program_Id := Current_Program); pragma Inline_Only (Terminate_Program); -- Purpose: This procedure terminates the specified program. --\x09\x09\x09 If the current program is terminated, then, the -- EXIT_EVENT callouts installed for the current program -- are called before the program is terminated. Otherwise, --\x09\x09\x09\x09if another program is terminated, its EXIT_EVENT callouts --\x09\x09\x09 aren't called. After the current or another program is --\x09\x09\x09\x09terminated, the TERMINATE_CALLOUT, passed to START_PROGRAM --\x09\x09\x09\x09is called. -- --\x09\x09\x09\x09When a program is terminated, all its tasks are aborted --\x09\x09\x09\x09and all memory allocated by the program is freed. -- --\x09\x09\x09\x09If the program being terminated has tasks in rendezvous --\x09\x09\x09\x09with tasks in other programs, then, the completion --\x09\x09\x09\x09of program termination is deferred until the rendezvous --\x09\x09\x09\x09finishes. For this case, TERMINATE_PROGRAM will return --\x09\x09\x09\x09before the termination has completed. However, --\x09\x09\x09 execution of the TERMINATE_CALLOUT procedure is deferred. -- -- For multiple programs on cross targets: -- - If called from an ISR, all programs are terminated. -- However, only the EXIT_EVENT callouts associated with -- the program containing the ISR are called. Also, --\x09\x09\x09\x09 the TERMINATE_CALLOUT isn't called. -- -- Where: -- -- status\x09\x09 is the program exit status -- -- program_name \x09indicates the id of the program to terminate function Get_Program_Key (Program_Name : in System.Program_Id := Current_Program) return System.Address; pragma Inline_Only (Get_Program_Key); -- Purpose: This function returns the user defined key for the --\x09\x09\x09\x09specified program. -- -- Where: -- -- program_name indicates the id of the program to get the key for procedure Install_Callout (Event : in Callout_Event_T; Proc : in System.Address); pragma Inline_Only (Install_Callout); -- Purpose: This service installs a procedure to be called at -- a program or task event. Callouts can be installed --\x09\x09\x09\x09for EXIT_EVENT, UNEXPECTED_EXIT_EVENT, --\x09\x09\x09\x09PROGRAM_SWITCH_EVENT, TASK_CREATE_EVENT, --\x09\x09\x09\x09TASK_SWITCH_EVENT or TASK_COMPLETE_EVENT. -- --\x09\x09\x09\x09Callout procedures are called in the order they were --\x09\x09\x09\x09installed. --\x09\x09\x09\x09The callouts reside in the user program's space. The --\x09\x09\x09\x09EXIT_EVENT and UNEXPECTED_EXIT_EVENT callouts are called --\x09\x09\x09\x09in the context of the main program's task. The remaining -- \x09\x09\x09callouts are called directly from kernel logic (use the --\x09\x09\x09\x09kernel's stack) and can only call kernel services that --\x09\x09\x09\x09are re-entrant, the same services callable from ISR's. --\x09\x09\x09\x09The service of most interest is CALENDAR.CLOCK which --\x09\x09\x09\x09would be called for time stamping. -- -- \x09\x09\x09Before any non-PROGRAM_SWITCH_EVENT callout procedure is -- \x09\x09\x09invoked, the STACK_LIMIT in the user program is set to 0 to -- \x09\x09\x09negate any stack limit checking. Therefore, the callout -- \x09\x09\x09procedures don't need to be compiled with stack limit --\x09\x09\x09\x09checking suppressed. However, the STACK_LIMIT isn't --\x09\x09\x09\x09zeroed before calling the PROGRAM_SWITCH_EVENT callout. --\x09\x09\x09\x09It needs to be compiled with stack checking suppressed. -- -- \x09\x09\x09Except for the PROGRAM_SWITCH_EVENT, the callouts are only -- \x09\x09\x09installed and called for the program where they reside. -- -- \x09\x09\x09An overview of the different callout events follows: -- -- \x09\x09\x09EXIT_EVENT --\x09\x09\x09\x09 Called when the program exits or terminates itself. Not --\x09\x09\x09\x09 called when the program is terminated from another --\x09\x09\x09\x09 program. Still called when the UNEXPECTED_EXIT_EVENT --\x09\x09\x09\x09 callout is called. -- -- \x09\x09\x09UNEXPECTED_EXIT_EVENT --\x09\x09\x09\x09 Called when the program is abandoned due to an unhandled --\x09\x09\x09\x09 Ada exception. --\x09\x09 --\x09 \x09\x09\x09PROGRAM_SWITCH_EVENT --\x09\x09\x09\x09 Called before switching to a task that resides in a --\x09\x09\x09\x09 program different from the current program. Called for --\x09\x09\x09\x09 all program switches, not just switches to and from the --\x09\x09\x09\x09 program containing the callout. -- --\x09 \x09\x09\x09TASK_CREATE_EVENT --\x09\x09\x09\x09 Called whenever a task is created in the program --\x09\x09\x09\x09 containing the callout. Since the TASK_CREATE_EVENT --\x09\x09\x09\x09 callout can be called after numerous tasks have already --\x09\x09\x09\x09 been created, the INSTALL_CALLOUT service loops through --\x09\x09\x09\x09 all existing tasks invoking the just installed --\x09\x09\x09\x09 TASK_CREATE_EVENT callout. -- --\x09 \x09\x09\x09TASK_SWITCH_EVENT --\x09\x09\x09\x09 Called before switching to a different task in the same --\x09\x09\x09\x09 program. For a program switch, the TASK_SWITCH_EVENT -- \x09\x09 callout is called with the task_name parameter set to --\x09\x09\x09\x09 NULL_TASK_NAME. -- --\x09 \x09\x09\x09TASK_SWITCH_COMPLETE --\x09\x09\x09\x09 Called whenever any task in the callout's program --\x09\x09\x09\x09 completes or is aborted. -- -- Where: -- -- event is the program or task event at which time the --\x09\x09\x09\x09\x09installed procedure is called. -- -- proc \x09\x09is the address of the procedure to be called. The -- \x09\x09\x09\x09EXIT_EVENT or UNEXPECTED_EXIT_EVENT callout procedure -- \x09\x09\x09\x09is called as follows: -- --\x09 \x09\x09\x09\x09procedure exit_callout_proc --\x09\x09\x09\x09\x09\x09\x09(status\x09: in integer);\x09-- main subprogram --\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09-- return status -- -- \x09\x09\x09\x09The PROGRAM_SWITCH_EVENT callout procedure is called --\x09\x09\x09\x09\x09as follows: -- --\x09 \x09\x09\x09\x09procedure program_switch_callout_proc --\x09 \x09\x09\x09\x09(new_program_name\x09: in program_id; --\x09\x09\x09\x09\x09\x09\x09 new_key\x09\x09\x09: in address); -- -- \x09\x09\x09\x09The TASK_CREATE_EVENT, TASK_SWITCH_EVENT or --\x09\x09\x09\x09\x09TASK_COMPLETE_EVENT callout procedure is called --\x09\x09\x09\x09\x09as follows: -- --\x09 \x09\x09\x09\x09procedure task_callout_proc --\x09 \x09\x09\x09\x09(task_name\x09: in task_id); -- -- Exceptions: -- -- STORAGE_ERROR is raised if not enough memory for the callout -- data structures function Allocate_Task_Storage (Size : in Natural) return Task_Storage_Id; pragma Inline_Only (Allocate_Task_Storage); -- Purpose: This service allocates storage in the task control block. -- It returns the id to be used in subsequent -- GET_TASK_STORAGE service calls. -- -- \x09\x09\x09The task storage allocation is only applicable to tasks --\x09\x09\x09\x09in the current program. -- -- Where: -- -- size indicates the number of bytes to be allocated in the task -- control block. -- -- Exceptions: -- -- STORAGE_ERROR is raised if not enough memory in the task control -- block for the task storage. The configuration parameter, -- TASK_STORAGE_SIZE, defines the size of the storage area set aside in -- the control block for each task. Each allocation from this area is -- aligned on a 4 or 8 byte boundary (the alignment is CPU dependent). function Get_Task_Storage (Task_Name : in System.Task_Id; Storage_Id : in Task_Storage_Id) return System.Address; pragma Inline_Only (Get_Task_Storage); -- Purpose: This service returns the starting address of the task -- storage area associated with the storage_id. -- -- Where: -- -- task_name indicates the id of the task to get the address of -- the storage area for. -- -- storage_id contains the value returned by -- \x09\x09\x09a previous call to allocate_task_storage. Its only -- \x09\x09\x09applicable to tasks in the program where the -- \x09\x09\x09ALLOCATE_TASK_STORAGE service was called from. procedure Disable_Preemption; pragma Inline_Only (Disable_Preemption); -- Purpose: To inhibit the current task from being preempted. --\x09\x09\x09\x09 This service doesn't disable interrupts. -- --\x09\x09\x09\x09 Calling a kernel service does an implicit --\x09\x09\x09\x09 ENABLE_PREEMPTION. procedure Enable_Preemption; pragma Inline_Only (Enable_Preemption); -- Purpose: To allow the current task to be preempted. private type Task_Storage_Id is new V_I_Callout.Task_Storage_Id; No_Task_Storage_Id : constant Task_Storage_Id := Task_Storage_Id (0); end V_Xtasking;
nblk1=1b nid=0 hdr6=36 [0x00] rec0=17 rec1=00 rec2=01 rec3=044 [0x01] rec0=13 rec1=00 rec2=02 rec3=042 [0x02] rec0=14 rec1=00 rec2=03 rec3=068 [0x03] rec0=1e rec1=00 rec2=04 rec3=020 [0x04] rec0=18 rec1=00 rec2=05 rec3=02e [0x05] rec0=1b rec1=00 rec2=06 rec3=022 [0x06] rec0=1d rec1=00 rec2=07 rec3=00c [0x07] rec0=1d rec1=00 rec2=08 rec3=0a0 [0x08] rec0=1c rec1=00 rec2=09 rec3=05c [0x09] rec0=1b rec1=00 rec2=0a rec3=02a [0x0a] rec0=19 rec1=00 rec2=0b rec3=030 [0x0b] rec0=18 rec1=00 rec2=0c rec3=022 [0x0c] rec0=1b rec1=00 rec2=0d rec3=000 [0x0d] rec0=17 rec1=00 rec2=0e rec3=03c [0x0e] rec0=16 rec1=00 rec2=0f rec3=016 [0x0f] rec0=15 rec1=00 rec2=10 rec3=010 [0x10] rec0=1a rec1=00 rec2=11 rec3=032 [0x11] rec0=17 rec1=00 rec2=12 rec3=02e [0x12] rec0=17 rec1=00 rec2=13 rec3=026 [0x13] rec0=19 rec1=00 rec2=14 rec3=028 [0x14] rec0=11 rec1=00 rec2=15 rec3=01c [0x15] rec0=17 rec1=00 rec2=16 rec3=006 [0x16] rec0=18 rec1=00 rec2=17 rec3=010 [0x17] rec0=1c rec1=00 rec2=18 rec3=016 [0x18] rec0=19 rec1=00 rec2=19 rec3=018 [0x19] rec0=1d rec1=00 rec2=1a rec3=00a [0x1a] rec0=04 rec1=00 rec2=1b rec3=000 tail 0x215347eda85657438d291 0x42a00088462060003