/* ** openMosix "struct mosix_info" handlers used by mosmon ** ** Copyright (C) 2004 Moreno 'baro' Baricevic ** ** ** This file may be used subject to the terms and conditions of the ** GNU Library General Public License as published by the Free Soft- ** ware Foundation; either version 2 of the License, or (at your op- ** tion) any later version. ** ** This file is distributed in the hope that it will be useful, but ** WITHOUT ANY WARRANTY; without even the implied warranty of MER- ** CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Li- ** brary General Public License for more details. */ /************************************************** * Author: Moreno 'baro' Baricevic * * Date: 13 Mar 2004 * * Title: mosix_info.c * *================================================* * Prev Modified: 13 Mar 2004 * * Prev Modified: 17 Mar 2004 * * Prev Modified: 19 Mar 2004 * * Prev Modified: 21 Mar 2004 * * Prev Modified: 25 Mar 2004 * * Prev Modified: 06 Apr 2004 * * Prev Modified: 19 Jun 2004 * * Last Modified: 25 Jun 2004 * **************************************************/ #include #include "utils.h" #include "mosix_info.h" static ssize_t get_recsz ( int fd ); #define SOMECODE( _k ) \ { \ DBGprint( "using struct mosix_info" # _k ); \ readstruct = readstruct ## _k ; \ recsz = RECSZ ## _k ; \ snprintf( mstruct , 16 , "mosix_info" # _k ); \ return _k ; \ } /***************************************************************************** *_____________________________ GUESS_BY_RECSZ _____________________________* *****************************************************************************/ /* ** Sets record size, mosix_info structure, handlers and all that stuff. ** Kernel and openMosix versions are not reliable for this purpose ** (believe me, I've already tested both and any kind of mix). ** This seems to be the most reliable method. ** ** NOTE that works ONLY with PROC_HPC_INFOS. It is a special proc file. ** On this file, lseek() jumps across records instead of bytes. By jumping ** directly to end of file, we get the total number of records stored ** inside the file. ** ** Consider that on "normal" files lseek() jumps across bytes, on proc ** files it usually does not work (EINVAL). ** */ int guess_by_recsz( int fd ) { off_t curr = lseek( fd , 0L , SEEK_CUR ); // get current position off_t nrec = lseek( fd , 0L , SEEK_END ); // get number of records ssize_t nr = 0; if ( nrec < 1 ) // Houston, ... SOMECODE( _DUMMY ); (void)lseek( fd , nrec - 1 , SEEK_SET ); // go to the last record nr = get_recsz( fd ); // get the record size (void)lseek( fd , curr , SEEK_SET ); // go to previous position DBGprint( "nr = %d" , nr ); switch ( nr ) { case RECSZ_2416 /* 32 */: SOMECODE( _2416 ); case RECSZ_2419 /* 24 */: SOMECODE( _2419 ); case RECSZ_2421 /* 56 */: SOMECODE( _2421 ); case RECSZ_2423 /* 36 */: SOMECODE( _2423 ); // case RECSZ_2422 /* 68 */: SOMECODE( _2422 ); case RECSZ_2424 /* 68 */: if ( openmosix_release.version >= 10904 ) // > 2.4.24-om1 { SOMECODE( _2424 ); } else { SOMECODE( _2422 ); } default /* unknown */: break; } SOMECODE( _DUMMY ); // avoid unassigned handlers return _UNKNOWN; // just in case... (already done by SOMECODE()) } /* guess_by_recsz */ /************************************************************************ *_____________________________ GET_RECSZ _____________________________* ************************************************************************/ /* ** We should be already positioned at the start of the last record. ** By reading larger amount of data than any possible record size, the ** read()'s return value is the effective record size (bytes until EOF). ** (MAX_RECSZ must be larger than any possible record size) */ static ssize_t get_recsz ( int fd ) { void * dummy = xcmalloc( MAX_RECSZ ); ssize_t nr = read( fd , dummy , MAX_RECSZ ); free( dummy ); return nr; } /* get_recsz */ /**************************************************************************** *_____________________________ FORCE_VERSION _____________________________* ****************************************************************************/ /* ** force a specific version ** Input: 2416, 2417, ... ** Output: _2416 (0), _2419 (1), ... ** No parachute here, we must die on error (unhandled versions). */ int force_version( int ver ) { int realver = 0; switch( ver ) { /* stable */ case 2416: realver = _2416 ; break; case 2417: case 2418: case 2419: case 2420: realver = _2419 ; break; case 2421: realver = _2421 ; break; case 2422: realver = _2422 ; break; case 2424: realver = _2424 ; break; /* testing */ case 2423: // case 2424: case 2425: realver = _2423 ; break; default: return _UNKNOWN; } switch( realver ) { case _2416: SOMECODE( _2416 ); case _2419: SOMECODE( _2419 ); case _2421: SOMECODE( _2421 ); case _2422: SOMECODE( _2422 ); case _2423: SOMECODE( _2423 ); case _2424: SOMECODE( _2424 ); default: break; } return _UNKNOWN; } /* force_version */ #ifdef DEBUG /********************************************************************** *_____________________________ SUMMARY _____________________________* **********************************************************************/ /* ** shows recsize(s) -- (debug) */ void summary( void ) { #define SUMMARY( x ) { DBGprint( "RECSZ_" # x " = %d" , RECSZ_ ## x ); } SUMMARY( STD ); SUMMARY( 2416 ); SUMMARY( 2419 ); SUMMARY( 2421 ); SUMMARY( 2422 ); SUMMARY( 2423 ); SUMMARY( 2424 ); } /* summary */ /**************************************************************************** *_____________________________ PRINT_STRINFO _____________________________* ****************************************************************************/ /* ** prints the content of the given mosix_infos_s structure -- (debug) */ void print_strinfo ( mosix_info_s * mis ) { #define pru16(x) printf( "%-13s = 0x%016x = %u\n" , # x , mis->x , mis->x ) #define pru32(x) printf( "%-13s = 0x%016lx = %lu\n" , # x , mis->x , mis->x ) #define pri64(x) printf( "%-13s = 0x%016llx = %lld\n" , # x , mis->x , mis->x ) pru32( load ); pru16( speed ); pru16( ncpus ); pru16( util ); pru16( status ); pri64( mem ); pri64( rmem ); pri64( tmem ); } /* print_strinfo */ #endif /* DEBUG */ /****************************************************************************** *_____________________________ READSTRUCT_2xxx _____________________________* ******************************************************************************/ /* ** Define a function for each known mosix_info structure. ** This family of functions returns npe or 0. */ #define BUILD_READSTRUCT( type ) \ int \ readstruct_ ## type ( fd , mis , el ) \ int fd ; \ mosix_info_s * mis ; \ size_t el ; \ { \ size_t outsize = el * RECSZ_STD ; \ size_t insize = el * RECSZ_ ## type ; \ \ ssize_t nr = -1 ; \ \ mosix_info_s * optr = mis; /* walk ptr */ \ \ struct mosix_info_ ## type * dummy; /* alloc ptr */ \ struct mosix_info_ ## type * iptr; /* walk ptr */ \ \ DBGprint( "el %d, orcsz %d, osz %d, ircsz %d, isz %d" \ , el \ , RECSZ_STD , outsize \ , RECSZ_ ## type , insize \ ); \ \ iptr = dummy = ( struct mosix_info_ ## type * ) \ xcmalloc( insize ); \ \ nr = read( fd , dummy , insize ); \ if ( nr == insize ) \ { \ int i; \ for ( i = 0 ; i < el ; i++ , optr++ , iptr++ ) \ { \ DBGprint( "got a record [%d of %d] out %p in %p" \ , i+1 , el , optr , iptr ); \ optr->load = ( uint32_t )iptr->load; \ optr->speed = ( uint16_t )iptr->speed; \ optr->ncpus = ( uint16_t )iptr->ncpus; \ optr->util = ( uint16_t )iptr->util; \ optr->status = ( uint16_t )iptr->status; \ optr->mem = ( int64_t )iptr->mem; \ optr->rmem = ( int64_t )iptr->rmem; \ optr->tmem = ( int64_t )iptr->tmem; \ } \ } \ else \ DBGprint( "*** NO record" ); \ free( dummy ); \ return ( nr > 0 ) ? (int)( nr / RECSZ_ ## type ) : 0 ; \ } BUILD_READSTRUCT( 2416 ) BUILD_READSTRUCT( 2419 ) BUILD_READSTRUCT( 2421 ) BUILD_READSTRUCT( 2422 ) BUILD_READSTRUCT( 2423 ) BUILD_READSTRUCT( 2424 ) #undef BUILD_READSTRUCT /* ** this parachute avoids unassigned handler (and consequent segfault ;) */ int readstruct_DUMMY ( int x , mosix_info_s * y , size_t z ) { return 0; } /* readstruct_DUMMY */ /*********************** E N D O F F I L E ************************/