Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:22

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplClassicMessageMP
0007  *
0008  * @brief This source file contains the implementation to support the Message
0009  *   Manager in multiprocessing (MP) configurations.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2008.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include <rtems/rtems/messageimpl.h>
0043 #include <rtems/rtems/optionsimpl.h>
0044 #include <rtems/rtems/statusimpl.h>
0045 #include <rtems/score/coremsgimpl.h>
0046 #include <rtems/score/statesimpl.h>
0047 #include <rtems/score/threadimpl.h>
0048 #include <rtems/sysinit.h>
0049 
0050 RTEMS_STATIC_ASSERT(
0051   MESSAGE_QUEUE_MP_PACKET_SIZE <= MP_PACKET_MINIMUM_PACKET_SIZE,
0052   Message_queue_MP_Packet
0053 );
0054 
0055 static Message_queue_MP_Packet *_Message_queue_MP_Get_packet( void )
0056 {
0057   return (Message_queue_MP_Packet *) _MPCI_Get_packet();
0058 }
0059 
0060 
0061 /*
0062  *  _Message_queue_MP_Send_process_packet
0063  *
0064  */
0065 
0066 void _Message_queue_MP_Send_process_packet (
0067   Message_queue_MP_Remote_operations  operation,
0068   Objects_Id                          message_queue_id,
0069   rtems_name                          name,
0070   Objects_Id                          proxy_id
0071 )
0072 {
0073   Message_queue_MP_Packet *the_packet;
0074   uint32_t                 node;
0075 
0076   switch ( operation ) {
0077 
0078     case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
0079     case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
0080     case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
0081 
0082       the_packet                    = _Message_queue_MP_Get_packet();
0083       the_packet->Prefix.the_class  = MP_PACKET_MESSAGE_QUEUE;
0084       the_packet->Prefix.length     = MESSAGE_QUEUE_MP_PACKET_SIZE;
0085       the_packet->Prefix.to_convert = MESSAGE_QUEUE_MP_PACKET_SIZE;
0086       the_packet->operation         = operation;
0087       the_packet->Prefix.id         = message_queue_id;
0088       the_packet->name              = name;
0089       the_packet->proxy_id          = proxy_id;
0090 
0091       if ( operation == MESSAGE_QUEUE_MP_EXTRACT_PROXY )
0092          node = _Objects_Get_node( message_queue_id );
0093       else
0094          node = MPCI_ALL_NODES;
0095 
0096       _MPCI_Send_process_packet( node, &the_packet->Prefix );
0097       break;
0098 
0099     case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
0100     case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
0101     case MESSAGE_QUEUE_MP_SEND_REQUEST:
0102     case MESSAGE_QUEUE_MP_SEND_RESPONSE:
0103     case MESSAGE_QUEUE_MP_URGENT_REQUEST:
0104     case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
0105     case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
0106     case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
0107     case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
0108     case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
0109     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
0110     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
0111       break;
0112 
0113   }
0114 }
0115 
0116 /*
0117  *  _Message_queue_MP_Send_request_packet
0118  *
0119  */
0120 
0121 static rtems_status_code _Message_queue_MP_Send_request_packet (
0122   Objects_Id                          message_queue_id,
0123   const void                         *buffer,
0124   size_t                             *size_p,
0125   rtems_option                        option_set,
0126   rtems_interval                      timeout,
0127   Message_queue_MP_Remote_operations  operation
0128 )
0129 {
0130   Message_queue_MP_Packet *the_packet;
0131   Status_Control           status;
0132 
0133   if ( !_Message_queue_MP_Is_remote( message_queue_id ) ) {
0134     return RTEMS_INVALID_ID;
0135   }
0136 
0137   switch ( operation ) {
0138 
0139     case MESSAGE_QUEUE_MP_SEND_REQUEST:
0140     case MESSAGE_QUEUE_MP_URGENT_REQUEST:
0141     case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
0142     case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
0143     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
0144 
0145       the_packet                    = _Message_queue_MP_Get_packet();
0146       the_packet->Prefix.the_class  = MP_PACKET_MESSAGE_QUEUE;
0147       the_packet->Prefix.length     = MESSAGE_QUEUE_MP_PACKET_SIZE;
0148       if ( size_p )
0149         the_packet->Prefix.length     += *size_p;
0150       the_packet->Prefix.to_convert = MESSAGE_QUEUE_MP_PACKET_SIZE;
0151 
0152       /*
0153        * make sure message is not too big for our MPCI driver
0154        * We have to check it here instead of waiting for MPCI because
0155        * we are about to slam in the payload
0156        */
0157 
0158       if (the_packet->Prefix.length > _MPCI_table->maximum_packet_size) {
0159           return RTEMS_INVALID_SIZE;
0160       }
0161 
0162       if (! _Options_Is_no_wait(option_set))
0163           the_packet->Prefix.timeout = timeout;
0164 
0165       the_packet->operation  = operation;
0166       the_packet->Prefix.id  = message_queue_id;
0167       the_packet->option_set = option_set;
0168 
0169       /*
0170        * Copy the data into place if needed
0171        */
0172 
0173       if (buffer) {
0174           the_packet->size = *size_p;
0175           _CORE_message_queue_Copy_buffer(
0176             buffer,
0177             the_packet->buffer,
0178             *size_p
0179           );
0180       }
0181 
0182       status = _MPCI_Send_request_packet(
0183         _Objects_Get_node(message_queue_id),
0184         &the_packet->Prefix,
0185         STATES_WAITING_FOR_MESSAGE
0186       );
0187       return _Status_Get( status );
0188 
0189     case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
0190 
0191       the_packet                    = _Message_queue_MP_Get_packet();
0192       the_packet->Prefix.the_class  = MP_PACKET_MESSAGE_QUEUE;
0193       the_packet->Prefix.length     = MESSAGE_QUEUE_MP_PACKET_SIZE;
0194       the_packet->Prefix.to_convert = MESSAGE_QUEUE_MP_PACKET_SIZE;
0195 
0196       if (! _Options_Is_no_wait(option_set))
0197           the_packet->Prefix.timeout = timeout;
0198 
0199       the_packet->operation  = MESSAGE_QUEUE_MP_RECEIVE_REQUEST;
0200       the_packet->Prefix.id  = message_queue_id;
0201       the_packet->option_set = option_set;
0202       the_packet->size       = 0;        /* just in case of an error */
0203 
0204       _Thread_Executing->Wait.return_argument_second.immutable_object = buffer;
0205       _Thread_Executing->Wait.return_argument = size_p;
0206 
0207       status = _MPCI_Send_request_packet(
0208         _Objects_Get_node(message_queue_id),
0209         &the_packet->Prefix,
0210         STATES_WAITING_FOR_MESSAGE
0211       );
0212       return _Status_Get( status );
0213 
0214     case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
0215     case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
0216     case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
0217     case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
0218     case MESSAGE_QUEUE_MP_SEND_RESPONSE:
0219     case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
0220     case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
0221     case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
0222     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
0223       break;
0224   }
0225 
0226   return RTEMS_SUCCESSFUL;
0227 }
0228 
0229 rtems_status_code _Message_queue_MP_Broadcast(
0230   rtems_id    id,
0231   const void *buffer,
0232   size_t      size,
0233   uint32_t   *count
0234 )
0235 {
0236   _Thread_Get_executing()->Wait.return_argument = count;
0237   return _Message_queue_MP_Send_request_packet(
0238     id,
0239     buffer,
0240     &size,
0241     0,
0242     MPCI_DEFAULT_TIMEOUT,
0243     MESSAGE_QUEUE_MP_BROADCAST_REQUEST
0244   );
0245 }
0246 
0247 rtems_status_code _Message_queue_MP_Flush(
0248   rtems_id  id,
0249   uint32_t *count
0250 )
0251 {
0252   _Thread_Get_executing()->Wait.return_argument = count;
0253   return _Message_queue_MP_Send_request_packet(
0254     id,
0255     NULL,
0256     NULL,
0257     0,
0258     MPCI_DEFAULT_TIMEOUT,
0259     MESSAGE_QUEUE_MP_FLUSH_REQUEST
0260   );
0261 }
0262 
0263 rtems_status_code _Message_queue_MP_Get_number_pending(
0264   rtems_id  id,
0265   uint32_t *count
0266 )
0267 {
0268   _Thread_Get_executing()->Wait.return_argument = count;
0269   return _Message_queue_MP_Send_request_packet(
0270     id,
0271     NULL,
0272     NULL,
0273     0,
0274     MPCI_DEFAULT_TIMEOUT,
0275     MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST
0276   );
0277 }
0278 
0279 rtems_status_code _Message_queue_MP_Receive(
0280   rtems_id        id,
0281   void           *buffer,
0282   size_t         *size,
0283   rtems_option    option_set,
0284   rtems_interval  timeout
0285 )
0286 {
0287   return _Message_queue_MP_Send_request_packet(
0288     id,
0289     buffer,
0290     size,
0291     option_set,
0292     timeout,
0293     MESSAGE_QUEUE_MP_RECEIVE_REQUEST
0294   );
0295 }
0296 
0297 rtems_status_code _Message_queue_MP_Send(
0298   rtems_id    id,
0299   const void *buffer,
0300   size_t      size
0301 )
0302 {
0303   return _Message_queue_MP_Send_request_packet(
0304     id,
0305     buffer,
0306     &size,
0307     0,
0308     MPCI_DEFAULT_TIMEOUT,
0309     MESSAGE_QUEUE_MP_SEND_REQUEST
0310   );
0311 }
0312 
0313 rtems_status_code _Message_queue_MP_Urgent(
0314   rtems_id    id,
0315   const void *buffer,
0316   size_t      size
0317 )
0318 {
0319   return _Message_queue_MP_Send_request_packet(
0320     id,
0321     buffer,
0322     &size,
0323     0,
0324     MPCI_DEFAULT_TIMEOUT,
0325     MESSAGE_QUEUE_MP_URGENT_REQUEST
0326   );
0327 }
0328 
0329 /*
0330  *  _Message_queue_MP_Send_response_packet
0331  *
0332  */
0333 
0334 static void _Message_queue_MP_Send_response_packet (
0335   Message_queue_MP_Remote_operations  operation,
0336   Objects_Id                          message_queue_id,
0337   Thread_Control                     *the_thread
0338 )
0339 {
0340   Message_queue_MP_Packet *the_packet;
0341 
0342   switch ( operation ) {
0343 
0344     case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
0345     case MESSAGE_QUEUE_MP_SEND_RESPONSE:
0346     case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
0347     case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
0348     case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
0349     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
0350 
0351       the_packet = ( Message_queue_MP_Packet *) the_thread->receive_packet;
0352 
0353 /*
0354  *  The packet being returned already contains the class, length, and
0355  *  to_convert fields, therefore they are not set in this routine.
0356  *
0357  *  Exception: MESSAGE_QUEUE_MP_RECEIVE_RESPONSE needs payload length
0358  *             added to 'length'
0359  */
0360       the_packet->operation = operation;
0361       the_packet->Prefix.id = the_packet->Prefix.source_tid;
0362 
0363       if (operation == MESSAGE_QUEUE_MP_RECEIVE_RESPONSE)
0364           the_packet->Prefix.length += the_packet->size;
0365 
0366       _MPCI_Send_response_packet(
0367         _Objects_Get_node( the_packet->Prefix.source_tid ),
0368         &the_packet->Prefix
0369       );
0370       break;
0371 
0372     case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
0373     case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
0374     case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
0375     case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
0376     case MESSAGE_QUEUE_MP_SEND_REQUEST:
0377     case MESSAGE_QUEUE_MP_URGENT_REQUEST:
0378     case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
0379     case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
0380     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
0381       break;
0382 
0383   }
0384 }
0385 
0386 static void _Message_queue_MP_Process_packet (
0387   rtems_packet_prefix   *the_packet_prefix
0388 )
0389 {
0390   Message_queue_MP_Packet *the_packet;
0391   Thread_Control          *the_thread;
0392 
0393   the_packet = (Message_queue_MP_Packet *) the_packet_prefix;
0394 
0395   switch ( the_packet->operation ) {
0396 
0397     case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
0398 
0399       _Objects_MP_Allocate_and_open(
0400         &_Message_queue_Information,
0401         the_packet->name,
0402         the_packet->Prefix.id,
0403         true
0404       );
0405 
0406       _MPCI_Return_packet( the_packet_prefix );
0407       break;
0408 
0409     case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
0410 
0411       _Objects_MP_Close( &_Message_queue_Information, the_packet->Prefix.id );
0412 
0413       _MPCI_Return_packet( the_packet_prefix );
0414       break;
0415 
0416     case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
0417 
0418       the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id );
0419 
0420       if ( the_thread != NULL ) {
0421         _Thread_queue_Extract( the_thread );
0422       }
0423 
0424       _MPCI_Return_packet( the_packet_prefix );
0425       break;
0426 
0427     case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
0428 
0429       the_packet->Prefix.return_code = rtems_message_queue_receive(
0430         the_packet->Prefix.id,
0431         the_packet->buffer,
0432         &the_packet->size,
0433         the_packet->option_set,
0434         the_packet->Prefix.timeout
0435       );
0436 
0437       if ( the_packet->Prefix.return_code != RTEMS_PROXY_BLOCKING )
0438         _Message_queue_MP_Send_response_packet(
0439           MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,
0440           the_packet->Prefix.id,
0441           _Thread_Executing
0442         );
0443       break;
0444 
0445     case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
0446 
0447       the_thread = _MPCI_Process_response( the_packet_prefix );
0448 
0449       if (the_packet->Prefix.return_code == RTEMS_SUCCESSFUL) {
0450         *(size_t *) the_thread->Wait.return_argument =
0451            the_packet->size;
0452 
0453         _CORE_message_queue_Copy_buffer(
0454           the_packet->buffer,
0455           the_thread->Wait.return_argument_second.mutable_object,
0456           the_packet->size
0457         );
0458       }
0459 
0460       _MPCI_Return_packet( the_packet_prefix );
0461       break;
0462 
0463     case MESSAGE_QUEUE_MP_SEND_REQUEST:
0464 
0465       the_packet->Prefix.return_code = rtems_message_queue_send(
0466         the_packet->Prefix.id,
0467         the_packet->buffer,
0468         the_packet->size
0469       );
0470 
0471       _Message_queue_MP_Send_response_packet(
0472         MESSAGE_QUEUE_MP_SEND_RESPONSE,
0473         the_packet->Prefix.id,
0474         _Thread_Executing
0475       );
0476       break;
0477 
0478     case MESSAGE_QUEUE_MP_SEND_RESPONSE:
0479     case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
0480 
0481       the_thread = _MPCI_Process_response( the_packet_prefix );
0482 
0483       _MPCI_Return_packet( the_packet_prefix );
0484       break;
0485 
0486     case MESSAGE_QUEUE_MP_URGENT_REQUEST:
0487 
0488       the_packet->Prefix.return_code = rtems_message_queue_urgent(
0489         the_packet->Prefix.id,
0490         the_packet->buffer,
0491         the_packet->size
0492       );
0493 
0494       _Message_queue_MP_Send_response_packet(
0495         MESSAGE_QUEUE_MP_URGENT_RESPONSE,
0496         the_packet->Prefix.id,
0497         _Thread_Executing
0498       );
0499       break;
0500 
0501     case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
0502 
0503       the_packet->Prefix.return_code = rtems_message_queue_broadcast(
0504         the_packet->Prefix.id,
0505         the_packet->buffer,
0506         the_packet->size,
0507         &the_packet->count
0508       );
0509 
0510       _Message_queue_MP_Send_response_packet(
0511         MESSAGE_QUEUE_MP_BROADCAST_RESPONSE,
0512         the_packet->Prefix.id,
0513         _Thread_Executing
0514       );
0515       break;
0516 
0517     case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
0518     case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
0519     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
0520 
0521       the_thread = _MPCI_Process_response( the_packet_prefix );
0522 
0523       *(uint32_t *) the_thread->Wait.return_argument = the_packet->count;
0524 
0525       _MPCI_Return_packet( the_packet_prefix );
0526       break;
0527 
0528     case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
0529 
0530       the_packet->Prefix.return_code = rtems_message_queue_flush(
0531         the_packet->Prefix.id,
0532         &the_packet->count
0533       );
0534 
0535       _Message_queue_MP_Send_response_packet(
0536         MESSAGE_QUEUE_MP_FLUSH_RESPONSE,
0537         the_packet->Prefix.id,
0538         _Thread_Executing
0539       );
0540       break;
0541 
0542     case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
0543 
0544       the_packet->Prefix.return_code = rtems_message_queue_get_number_pending(
0545         the_packet->Prefix.id,
0546         &the_packet->count
0547       );
0548 
0549       _Message_queue_MP_Send_response_packet(
0550         MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE,
0551         the_packet->Prefix.id,
0552         _Thread_Executing
0553       );
0554       break;
0555 
0556   }
0557 }
0558 
0559 /*
0560  *  _Message_queue_MP_Send_object_was_deleted
0561  *
0562  */
0563 
0564 void _Message_queue_MP_Send_object_was_deleted (
0565   Thread_Control *the_proxy,
0566   Objects_Id      mp_id
0567 )
0568 {
0569   the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED;
0570 
0571   _Message_queue_MP_Send_response_packet(
0572     MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,
0573     mp_id,
0574     the_proxy
0575   );
0576 }
0577 
0578 /*
0579  *  _Message_queue_MP_Send_extract_proxy
0580  *
0581  */
0582 
0583 void _Message_queue_MP_Send_extract_proxy (
0584   Thread_Control *the_thread,
0585   Objects_Id      id
0586 )
0587 {
0588   _Message_queue_MP_Send_process_packet(
0589     MESSAGE_QUEUE_MP_EXTRACT_PROXY,
0590     id,
0591     (rtems_name) 0,
0592     the_thread->Object.id
0593   );
0594 }
0595 
0596 void  _Message_queue_Core_message_queue_mp_support(
0597   Thread_Control *the_thread,
0598   Objects_Id      id
0599 )
0600 {
0601   the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
0602 
0603   _Message_queue_MP_Send_response_packet(
0604     MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,
0605     id,
0606     the_thread
0607   );
0608 }
0609 
0610 static void _Message_queue_MP_Initialize( void )
0611 {
0612   _MPCI_Register_packet_processor(
0613     MP_PACKET_MESSAGE_QUEUE,
0614     _Message_queue_MP_Process_packet
0615   );
0616 }
0617 
0618 RTEMS_SYSINIT_ITEM(
0619   _Message_queue_MP_Initialize,
0620   RTEMS_SYSINIT_CLASSIC_MESSAGE_QUEUE_MP,
0621   RTEMS_SYSINIT_ORDER_MIDDLE
0622 );