Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup rtems_bdpart
0007  *
0008  * @brief Enable the Monitor to Show bdbuf Information
0009  *
0010  * This module inspects the bdbuf data structures,
0011  * assuming they are static, but in fact they are used very
0012  * dynamically. Therefore the results show MAY BE INCORRECT in
0013  * some cases. And, to cure this a bit, this module may block
0014  * preemption for a rather long time and therefore it may
0015  * BREAK THE REALTIME BEHAVIOUR OF YOUR SYSTEM (when in use)
0016  */
0017 
0018 /*
0019  * Copyright (c) 2005 embedded brains GmbH & Co. KG
0020  * Redistribution and use in source and binary forms, with or without
0021  * modification, are permitted provided that the following conditions
0022  * are met:
0023  * 1. Redistributions of source code must retain the above copyright
0024  *    notice, this list of conditions and the following disclaimer.
0025  * 2. Redistributions in binary form must reproduce the above copyright
0026  *    notice, this list of conditions and the following disclaimer in the
0027  *    documentation and/or other materials provided with the distribution.
0028  *
0029  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0030  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0031  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0032  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0033  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0034  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0035  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0036  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0037  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0038  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0039  * POSSIBILITY OF SUCH DAMAGE.
0040  */
0041 
0042 #ifdef HAVE_CONFIG_H
0043 #include "config.h"
0044 #endif
0045 
0046 #include <rtems.h>
0047 #include <rtems/monitor.h>
0048 #include <rtems/bdbuf.h>
0049 #include <string.h>
0050 #include <ctype.h>
0051 #include <stdio.h>
0052 #include <rtems/libio.h>
0053 #include <inttypes.h>
0054 
0055 typedef struct {
0056   bool bdbuf_modified;
0057   bool bdbuf_in_progress;
0058   bool bdbuf_actual;
0059   bool bdbuf_used;
0060   bool bdbuf_all;
0061   rtems_bdpool_id pool_id;
0062 } show_bdbuf_filter_t;
0063 
0064 typedef struct {
0065   bool show_all;
0066   bool show_node_chain;
0067   bool show_dev;
0068   bool show_blocknum;
0069   bool show_error;
0070   bool show_state;
0071   bool show_use_count;
0072   bool show_pool_id;
0073   bool show_sema;
0074 } show_bdbuf_selector_t;
0075 
0076 typedef enum {bdbuf_chain_ident_none,
0077           bdbuf_chain_ident_free,
0078           bdbuf_chain_ident_lru,
0079           bdbuf_chain_ident_mod} bdbuf_chain_identifier_t;
0080 
0081 typedef struct {
0082   rtems_bdpool_id pool_id;
0083   int index;
0084   bdbuf_chain_identifier_t in_chain;
0085   dev_t dev;
0086   blkdev_bnum blknum;
0087   rtems_status_code status;
0088   int error;
0089   bool modified;
0090   bool in_progress;
0091   bool actual;
0092   int use_count;
0093   const CORE_mutex_Control *sema;
0094 } show_bdbuf_bdbuf_info_t;
0095 
0096 typedef rtems_mode preemption_key_t;
0097 #define DISABLE_PREEMPTION(key) \
0098     do {                                                               \
0099         rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &(key)); \
0100     } while (0)
0101 
0102 #define ENABLE_PREEMPTION(key) \
0103     do {                                                        \
0104         rtems_mode temp;                                        \
0105         rtems_task_mode((key), RTEMS_PREEMPT_MASK, &temp);      \
0106     } while (0)
0107 
0108 /*=========================================================================*\
0109 | Function:                                                                 |
0110 \*-------------------------------------------------------------------------*/
0111 rtems_status_code rtems_bdbuf_show_follow_chain_node_to_head
0112 (
0113 /*-------------------------------------------------------------------------*\
0114 | Purpose:                                                                  |
0115 |   follow a given chain to its head                                        |
0116 |   XXX: this is executed with preemption disabled                          |
0117 +---------------------------------------------------------------------------+
0118 | Input Parameters:                                                         |
0119 \*-------------------------------------------------------------------------*/
0120  const Chain_Node *the_node, /* input: node to track to its head  */
0121  Chain_Control **the_head    /* storage for pointer to chain head */
0122 )
0123 /*-------------------------------------------------------------------------*\
0124 | Return Value:                                                             |
0125 |    rtems_status_code                                                      |
0126 \*=========================================================================*/
0127 {
0128   rtems_status_code rc = RTEMS_SUCCESSFUL;
0129   preemption_key_t preempt_key;
0130   bool preempt_disabled = false;
0131   /*
0132    * disable preemption
0133    */
0134   if (rc == RTEMS_SUCCESSFUL) {
0135     DISABLE_PREEMPTION(preempt_key);
0136   }
0137   /*
0138    * follow node to its head
0139    * XXX: this is highly dependent on the chain implementation
0140    * in score/src/chain.c and friends
0141    */
0142   while (the_node->previous != NULL) {
0143     the_node = the_node->previous;
0144   }
0145   /*
0146    * reenable preemption, if disabled
0147    */
0148   if (preempt_disabled) {
0149     ENABLE_PREEMPTION(preempt_key);
0150   }
0151   /*
0152    * XXX: this depends n the chain implementation in
0153    * score/include/rtems/score/chain.h:
0154    * Chain_Control is overlayed by two Cohain_Nodes
0155    */
0156   *the_head = (Chain_Control *)the_node;
0157 
0158   return rc;
0159 }
0160 
0161 /*=========================================================================*\
0162 | Function:                                                                 |
0163 \*-------------------------------------------------------------------------*/
0164 rtems_status_code rtems_bdbuf_show_determine_chain_of_bdbuf
0165 (
0166 /*-------------------------------------------------------------------------*\
0167 | Purpose:                                                                  |
0168 |   find out, which chain this bdbuf is linked in                           |
0169 +---------------------------------------------------------------------------+
0170 | Input Parameters:                                                         |
0171 \*-------------------------------------------------------------------------*/
0172  const bdbuf_buffer *the_bdbuf,         /* this is the bdbuf structure     */
0173  const bdbuf_pool   *curr_pool,         /* the pool this buffer belongs to */
0174  bdbuf_chain_identifier_t *chn_ident    /* result: identifier for chain    */
0175 )
0176 /*-------------------------------------------------------------------------*\
0177 | Return Value:                                                             |
0178 |    rtems_status_code                                                      |
0179 \*=========================================================================*/
0180 {
0181   rtems_status_code rc = RTEMS_SUCCESSFUL;
0182   Chain_Control *the_chain_control;
0183 
0184 
0185   *chn_ident = bdbuf_chain_ident_none;
0186   if (rc == RTEMS_SUCCESSFUL) {
0187     rc = rtems_bdbuf_show_follow_chain_node_to_head(&(the_bdbuf->link),
0188                             &(the_chain_control));
0189   }
0190   if (rc == RTEMS_SUCCESSFUL) {
0191     if (the_chain_control == &(curr_pool->free)) {
0192       *chn_ident = bdbuf_chain_ident_free;
0193     }
0194     else if (the_chain_control == &(curr_pool->lru)) {
0195       *chn_ident = bdbuf_chain_ident_lru;
0196     }
0197     else if (the_chain_control == &(rtems_bdbuf_ctx.mod)) {
0198       *chn_ident = bdbuf_chain_ident_mod;
0199     }
0200   }
0201   return rc;
0202 }
0203 
0204 /*=========================================================================*\
0205 | Function:                                                                 |
0206 \*-------------------------------------------------------------------------*/
0207 rtems_status_code rtems_bdbuf_show_getargs
0208 (
0209 /*-------------------------------------------------------------------------*\
0210 | Purpose:                                                                  |
0211 |   analyze cmd arguments                                                   |
0212 +---------------------------------------------------------------------------+
0213 | Input Parameters:                                                         |
0214 \*-------------------------------------------------------------------------*/
0215     int     argc,
0216     char  **argv,
0217     show_bdbuf_filter_t *filter,
0218     show_bdbuf_selector_t *selector
0219 )
0220 /*-------------------------------------------------------------------------*\
0221 | Return Value:                                                             |
0222 |    rtems_status_code                                                      |
0223 \*=========================================================================*/
0224 {
0225   rtems_status_code sc = RTEMS_SUCCESSFUL;
0226   int arg_error = 0;
0227   int i;
0228   char *tmp_ptr;
0229   int nm_argc = 0;
0230   /*
0231    * set filter and selector to default
0232    */
0233   memset(filter,0,sizeof(*filter));
0234   filter->bdbuf_all  = true;
0235   memset(selector,0,sizeof(*selector));
0236   selector->show_all = true;
0237 
0238   /*
0239    * scan arguments
0240    */
0241   for (i = 1;
0242        (i < argc) && (arg_error == 0);
0243        i++) {
0244     if (argv[i][0] == '-') {
0245       /*
0246        * modifier arguments
0247        */
0248       switch(tolower(argv[i][1])) {
0249     /*
0250      * selection, which bdbufs to show
0251      */
0252       case 'm': /* only show bdbufs modified */
0253     filter->bdbuf_modified = true ;
0254     filter->bdbuf_all      = false;
0255     break;
0256       case 'i': /* only show bdbufs in progress*/
0257     filter->bdbuf_in_progress = true ;
0258     filter->bdbuf_all         = false;
0259     break;
0260       case 'v': /* only show bdbufs, which have valid data*/
0261     filter->bdbuf_actual   = true ;
0262     filter->bdbuf_all      = false;
0263     break;
0264       case 'u': /* only show bdbufs, which are in use */
0265     filter->bdbuf_used     = true ;
0266     filter->bdbuf_all      = false;
0267     break;
0268       case 'p': /* only show bdbufs, which belong to pool <n> */
0269     filter->pool_id = strtol(argv[i]+2,&tmp_ptr,0);
0270     if (tmp_ptr == argv[i]+2) { /* no conversion performed... */
0271       arg_error = i;
0272     }
0273     filter->bdbuf_all      = false;
0274     break;
0275     /*
0276      * selection, what fields to show
0277      */
0278       case 'n': /* show bdbuf node_chain */
0279     selector->show_node_chain = true ;
0280     selector->show_all        = false;
0281     break;
0282       case 'd': /* show device           */
0283     selector->show_dev        = true ;
0284     selector->show_all        = false;
0285     break;
0286       case 'b': /* show blocknum         */
0287     selector->show_blocknum   = true ;
0288     selector->show_all        = false;
0289     break;
0290       case 'e': /* show bdbuf error status */
0291     selector->show_error      = true ;
0292     selector->show_all        = false;
0293     break;
0294       case 's': /* show bdbuf state */
0295     selector->show_state      = true ;
0296     selector->show_all        = false;
0297     break;
0298       case 'c': /* show bdbuf use count */
0299     selector->show_use_count  = true ;
0300     selector->show_all        = false;
0301     break;
0302       case 'l': /* show bdbuf pool id   */
0303     selector->show_pool_id    = true ;
0304     selector->show_all        = false;
0305     break;
0306       case 't': /* show bdbuf transfer sema */
0307     selector->show_sema       = true ;
0308     break;
0309       default:
0310     arg_error = i;
0311     break;
0312       }
0313     }
0314     else {
0315       /*
0316        * non-modifier arguments
0317        */
0318       switch(++nm_argc) {
0319       default: /* no further arguments defined */
0320     arg_error = i;
0321     break;
0322       }
0323     }
0324   }
0325   if (arg_error) {
0326     printf("%s: unknown argument %s\n",argv[0],argv[arg_error]);
0327     sc = RTEMS_NOT_DEFINED;
0328   }
0329   return sc;
0330 }
0331 
0332 /*=========================================================================*\
0333 | Function:                                                                 |
0334 \*-------------------------------------------------------------------------*/
0335 rtems_status_code rtems_bdbuf_show_get_bufpool
0336 (
0337 /*-------------------------------------------------------------------------*\
0338 | Purpose:                                                                  |
0339 |   get buffer pool information                                             |
0340 |   XXX: this should be coupled closer to the bdbuf.c module               |
0341 +---------------------------------------------------------------------------+
0342 | Input Parameters:                                                         |
0343 \*-------------------------------------------------------------------------*/
0344  struct bdbuf_pool **pool_base_pptr,
0345  int *pool_cnt_ptr
0346 )
0347 /*-------------------------------------------------------------------------*\
0348 | Return Value:                                                             |
0349 |    rtems_status_code                                                      |
0350 \*=========================================================================*/
0351 {
0352   rtems_status_code rc = RTEMS_SUCCESSFUL;
0353 #if 0
0354   rtems_status_code pool_rc = RTEMS_SUCCESSFUL;
0355   struct bdbuf_pool *curr_pool,*pool_base, *pool_top;
0356   int pool_cnt;
0357   int pool_probe_size;
0358   /*
0359    * get first buffer pool
0360    * XXX: this is highly dependent on how pools are defined
0361    * and maintained in bdbuf.c
0362    */
0363   if (rc == RTEMS_SUCCESSFUL) {
0364     /*
0365      * try all possible pool sizes, get highest/lowest pool address
0366      */
0367     pool_base = NULL;
0368     pool_top  = NULL;
0369     curr_pool = NULL;
0370     for (pool_probe_size = 1;
0371      pool_probe_size < (INT_MAX>>1) && (pool_rc == RTEMS_SUCCESSFUL);
0372      pool_probe_size <<= 1) {
0373       pool_rc = rtems_bdbuf_find_pool(pool_probe_size,&curr_pool);
0374       if (pool_rc == RTEMS_SUCCESSFUL) {
0375     if (pool_base > curr_pool) {
0376       pool_base = curr_pool;
0377     }
0378     if (pool_top < curr_pool) {
0379       pool_top = curr_pool;
0380     }
0381       }
0382     }
0383     if (pool_base == NULL) {
0384       rc = RTEMS_UNSATISFIED;
0385     }
0386     else {
0387       pool_cnt = (pool_top - pool_base) + 1;
0388     }
0389   }
0390   if (rc == RTEMS_SUCCESSFUL) {
0391     *pool_base_pptr = pool_base;
0392     *pool_cnt_ptr   = pool_cnt;
0393   }
0394 #else
0395   if (rc == RTEMS_SUCCESSFUL) {
0396     *pool_base_pptr = rtems_bdbuf_ctx.pool;
0397     *pool_cnt_ptr   = rtems_bdbuf_ctx.npools;
0398   }
0399 #endif
0400   return rc;
0401 }
0402 
0403 /*=========================================================================*\
0404 | Function:                                                                 |
0405 \*-------------------------------------------------------------------------*/
0406 rtems_status_code rtems_bdbuf_show_pool_header
0407 (
0408 /*-------------------------------------------------------------------------*\
0409 | Purpose:                                                                  |
0410 |   print buffer pool information                                           |
0411 +---------------------------------------------------------------------------+
0412 | Input Parameters:                                                         |
0413 \*-------------------------------------------------------------------------*/
0414  int        pool_idx,
0415  bdbuf_pool *pool_ptr
0416 )
0417 /*-------------------------------------------------------------------------*\
0418 | Return Value:                                                             |
0419 |    rtems_status_code                                                      |
0420 \*=========================================================================*/
0421 {
0422 
0423   rtems_status_code rc = RTEMS_SUCCESSFUL;
0424 
0425   if (rc == RTEMS_SUCCESSFUL) {
0426     printf("------------------------------------------------------------------------------\n");
0427     printf(" pool #%03d: blksize=%5u nblks=%5u buf_mem=0x%08" PRIxPTR " bdbuf_mem=0x%08" PRIxPTR "\n",
0428        pool_idx,
0429        pool_ptr->blksize,
0430        pool_ptr->nblks,
0431        (intptr_t) pool_ptr->mallocd_bufs,
0432        (intptr_t) pool_ptr->bdbufs);
0433     printf("------------------------------------------------------------------------------\n");
0434   }
0435   return rc;
0436 }
0437 
0438 /*=========================================================================*\
0439 | Function:                                                                 |
0440 \*-------------------------------------------------------------------------*/
0441 rtems_status_code rtems_show_bdbuf_get_bdbuf_info
0442 (
0443 /*-------------------------------------------------------------------------*\
0444 | Purpose:                                                                  |
0445 |   get buffer pool information                                             |
0446 |   XXX: this should be coupled closer to the bdbuf.c module                |
0447 +---------------------------------------------------------------------------+
0448 | Input Parameters:                                                         |
0449 \*-------------------------------------------------------------------------*/
0450  const bdbuf_buffer *the_bdbuf,         /* this is the bdbuf structure     */
0451  int           bdbuf_idx,               /* index of bdbuf                  */
0452  const bdbuf_pool   *curr_pool,         /* the pool this buffer belongs to */
0453  show_bdbuf_bdbuf_info_t *bdbuf_info    /* struct to  store info of bdbuf */
0454 )
0455 /*-------------------------------------------------------------------------*\
0456 | Return Value:                                                             |
0457 |    rtems_status_code                                                      |
0458 \*=========================================================================*/
0459 {
0460 
0461   rtems_status_code rc = RTEMS_SUCCESSFUL;
0462 
0463   /*
0464    * determine the chain we are in
0465    */
0466   if (rc == RTEMS_SUCCESSFUL) {
0467     rc = rtems_bdbuf_show_determine_chain_of_bdbuf(the_bdbuf,curr_pool,
0468         &(bdbuf_info->in_chain));
0469     if (rc != RTEMS_SUCCESSFUL) {
0470       bdbuf_info->in_chain = bdbuf_chain_ident_none;
0471       rc = RTEMS_SUCCESSFUL;
0472     }
0473   }
0474 
0475   if (rc == RTEMS_SUCCESSFUL) {
0476     bdbuf_info->index       = bdbuf_idx;
0477     bdbuf_info->dev         = the_bdbuf->dev;
0478     bdbuf_info->blknum      = the_bdbuf->block;
0479     bdbuf_info->status      = the_bdbuf->status;
0480     bdbuf_info->error       = the_bdbuf->error;
0481     bdbuf_info->modified    = the_bdbuf->modified;
0482     bdbuf_info->in_progress = the_bdbuf->in_progress;
0483     bdbuf_info->actual      = the_bdbuf->actual;
0484     bdbuf_info->use_count   = the_bdbuf->use_count;
0485     bdbuf_info->sema        = &(the_bdbuf->transfer_sema);
0486     bdbuf_info->pool_id     = the_bdbuf->pool;
0487   }
0488   return rc;
0489 }
0490 
0491 /*=========================================================================*\
0492 | Function:                                                                 |
0493 \*-------------------------------------------------------------------------*/
0494 rtems_status_code rtems_show_bdbuf_match_filter
0495 (
0496 /*-------------------------------------------------------------------------*\
0497 | Purpose:                                                                  |
0498 |   match bdbuf info with given filter                                      |
0499 +---------------------------------------------------------------------------+
0500 | Input Parameters:                                                         |
0501 \*-------------------------------------------------------------------------*/
0502  const show_bdbuf_bdbuf_info_t *bdbuf_info, /* struct to  store info of bdbuf */
0503  const show_bdbuf_filter_t *filter,
0504  bool *is_match
0505 )
0506 /*-------------------------------------------------------------------------*\
0507 | Return Value:                                                             |
0508 |    rtems_status_code                                                      |
0509 \*=========================================================================*/
0510 {
0511 
0512   rtems_status_code rc = RTEMS_SUCCESSFUL;
0513   bool unmatch = false;
0514 
0515   if (rc == RTEMS_SUCCESSFUL) {
0516     if (filter->bdbuf_all) {
0517       unmatch = false;
0518     }
0519     else {
0520       unmatch = ((filter->bdbuf_modified    && !bdbuf_info->modified) ||
0521          (filter->bdbuf_in_progress && !bdbuf_info->in_progress) ||
0522          (filter->bdbuf_actual      && !bdbuf_info->actual) ||
0523          (filter->bdbuf_used        && !(bdbuf_info->use_count > 0)));
0524 
0525     }
0526     *is_match = !unmatch;
0527   }
0528   return rc;
0529 }
0530 
0531 /*=========================================================================*\
0532 | Function:                                                                 |
0533 \*-------------------------------------------------------------------------*/
0534 rtems_status_code rtems_show_bdbuf_print_wait_chain
0535 (
0536 /*-------------------------------------------------------------------------*\
0537 | Purpose:                                                                  |
0538 |   list tasks waiting in "transfer_sema" chain                             |
0539 +---------------------------------------------------------------------------+
0540 | Input Parameters:                                                         |
0541 \*-------------------------------------------------------------------------*/
0542  bdbuf_buffer *the_bdbuf                /* this is the bdbuf structure     */
0543 )
0544 /*-------------------------------------------------------------------------*\
0545 | Return Value:                                                             |
0546 |    rtems_status_code                                                      |
0547 \*=========================================================================*/
0548 {
0549   rtems_status_code rc = RTEMS_SUCCESSFUL;
0550   Chain_Control *the_chain_head;
0551   const Chain_Node    *the_chain_node;
0552   int   thread_cnt = 0;
0553   const Thread_Control *the_thread;
0554   Objects_Id      thread_id;
0555   Objects_Name    thread_name;
0556   uint32_t        thread_name_nonstring;
0557   /*
0558    * get head of (fifo) wait chain
0559    */
0560   if (rc == RTEMS_SUCCESSFUL) {
0561     the_chain_head = &(the_bdbuf->transfer_sema.Wait_queue.Queues.Fifo);
0562     the_chain_node = _Chain_First(the_chain_head);
0563   }
0564   /*
0565    * walk through thread chain
0566    */
0567   while ((rc == RTEMS_SUCCESSFUL) &&
0568      (the_chain_node != _Chain_Tail( the_chain_head ))) {
0569     thread_cnt++;
0570     the_thread = (const Thread_Control *)the_chain_node;
0571 
0572     thread_id   = the_thread->Object.id;
0573     thread_name = the_thread->Object.name;
0574     thread_name_nonstring = (uint32_t)thread_name.name_u32;
0575     printf("%20s %3d (0x%08" PRIx32 ") %c%c%c%c\n",
0576        ((thread_cnt == 1) ? "Threads waiting:" : ""),
0577        thread_cnt,thread_id,
0578        (char)((thread_name_nonstring >> 24) & 0xff),
0579        (char)((thread_name_nonstring >> 16) & 0xff),
0580        (char)((thread_name_nonstring >>  8) & 0xff),
0581        (char)((thread_name_nonstring >>  0) & 0xff));
0582 
0583     the_chain_node = the_chain_node->next;
0584   }
0585 
0586   return rc;
0587 }
0588 
0589 /*=========================================================================*\
0590 | Function:                                                                 |
0591 \*-------------------------------------------------------------------------*/
0592 rtems_status_code rtems_show_bdbuf_print
0593 (
0594 /*-------------------------------------------------------------------------*\
0595 | Purpose:                                                                  |
0596 |   print requested bdbuffer information                                    |
0597 +---------------------------------------------------------------------------+
0598 | Input Parameters:                                                         |
0599 \*-------------------------------------------------------------------------*/
0600  const show_bdbuf_bdbuf_info_t *bdbuf_info, /* info of bdbuf               */
0601  show_bdbuf_selector_t * selector,          /* selector, what to show      */
0602  bool       print_header             /* true: print header, not info    */
0603 )
0604 /*-------------------------------------------------------------------------*\
0605 | Return Value:                                                             |
0606 |    rtems_status_code                                                      |
0607 \*=========================================================================*/
0608 {
0609 
0610   rtems_status_code rc = RTEMS_SUCCESSFUL;
0611 
0612   /*
0613    * 6 chars: print index of buffer
0614    */
0615   if (rc == RTEMS_SUCCESSFUL) {
0616     if (print_header) {
0617       printf("INDEX ");
0618     }
0619     else {
0620       printf("%5u ",bdbuf_info->index);
0621     }
0622   }
0623   /*
0624    * 3 chars: print info about the pool id of this buffer
0625    */
0626   if ((rc == RTEMS_SUCCESSFUL) &&
0627       ((selector->show_all) ||
0628        (selector->show_use_count))) {
0629     if (print_header) {
0630       printf("PL ");
0631     }
0632     else {
0633       printf("%2u ",bdbuf_info->pool_id);
0634     }
0635   }
0636 
0637   /*
0638    * 4 chars: print info about chain (lru/free/mod) of this buffer
0639    */
0640   if ((rc == RTEMS_SUCCESSFUL) &&
0641       ((selector->show_all) ||
0642        (selector->show_node_chain))) {
0643     if (print_header) {
0644       printf("CHN ");
0645     }
0646     else {
0647       printf("%3s ",
0648          ((bdbuf_info->in_chain == bdbuf_chain_ident_free)  ? "FRE"
0649           : (bdbuf_info->in_chain == bdbuf_chain_ident_lru) ? "LRU"
0650           : (bdbuf_info->in_chain == bdbuf_chain_ident_mod) ? "MOD"
0651           : "???"));
0652     }
0653   }
0654 
0655   /*
0656    * 7 chars: print info about device of this buffer
0657    */
0658   if ((rc == RTEMS_SUCCESSFUL) &&
0659       ((selector->show_all) ||
0660        (selector->show_dev))) {
0661     if (print_header) {
0662       printf("DEVICE ");
0663     }
0664     else {
0665       printf("%3" PRIu32 "%2" PRIu32,
0666          ((bdbuf_info->dev == -1)
0667           ? 0 : rtems_filesystem_dev_major_t(bdbuf_info->dev)),
0668          ((bdbuf_info->dev == -1)
0669           ? 0 : rtems_filesystem_dev_minor_t(bdbuf_info->dev)));
0670     }
0671   }
0672 
0673   /*
0674    * 7 chars: print info about block number of this buffer
0675    */
0676   if ((rc == RTEMS_SUCCESSFUL) &&
0677       ((selector->show_all) ||
0678        (selector->show_blocknum))) {
0679     if (print_header) {
0680       printf("BLOCK  ");
0681     }
0682     else {
0683       printf("%6" PRIu32,bdbuf_info->blknum);
0684     }
0685   }
0686 
0687   /*
0688    * 4 chars: print info about use count of this buffer
0689    */
0690   if ((rc == RTEMS_SUCCESSFUL) &&
0691       ((selector->show_all) ||
0692        (selector->show_use_count))) {
0693     if (print_header) {
0694       printf("USE ");
0695     }
0696     else {
0697       printf("%3u ",bdbuf_info->use_count);
0698     }
0699   }
0700 
0701   /*
0702    * 4 chars: print info about state of this buffer
0703    */
0704   if ((rc == RTEMS_SUCCESSFUL) &&
0705       ((selector->show_all) ||
0706        (selector->show_state))) {
0707     if (print_header) {
0708       printf("STA ");
0709     }
0710     else {
0711       printf("%c%c%c ",
0712          (bdbuf_info->modified    ? 'M' : '.'),
0713          (bdbuf_info->in_progress ? 'P' : '.'),
0714          (bdbuf_info->actual      ? 'A' : '.'));
0715     }
0716   }
0717 
0718   /*
0719    * 42 chars: print info about error of this buffer
0720    */
0721   if ((rc == RTEMS_SUCCESSFUL) &&
0722       ((selector->show_all) ||
0723        (selector->show_error))) {
0724     if (print_header) {
0725       printf("%20s:%-10s ","RTEMS STATUS","ERRNO");
0726     }
0727     else {
0728       printf("%20s:%-10s ",
0729          ((bdbuf_info->status == RTEMS_SUCCESSFUL)
0730           ? "SUCCESSFUL" : rtems_status_text(bdbuf_info->status)),
0731          ((bdbuf_info->status == RTEMS_SUCCESSFUL)
0732           ? "" : strerror(bdbuf_info->error)));
0733     }
0734   }
0735   /*
0736    * FIXME: add info about waiting chain
0737    */
0738   printf("\n");
0739   return rc;
0740 }
0741 
0742 /*=========================================================================*\
0743 | Function:                                                                 |
0744 \*-------------------------------------------------------------------------*/
0745 void rtems_bdbuf_show_fnc
0746 (
0747 /*-------------------------------------------------------------------------*\
0748 | Purpose:                                                                  |
0749 |   list all bdbufs with their content                                      |
0750 +---------------------------------------------------------------------------+
0751 | Input Parameters:                                                         |
0752 \*-------------------------------------------------------------------------*/
0753     int     argc,
0754     char  **argv,
0755     rtems_monitor_command_arg_t* command_arg,
0756     bool verbose
0757 )
0758 /*-------------------------------------------------------------------------*\
0759 | Return Value:                                                             |
0760 |    rtems_status_code                                                      |
0761 \*=========================================================================*/
0762 {
0763   rtems_status_code rc = RTEMS_SUCCESSFUL;
0764   show_bdbuf_filter_t   filter;
0765   show_bdbuf_selector_t selector;
0766   show_bdbuf_bdbuf_info_t bdbuf_info;
0767 
0768   bdbuf_pool *curr_pool,*pool_base;
0769   int pool_cnt,pool_idx;
0770   int bdbuf_idx;
0771   bool bdbuf_matches;
0772   int matched_cnt,un_matched_cnt;
0773 
0774   /*
0775    * analyze command line options
0776    */
0777   if (rc == RTEMS_SUCCESSFUL) {
0778     rc = rtems_bdbuf_show_getargs (argc,argv,
0779                    &filter,&selector);
0780   }
0781 
0782   /*
0783    * get buffer pool information
0784    */
0785   if (rc == RTEMS_SUCCESSFUL) {
0786     rc = rtems_bdbuf_show_get_bufpool(&pool_base,&pool_cnt);
0787     if (rc != RTEMS_SUCCESSFUL) {
0788       printf("%s: ERROR: no buffer pool found\n",argv[0]);
0789     }
0790   }
0791   /*
0792    * for all or selected buffer pool(s)
0793    */
0794   for (pool_idx = 0;
0795        (rc == RTEMS_SUCCESSFUL) && (pool_idx < pool_cnt);
0796        pool_idx++) {
0797     if ((filter.pool_id < 0) ||
0798     (filter.pool_id == pool_idx)) {
0799       curr_pool = pool_base + pool_idx;
0800       /*
0801        * print pool header
0802        */
0803       if (rc == RTEMS_SUCCESSFUL) {
0804     rc = rtems_bdbuf_show_pool_header(pool_idx,curr_pool);
0805       }
0806       if (rc == RTEMS_SUCCESSFUL) {
0807     matched_cnt = 0;
0808     un_matched_cnt = 0;
0809     /*
0810      * print header for bdbuf
0811      */
0812       if (rc == RTEMS_SUCCESSFUL) {
0813         rc = rtems_show_bdbuf_print(NULL,&selector,
0814                     true);
0815       }
0816     /*
0817      * for all bdbufs in this pool
0818      */
0819     for (bdbuf_idx = 0;
0820          ((rc == RTEMS_SUCCESSFUL) &&
0821           (bdbuf_idx < curr_pool->nblks));
0822          bdbuf_idx++) {
0823       /*
0824        * get infos about bdbuf
0825        */
0826       if (rc == RTEMS_SUCCESSFUL) {
0827         rc = rtems_show_bdbuf_get_bdbuf_info
0828           (&(curr_pool->bdbufs[bdbuf_idx]),
0829            bdbuf_idx,
0830            curr_pool,
0831            &bdbuf_info);
0832       }
0833       /*
0834        * check, if bdbuf matches selection criteria
0835        */
0836       if (rc == RTEMS_SUCCESSFUL) {
0837         rc = rtems_show_bdbuf_match_filter(&bdbuf_info,&filter,
0838                            &bdbuf_matches);
0839       }
0840       /*
0841        * print info about bdbuf
0842        */
0843       if (rc == RTEMS_SUCCESSFUL) {
0844         if (bdbuf_matches) {
0845           rc = rtems_show_bdbuf_print(&bdbuf_info,&selector,
0846                       false);
0847           if ((rc == RTEMS_SUCCESSFUL) &&
0848           selector.show_sema) {
0849         rc = rtems_show_bdbuf_print_wait_chain(&(curr_pool->bdbufs[bdbuf_idx]));
0850           }
0851           matched_cnt++;
0852         }
0853         else {
0854           un_matched_cnt++;
0855         }
0856       }
0857     }
0858     /*
0859      * print match statistics and footer
0860      */
0861     if (rc == RTEMS_SUCCESSFUL) {
0862       printf("%d bdbufs printed, %d bdbufs suppressed\n",
0863          matched_cnt,un_matched_cnt);
0864     }
0865       }
0866     }
0867   }
0868 }
0869 
0870 static rtems_monitor_command_entry_t rtems_show_bdbuf_cmds[] = {
0871   {
0872     "bdbuf_show",
0873     "usage: bdbuf_show\n",
0874     0,
0875     rtems_bdbuf_show_fnc,
0876     { 0 },
0877     0
0878   }
0879 };
0880 
0881 #ifndef ARRAY_CNT
0882 #define ARRAY_CNT(arr) (sizeof((arr))/sizeof((arr)[0]))
0883 #endif
0884 
0885 /*=========================================================================*\
0886 | Function:                                                                 |
0887 \*-------------------------------------------------------------------------*/
0888 rtems_status_code rtems_bdbuf_show_init
0889 (
0890 /*-------------------------------------------------------------------------*\
0891 | Purpose:                                                                  |
0892 |   add command(s) to monitor                                               |
0893 +---------------------------------------------------------------------------+
0894 | Input Parameters:                                                         |
0895 \*-------------------------------------------------------------------------*/
0896  void /* none up to now */
0897 )
0898 /*-------------------------------------------------------------------------*\
0899 | Return Value:                                                             |
0900 |    rtems_status_code                                                      |
0901 \*=========================================================================*/
0902 {
0903   rtems_status_code sc = RTEMS_SUCCESSFUL;
0904   int item;
0905 
0906   for (item = 0;
0907        (sc == RTEMS_SUCCESSFUL) && (item < ARRAY_CNT(rtems_show_bdbuf_cmds));
0908        item++) {
0909     if (0 == rtems_monitor_insert_cmd (&rtems_show_bdbuf_cmds[item])) {
0910       sc = RTEMS_INVALID_NAME;
0911     }
0912   }
0913   return sc;
0914 }