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 RTEMSImplClassicTaskMP
0007  *
0008  * @brief This source file contains the implementation to support the Task
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/tasksimpl.h>
0043 #include <rtems/rtems/optionsimpl.h>
0044 #include <rtems/rtems/statusimpl.h>
0045 #include <rtems/score/statesimpl.h>
0046 #include <rtems/score/threadimpl.h>
0047 #include <rtems/score/threadqimpl.h>
0048 #include <rtems/sysinit.h>
0049 
0050 /**
0051  *  The following data structure defines the packet used to perform
0052  *  remote task operations.
0053  */
0054 typedef struct {
0055   rtems_packet_prefix               Prefix;
0056   RTEMS_tasks_MP_Remote_operations  operation;
0057   rtems_name                        name;
0058   rtems_task_priority               the_priority;
0059 }   RTEMS_tasks_MP_Packet;
0060 
0061 RTEMS_STATIC_ASSERT(
0062   sizeof(RTEMS_tasks_MP_Packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
0063   RTEMS_tasks_MP_Packet
0064 );
0065 
0066 static RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_packet( void )
0067 {
0068   return (RTEMS_tasks_MP_Packet *) _MPCI_Get_packet();
0069 }
0070 
0071 static RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_request_packet(
0072   Objects_Id id
0073 )
0074 {
0075   if ( !_Thread_MP_Is_remote( id ) ) {
0076     return NULL;
0077   }
0078 
0079   return _RTEMS_tasks_MP_Get_packet();
0080 }
0081 
0082 /*
0083  *  _RTEMS_tasks_MP_Send_process_packet
0084  *
0085  */
0086 
0087 void _RTEMS_tasks_MP_Send_process_packet (
0088   RTEMS_tasks_MP_Remote_operations operation,
0089   Objects_Id                       task_id,
0090   rtems_name                       name
0091 )
0092 {
0093   RTEMS_tasks_MP_Packet *the_packet;
0094 
0095   switch ( operation ) {
0096 
0097     case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
0098     case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
0099 
0100       the_packet                    = _RTEMS_tasks_MP_Get_packet();
0101       the_packet->Prefix.the_class  = MP_PACKET_TASKS;
0102       the_packet->Prefix.length     = sizeof ( RTEMS_tasks_MP_Packet );
0103       the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet );
0104       the_packet->operation         = operation;
0105       the_packet->Prefix.id         = task_id;
0106       the_packet->name              = name;
0107 
0108       _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
0109       break;
0110 
0111     case RTEMS_TASKS_MP_SUSPEND_REQUEST:
0112     case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
0113     case RTEMS_TASKS_MP_RESUME_REQUEST:
0114     case RTEMS_TASKS_MP_RESUME_RESPONSE:
0115     case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
0116     case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
0117       break;
0118   }
0119 }
0120 
0121 static rtems_status_code _RTEMS_tasks_MP_Send_request_packet(
0122   RTEMS_tasks_MP_Packet            *the_packet,
0123   Objects_Id                        id,
0124   RTEMS_tasks_MP_Remote_operations  operation
0125 )
0126 {
0127   Status_Control status;
0128 
0129   the_packet->Prefix.the_class  = MP_PACKET_TASKS;
0130   the_packet->Prefix.length     = sizeof( *the_packet );
0131   the_packet->Prefix.to_convert = sizeof( *the_packet );
0132   the_packet->Prefix.id         = id;
0133   the_packet->operation         = operation;
0134 
0135   status = _MPCI_Send_request_packet(
0136     _Objects_Get_node( id ),
0137     &the_packet->Prefix,
0138     STATES_READY /* Not used */
0139   );
0140   return _Status_Get( status );
0141 }
0142 
0143 rtems_status_code _RTEMS_tasks_MP_Set_priority(
0144   rtems_id             id,
0145   rtems_task_priority  new_priority,
0146   rtems_task_priority *old_priority
0147 )
0148 {
0149   RTEMS_tasks_MP_Packet *the_packet;
0150 
0151   the_packet = _RTEMS_tasks_MP_Get_request_packet( id );
0152   if ( the_packet == NULL ) {
0153     return RTEMS_INVALID_ID;
0154   }
0155 
0156   the_packet->the_priority = new_priority;
0157   _Thread_Executing->Wait.return_argument = old_priority;
0158   return _RTEMS_tasks_MP_Send_request_packet(
0159     the_packet,
0160     id,
0161     RTEMS_TASKS_MP_SET_PRIORITY_REQUEST
0162   );
0163 }
0164 
0165 rtems_status_code _RTEMS_tasks_MP_Suspend( rtems_id id )
0166 {
0167   RTEMS_tasks_MP_Packet *the_packet;
0168 
0169   the_packet = _RTEMS_tasks_MP_Get_request_packet( id );
0170   if ( the_packet == NULL ) {
0171     return RTEMS_INVALID_ID;
0172   }
0173 
0174   return _RTEMS_tasks_MP_Send_request_packet(
0175     the_packet,
0176     id,
0177     RTEMS_TASKS_MP_SUSPEND_REQUEST
0178   );
0179 }
0180 
0181 rtems_status_code _RTEMS_tasks_MP_Resume( rtems_id id )
0182 {
0183   RTEMS_tasks_MP_Packet *the_packet;
0184 
0185   the_packet = _RTEMS_tasks_MP_Get_request_packet( id );
0186   if ( the_packet == NULL ) {
0187     return RTEMS_INVALID_ID;
0188   }
0189 
0190   return _RTEMS_tasks_MP_Send_request_packet(
0191     the_packet,
0192     id,
0193     RTEMS_TASKS_MP_RESUME_REQUEST
0194   );
0195 }
0196 
0197 /*
0198  *  _RTEMS_tasks_MP_Send_response_packet
0199  *
0200  */
0201 
0202 static void _RTEMS_tasks_MP_Send_response_packet (
0203   RTEMS_tasks_MP_Remote_operations  operation,
0204   Thread_Control                   *the_thread
0205 )
0206 {
0207   RTEMS_tasks_MP_Packet *the_packet;
0208 
0209   switch ( operation ) {
0210 
0211     case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
0212     case RTEMS_TASKS_MP_RESUME_RESPONSE:
0213     case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
0214 
0215       the_packet = (RTEMS_tasks_MP_Packet *) the_thread->receive_packet;
0216 
0217 /*
0218  *  The packet being returned already contains the class, length, and
0219  *  to_convert fields, therefore they are not set in this routine.
0220  */
0221       the_packet->operation    = operation;
0222       the_packet->Prefix.id    = the_packet->Prefix.source_tid;
0223 
0224       _MPCI_Send_response_packet(
0225         _Objects_Get_node( the_packet->Prefix.source_tid ),
0226         &the_packet->Prefix
0227       );
0228       break;
0229 
0230     case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
0231     case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
0232     case RTEMS_TASKS_MP_SUSPEND_REQUEST:
0233     case RTEMS_TASKS_MP_RESUME_REQUEST:
0234     case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
0235       break;
0236 
0237   }
0238 }
0239 
0240 /*
0241  *
0242  *  _RTEMS_tasks_MP_Process_packet
0243  *
0244  */
0245 
0246 static void _RTEMS_tasks_MP_Process_packet (
0247   rtems_packet_prefix  *the_packet_prefix
0248 )
0249 {
0250   RTEMS_tasks_MP_Packet *the_packet;
0251   Thread_Control   *the_thread;
0252 
0253   the_packet = (RTEMS_tasks_MP_Packet *) the_packet_prefix;
0254 
0255   switch ( the_packet->operation ) {
0256 
0257     case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
0258 
0259       _Objects_MP_Allocate_and_open(
0260         &_RTEMS_tasks_Information.Objects,
0261         the_packet->name,
0262         the_packet->Prefix.id,
0263         true
0264       );
0265 
0266       _MPCI_Return_packet( the_packet_prefix );
0267       break;
0268 
0269     case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
0270 
0271       _Objects_MP_Close(
0272         &_RTEMS_tasks_Information.Objects,
0273         the_packet->Prefix.id
0274       );
0275 
0276       _MPCI_Return_packet( the_packet_prefix );
0277       break;
0278 
0279     case RTEMS_TASKS_MP_SUSPEND_REQUEST:
0280 
0281       the_packet->Prefix.return_code = rtems_task_suspend(
0282         the_packet->Prefix.id
0283       );
0284 
0285       _RTEMS_tasks_MP_Send_response_packet(
0286         RTEMS_TASKS_MP_SUSPEND_RESPONSE,
0287         _Thread_Executing
0288       );
0289       break;
0290 
0291     case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
0292     case RTEMS_TASKS_MP_RESUME_RESPONSE:
0293 
0294       the_thread = _MPCI_Process_response( the_packet_prefix );
0295 
0296       _MPCI_Return_packet( the_packet_prefix );
0297       break;
0298 
0299     case RTEMS_TASKS_MP_RESUME_REQUEST:
0300 
0301       the_packet->Prefix.return_code = rtems_task_resume(
0302         the_packet->Prefix.id
0303       );
0304 
0305       _RTEMS_tasks_MP_Send_response_packet(
0306         RTEMS_TASKS_MP_RESUME_RESPONSE,
0307         _Thread_Executing
0308       );
0309       break;
0310 
0311     case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
0312 
0313       the_packet->Prefix.return_code = rtems_task_set_priority(
0314         the_packet->Prefix.id,
0315         the_packet->the_priority,
0316         &the_packet->the_priority
0317       );
0318 
0319       _RTEMS_tasks_MP_Send_response_packet(
0320         RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE,
0321         _Thread_Executing
0322       );
0323       break;
0324 
0325     case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
0326 
0327       the_thread = _MPCI_Process_response( the_packet_prefix );
0328 
0329       *(rtems_task_priority *)the_thread->Wait.return_argument =
0330                                                the_packet->the_priority;
0331 
0332       _MPCI_Return_packet( the_packet_prefix );
0333       break;
0334   }
0335 }
0336 
0337 static void _RTEMS_tasks_MP_Initialize( void )
0338 {
0339   _MPCI_Register_packet_processor(
0340     MP_PACKET_TASKS,
0341     _RTEMS_tasks_MP_Process_packet
0342   );
0343 }
0344 
0345 RTEMS_SYSINIT_ITEM(
0346   _RTEMS_tasks_MP_Initialize,
0347   RTEMS_SYSINIT_CLASSIC_TASKS_MP,
0348   RTEMS_SYSINIT_ORDER_MIDDLE
0349 );