Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief RTEMS Monitor "object" support.
0007  *
0008  * Used to traverse object lists and print them out.
0009  * An object can be an RTEMS object (chain based stuff) or
0010  * a "misc" object such as a device driver.
0011  *
0012  * Each object has its own file in this directory (eg: extension.c)
0013  * That file provides routines to convert a "native" structure
0014  * to its canonical form, print a canonical structure, etc.
0015  *
0016  * TODO:
0017  *     should allow for non-numeric id's???
0018  */
0019 
0020 /*
0021  * COPYRIGHT (c) 1989-2022. On-Line Applications Research Corporation (OAR).
0022  *
0023  * Redistribution and use in source and binary forms, with or without
0024  * modification, are permitted provided that the following conditions
0025  * are met:
0026  * 1. Redistributions of source code must retain the above copyright
0027  *    notice, this list of conditions and the following disclaimer.
0028  * 2. Redistributions in binary form must reproduce the above copyright
0029  *    notice, this list of conditions and the following disclaimer in the
0030  *    documentation and/or other materials provided with the distribution.
0031  *
0032  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0033  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0034  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0035  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0036  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0037  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0038  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0039  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0040  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0041  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0042  * POSSIBILITY OF SUCH DAMAGE.
0043  */
0044 
0045 #ifdef HAVE_CONFIG_H
0046 #include "config.h"
0047 #endif
0048 
0049 #include <rtems.h>
0050 #include <rtems/monitor.h>
0051 #include <rtems/extensionimpl.h>
0052 #include <rtems/rtems/messageimpl.h>
0053 #include <rtems/rtems/partimpl.h>
0054 #include <rtems/rtems/regionimpl.h>
0055 #include <rtems/rtems/semimpl.h>
0056 #include <rtems/rtems/tasksimpl.h>
0057 #include <rtems/posix/pthreadimpl.h>
0058 
0059 #include <stdio.h>
0060 #include <stdlib.h>             /* strtoul() */
0061 #include <string.h>             /* memcpy() */
0062 
0063 #define NUMELEMS(arr)   (sizeof(arr) / sizeof(arr[0]))
0064 
0065 /*
0066  * add:
0067  *     next
0068  */
0069 
0070 static const rtems_monitor_object_info_t rtems_monitor_object_info[] =
0071 {
0072     { RTEMS_MONITOR_OBJECT_CONFIG,
0073       (void *) 0,
0074       sizeof(rtems_monitor_config_t),
0075       (rtems_monitor_object_next_fn)        rtems_monitor_config_next,
0076       (rtems_monitor_object_canonical_fn)   rtems_monitor_config_canonical,
0077       (rtems_monitor_object_dump_header_fn) rtems_monitor_config_dump_header,
0078       (rtems_monitor_object_dump_fn)        rtems_monitor_config_dump,
0079     },
0080     { RTEMS_MONITOR_OBJECT_MPCI,
0081       (void *) 0,
0082 #if defined(RTEMS_MULTIPROCESSING)
0083       sizeof(rtems_monitor_mpci_t),
0084       (rtems_monitor_object_next_fn)        rtems_monitor_mpci_next,
0085       (rtems_monitor_object_canonical_fn)   rtems_monitor_mpci_canonical,
0086       (rtems_monitor_object_dump_header_fn) rtems_monitor_mpci_dump_header,
0087       (rtems_monitor_object_dump_fn)        rtems_monitor_mpci_dump,
0088 #else
0089       0,
0090       (rtems_monitor_object_next_fn)        0,
0091       (rtems_monitor_object_canonical_fn)   0,
0092       (rtems_monitor_object_dump_header_fn) 0,
0093       (rtems_monitor_object_dump_fn)        0,
0094 #endif
0095     },
0096     { RTEMS_MONITOR_OBJECT_INIT_TASK,
0097       (void *) 0,
0098       sizeof(rtems_monitor_init_task_t),
0099       (rtems_monitor_object_next_fn)        rtems_monitor_init_task_next,
0100       (rtems_monitor_object_canonical_fn)   rtems_monitor_init_task_canonical,
0101       (rtems_monitor_object_dump_header_fn) rtems_monitor_init_task_dump_header,
0102       (rtems_monitor_object_dump_fn)        rtems_monitor_init_task_dump,
0103     },
0104     { RTEMS_MONITOR_OBJECT_TASK,
0105       (void *) &_RTEMS_tasks_Information.Objects,
0106       sizeof(rtems_monitor_task_t),
0107       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0108       (rtems_monitor_object_canonical_fn)   rtems_monitor_task_canonical,
0109       (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
0110       (rtems_monitor_object_dump_fn)        rtems_monitor_task_dump,
0111     },
0112     { RTEMS_MONITOR_OBJECT_QUEUE,
0113       (void *) &_Message_queue_Information,
0114       sizeof(rtems_monitor_queue_t),
0115       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0116       (rtems_monitor_object_canonical_fn)   rtems_monitor_queue_canonical,
0117       (rtems_monitor_object_dump_header_fn) rtems_monitor_queue_dump_header,
0118       (rtems_monitor_object_dump_fn)        rtems_monitor_queue_dump,
0119     },
0120     { RTEMS_MONITOR_OBJECT_SEMAPHORE,
0121       (void *) &_Semaphore_Information,
0122       sizeof(rtems_monitor_sema_t),
0123       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0124       (rtems_monitor_object_canonical_fn)   rtems_monitor_sema_canonical,
0125       (rtems_monitor_object_dump_header_fn) rtems_monitor_sema_dump_header,
0126       (rtems_monitor_object_dump_fn)        rtems_monitor_sema_dump,
0127     },
0128     { RTEMS_MONITOR_OBJECT_REGION,
0129       (void *) &_Region_Information,
0130       sizeof(rtems_monitor_region_t),
0131       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0132       (rtems_monitor_object_canonical_fn)   rtems_monitor_region_canonical,
0133       (rtems_monitor_object_dump_header_fn) rtems_monitor_region_dump_header,
0134       (rtems_monitor_object_dump_fn)        rtems_monitor_region_dump,
0135     },
0136     { RTEMS_MONITOR_OBJECT_PARTITION,
0137       (void *) &_Partition_Information,
0138       sizeof(rtems_monitor_part_t),
0139       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0140       (rtems_monitor_object_canonical_fn)   rtems_monitor_part_canonical,
0141       (rtems_monitor_object_dump_header_fn) rtems_monitor_part_dump_header,
0142       (rtems_monitor_object_dump_fn)        rtems_monitor_part_dump,
0143     },
0144     { RTEMS_MONITOR_OBJECT_EXTENSION,
0145       (void *) &_Extension_Information,
0146       sizeof(rtems_monitor_extension_t),
0147       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0148       (rtems_monitor_object_canonical_fn)   rtems_monitor_extension_canonical,
0149       (rtems_monitor_object_dump_header_fn) rtems_monitor_extension_dump_header,
0150       (rtems_monitor_object_dump_fn)        rtems_monitor_extension_dump,
0151     },
0152     { RTEMS_MONITOR_OBJECT_DRIVER,
0153       (void *) 0,
0154       sizeof(rtems_monitor_driver_t),
0155       (rtems_monitor_object_next_fn)        rtems_monitor_driver_next,
0156       (rtems_monitor_object_canonical_fn)   rtems_monitor_driver_canonical,
0157       (rtems_monitor_object_dump_header_fn) rtems_monitor_driver_dump_header,
0158       (rtems_monitor_object_dump_fn)        rtems_monitor_driver_dump,
0159     },
0160     { RTEMS_MONITOR_OBJECT_PTHREAD,
0161       (void *) &_POSIX_Threads_Information.Objects,
0162       sizeof(rtems_monitor_task_t),
0163       (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
0164       (rtems_monitor_object_canonical_fn)   rtems_monitor_task_canonical,
0165       (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
0166       (rtems_monitor_object_dump_fn)        rtems_monitor_task_dump,
0167     }
0168 };
0169 
0170 /*
0171  * Allow id's to be specified without the node number or
0172  * type for convenience.
0173  */
0174 
0175 rtems_id
0176 rtems_monitor_id_fixup(
0177     rtems_id            id,
0178     uint32_t            default_node,
0179     rtems_monitor_object_type_t type
0180 )
0181 {
0182     uint32_t    node;
0183 
0184     node = rtems_object_id_get_node(id);
0185     if (node == 0)
0186     {
0187         if (rtems_object_id_get_class(id) != OBJECTS_CLASSIC_NO_CLASS)
0188             type = rtems_object_id_get_class(id);
0189 
0190         id = rtems_build_id(
0191           OBJECTS_CLASSIC_API,
0192           type,
0193           default_node,
0194           rtems_object_id_get_index(id)
0195         );
0196     }
0197     return id;
0198 }
0199 
0200 
0201 const rtems_monitor_object_info_t *
0202 rtems_monitor_object_lookup(
0203     rtems_monitor_object_type_t type
0204 )
0205 {
0206     const rtems_monitor_object_info_t *p;
0207     for (p = &rtems_monitor_object_info[0];
0208          p < &rtems_monitor_object_info[NUMELEMS(rtems_monitor_object_info)];
0209          p++)
0210     {
0211         if (p->type == type)
0212             return p;
0213     }
0214     return 0;
0215 }
0216 
0217 #if defined(RTEMS_MULTIPROCESSING)
0218 static rtems_id
0219 rtems_monitor_object_canonical_next_remote(
0220     rtems_monitor_object_type_t type,
0221     rtems_id            id,
0222     void               *canonical
0223 )
0224 {
0225     rtems_id                        next_id;
0226     rtems_status_code               status;
0227     rtems_monitor_server_request_t  request;
0228     rtems_monitor_server_response_t response;
0229 
0230     /*
0231      * Send request
0232      */
0233 
0234     request.command = RTEMS_MONITOR_SERVER_CANONICAL;
0235     request.argument0 = (uint32_t) type;
0236     request.argument1 = (uint32_t) id;
0237 
0238     status = rtems_monitor_server_request(
0239       rtems_object_id_get_node(id), &request, &response);
0240     if (status != RTEMS_SUCCESSFUL)
0241         goto failed;
0242 
0243     /*
0244      * process response
0245      */
0246 
0247     next_id = (rtems_id) response.result0;
0248     if (next_id != RTEMS_OBJECT_ID_FINAL)
0249         (void) memcpy(canonical, &response.payload, response.result1);
0250 
0251     return next_id;
0252 
0253 failed:
0254     return RTEMS_OBJECT_ID_FINAL;
0255 
0256 }
0257 #endif
0258 
0259 
0260 rtems_id
0261 rtems_monitor_object_canonical_next(
0262     const rtems_monitor_object_info_t *info,
0263     rtems_id                     id,
0264     void                        *canonical
0265 )
0266 {
0267   rtems_id    next_id;
0268   const void *raw_item;
0269 
0270 #if defined(RTEMS_MULTIPROCESSING)
0271     if ( ! _Objects_Is_local_id(id) ) {
0272        next_id = rtems_monitor_object_canonical_next_remote(
0273          info->type,
0274          id,
0275          canonical
0276       );
0277     } else
0278 #endif
0279     {
0280       next_id = id;
0281 
0282       raw_item = info->next(
0283         info->object_information,
0284         canonical,
0285         &next_id
0286       );
0287 
0288      if (raw_item) {
0289        info->canonical(canonical, raw_item);
0290        _Objects_Allocator_unlock();
0291      }
0292   }
0293   return next_id;
0294 }
0295 
0296 
0297 /*
0298  * this is routine server invokes locally to get the type
0299  */
0300 
0301 rtems_id
0302 rtems_monitor_object_canonical_get(
0303     rtems_monitor_object_type_t  type,
0304     rtems_id             id,
0305     void                *canonical,
0306     size_t              *size_p
0307 )
0308 {
0309     const rtems_monitor_object_info_t *info;
0310     rtems_id                     next_id;
0311 
0312     *size_p = 0;
0313 
0314     info = rtems_monitor_object_lookup(type);
0315 
0316     if (info == 0)
0317         return RTEMS_OBJECT_ID_FINAL;
0318 
0319     next_id = rtems_monitor_object_canonical_next(info, id, canonical);
0320     *size_p = info->size;
0321 
0322     return next_id;
0323 }
0324 
0325 
0326 static void
0327 rtems_monitor_object_dump_1(
0328     const rtems_monitor_object_info_t *info,
0329     rtems_id                     id,
0330     bool                         verbose
0331 )
0332 {
0333     rtems_id next_id;
0334     rtems_monitor_union_t canonical;
0335 
0336     if ((next_id = rtems_monitor_object_canonical_next(
0337                                      info,
0338                                      id,
0339                                      &canonical)) != RTEMS_OBJECT_ID_FINAL)
0340     {
0341         /*
0342          * If the one we actually got is the one we wanted, then
0343          * print it out.
0344          * For ones that have an id field, this works fine,
0345          * for all others, always dump it out.
0346          *
0347          * HACK: the way we determine whether there is an id is a hack.
0348          *
0349          * by the way: the reason we try to not have an id, is that some
0350          *   of the canonical structures are almost too big for shared
0351          *   memory driver (eg: mpci)
0352          */
0353 
0354         if ((info->next != rtems_monitor_manager_next) ||
0355             (id == canonical.generic.id))
0356             info->dump(&canonical, verbose);
0357     }
0358 }
0359 
0360 static void
0361 rtems_monitor_object_dump_all(
0362     const rtems_monitor_object_info_t *info,
0363     bool                         verbose
0364 )
0365 {
0366     rtems_id next_id;
0367     rtems_monitor_union_t canonical;
0368 
0369     next_id = RTEMS_OBJECT_ID_INITIAL(OBJECTS_CLASSIC_API, info->type, rtems_monitor_default_node);
0370 
0371     while ((next_id = rtems_monitor_object_canonical_next(
0372                                          info,
0373                                          next_id,
0374                                          &canonical)) != RTEMS_OBJECT_ID_FINAL)
0375     {
0376         info->dump(&canonical, verbose);
0377     }
0378 }
0379 
0380 void
0381 rtems_monitor_object_cmd(
0382     int                                argc,
0383     char                             **argv,
0384     const rtems_monitor_command_arg_t *command_arg,
0385     bool                               verbose
0386 )
0387 {
0388     int arg;
0389     const rtems_monitor_object_info_t *info = 0;
0390     rtems_monitor_object_type_t  type;
0391 
0392     /* what is the default type? */
0393     type = command_arg->monitor_object;
0394 
0395     if (argc == 1)
0396     {
0397         if (type == RTEMS_MONITOR_OBJECT_INVALID)
0398         {
0399             fprintf(stdout,"A type must be specified to \"dump all\"\n");
0400             goto done;
0401         }
0402 
0403         info = rtems_monitor_object_lookup(type);
0404         if (info == 0)
0405             goto not_found;
0406 
0407         if (info->dump_header)
0408             info->dump_header(verbose);
0409         rtems_monitor_object_dump_all(info, verbose);
0410     }
0411     else
0412     {
0413         uint32_t            default_node = rtems_monitor_default_node;
0414         rtems_monitor_object_type_t last_type = RTEMS_MONITOR_OBJECT_INVALID;
0415         rtems_id            id;
0416 
0417         for (arg=1; argv[arg]; arg++)
0418         {
0419             id = (rtems_id) strtoul(argv[arg], 0, 16);
0420             id = rtems_monitor_id_fixup(id, default_node, type);
0421             type = (rtems_monitor_object_type_t) rtems_object_id_get_class(id);
0422 
0423             /*
0424              * Allow the item type to change in the middle
0425              * of the command.  If the type changes, then
0426              * just dump out a new header and keep on going.
0427              */
0428             if (type != last_type)
0429             {
0430                 info = rtems_monitor_object_lookup(type);
0431                 if (info == 0)
0432                     goto not_found;
0433 
0434                 if (info->dump_header)
0435                     info->dump_header(verbose);
0436             }
0437 
0438             if (info == 0)
0439             {
0440 not_found:      fprintf(stdout,"Invalid or unsupported type %d\n", type);
0441                 goto done;
0442             }
0443 
0444             rtems_monitor_object_dump_1(info, id, verbose);
0445 
0446             default_node = rtems_object_id_get_node(id);
0447 
0448             last_type = type;
0449         }
0450     }
0451 done:
0452     return;
0453 }