00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #if defined(macintosh)
00113 #include <types.h>
00114 #else
00115 #include <sys/types.h>
00116 #endif
00117 #include <stdio.h>
00118 #include <time.h>
00119 #include <string.h>
00120 #include <assert.h>
00121 #include <stdlib.h>
00122 #include <stdarg.h>
00123 #include "merc.h"
00124 #include "db.h"
00125
00126
00127
00128
00129
00130 #define STRSPACE_DEFAULT (2*4096)
00131
00132
00133
00134 #define STRSPACE_INCREMENT 128
00135
00136
00137 #define MPROGS_INSTALLED
00138
00139
00140 #define DOUBLE_LOGGING
00141
00142
00143
00144
00145
00146 #define SHOW_ALL_RGSIZES
00147
00148
00149 #define ALLOC_PERM_ALIGN 32//sizeof(int)
00150
00151
00152
00153
00154
00155
00156
00157 #define MAX_MEM_LIST 11
00158
00159 const size_t rgSizeList [MAX_MEM_LIST]
00160 = { 16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768-64 };
00161
00162
00163
00164
00165
00166 #ifndef __mkwMUD
00167
00168 #define MAGIC_CHECKING
00169
00170
00171 #define chwrite( ch, str ) send_to_char( str, ch )
00172
00173
00174 #define object_free obj_free
00175
00176
00177 #define OK 0
00178 #define ERR 1
00179
00180 #endif
00181
00182
00183
00184
00185
00186 extern char * string_space;
00187 extern int mobile_count;
00188 extern OBJ_DATA *obj_free;
00189 extern CHAR_DATA *char_free;
00190 extern DESCRIPTOR_DATA *descriptor_free;
00191 extern PC_DATA *pcdata_free;
00192 extern AFFECT_DATA *affect_free;
00193 extern NOTE_DATA *note_list,*idea_list,*penalty_list,*news_list,*changes_list;
00194
00195
00196
00197
00198
00199
00200
00201 int has_system_auth( CHAR_DATA* ch );
00202 int strspace_size_read();
00203 int strspace_size_set( int newsize );
00204 void strspace_size_default();
00205 extern const size_t rgSizeList [MAX_MEM_LIST];
00206 extern void * rgFreeList [MAX_MEM_LIST];
00207
00208
00209
00210
00211
00212
00213
00214 const char ver_mkwSys[]="mkwSys Version 2.01";
00215
00216 unsigned strspace_size;
00217
00218 void* rgFreeList [MAX_MEM_LIST];
00219
00220 unsigned long nAllocGP[MAX_MEM_LIST] = { 0,0,0,0,0,0,0,0,0,0,0};
00221
00222 int nAllocPerm;
00223 size_t sAllocPerm = 0;
00224 int nPermBlocks = 0;
00225
00226 void boot_fail(char* module_name)
00227 {
00228 logf( "********************* Reboot by %-11s *********************", module_name );
00229 exit( EXIT_FAILURE );
00230 }
00231
00232
00233 char* strspace_alloc()
00234 {
00235 strspace_size_read();
00236 if ( ( string_space = calloc( 1, strspace_size * 1024 ) ) == NULL )
00237 {
00238 logf( "mkwSys.c: Unable to allocate %d kB string space from system.", strspace_size );
00239 if( strspace_size > STRSPACE_DEFAULT )
00240 strspace_size_default();
00241 else
00242 logf( "Increase your system's virtual memory size.", strspace_size );
00243 boot_fail( "mkwSys.c" );
00244 }
00245 return string_space;
00246 }
00247
00248
00249 void strspace_size_default()
00250 {
00251 strspace_size_set( STRSPACE_DEFAULT );
00252 logf( "mkwSys.c: String space size reset to program default of %d kB.", strspace_size );
00253 }
00254
00255
00256 void strspace_size_increment()
00257 {
00258 logf( "mkwSys.c: String space size of %d kB did not suffice.", strspace_size );
00259 strspace_size_set( strspace_size + STRSPACE_INCREMENT );
00260 logf( "mkwSys.c: Incrementing string space size to %d kB and rebooting.", strspace_size );
00261 boot_fail( "mkwSys.c" );
00262 }
00263
00264
00265 int strspace_size_set( int newsize )
00266 {
00267 if( newsize > 0 )
00268 {
00269 FILE* memini= fopen( DATPATH "mkwSys.ini", "w" );
00270 if( memini )
00271 {
00272 fprintf( memini, "stringspace = %u\n", newsize );
00273 fclose( memini );
00274 return OK;
00275 }
00276 else
00277 {
00278 logf( "Unable to open mkwSys.ini for writing" );
00279 }
00280 }
00281 return ERR;
00282 }
00283
00284
00285 int strspace_size_read()
00286 {
00287 FILE* memini= fopen( DATPATH "mkwSys.ini", "r" );
00288 if( memini )
00289 {
00290 strspace_size = 0;
00291 while( str_cmp( fread_word( memini ), "stringspace" ) )
00292 ;
00293 fscanf( memini, " = %u", &strspace_size );
00294 fclose( memini );
00295 if( !strspace_size )
00296 {
00297 logf( "mkwSys.c: String space size not set in mkwSys.ini, using default." );
00298 strspace_size_default();
00299 }
00300 else
00301 return OK;
00302 }
00303 else
00304 {
00305 logf( "mkwSys.c: Unable to open memsize.ini for reading, using default string space size." );
00306 strspace_size_default();
00307 }
00308 return ERR;
00309 }
00310
00311 int has_system_auth( CHAR_DATA* ch )
00312 {
00313 if( get_trust( ch ) < CREATOR )
00314 {
00315 send_to_char( "You are not authorized to issue system commands.\n\r", ch );
00316 return FALSE;
00317 }
00318 else
00319 return TRUE;
00320 }
00321
00322 #define IMP_COUNTER( type, start, px) \
00323 int px##type() { type * p = start; int n = 0; while( p!=NULL ) { p= p->next; n++; } return n; }
00324
00325
00326 #define IMP_LIST_COUNTERS( type, prefix ) \
00327 IMP_COUNTER( type, prefix##list, n ) IMP_COUNTER( type, prefix##free, f )
00328
00329
00330
00331 IMP_COUNTER ( PC_DATA, pcdata_free, f)
00332 IMP_COUNTER ( AFFECT_DATA, affect_free, f)
00333
00334
00335 IMP_LIST_COUNTERS ( OBJ_DATA, object_ );
00336 IMP_LIST_COUNTERS ( CHAR_DATA, char_ );
00337 IMP_LIST_COUNTERS ( DESCRIPTOR_DATA, descriptor_ );
00338
00339 #ifdef MPROGS_INSTALLED
00340 IMP_COUNTER ( MPROG_CODE, mprog_list, n );
00341
00342
00343
00344 #endif
00345
00346 int nNOTE_DATA()
00347 {
00348 NOTE_DATA* p; int n = 0;
00349 for( p=note_list;p!=NULL; p=p->next) n++;
00350 for( p=idea_list;p!=NULL; p=p->next) n++;
00351 for( p=changes_list;p!=NULL; p=p->next) n++;
00352 for( p=penalty_list;p!=NULL; p=p->next) n++;
00353 for( p=news_list;p!=NULL; p=p->next) n++;
00354 return n;
00355 }
00356
00357
00358 #define rpt( name, n, obj ) chprintf( ch, "%5d %-14s *%4d Bytes =%6d kB\n\r", \
00359 n, name, sizeof(obj), (n) * sizeof(obj)/1024 )
00360
00361
00362 #define rpt_dy( name, type ) { int n= n##type(); rpt( name, n, type ); }
00363
00364
00365
00366 #define rptsd( st, sz ) chprintf( ch, "%-34s %5d kB\n\r", st, sz )
00367
00368
00369 #define rptdsd(n,st,sz) chprintf( ch, "%5d %-28s %5d kB\n\r", n, st, sz )
00370
00371
00372 const char separator[] = "-------------------------------------------\n\r";
00373
00374 void do_memory_perms( CHAR_DATA *ch, char* argument )
00375 {
00376 int i;
00377 chwrite( ch, separator );
00378 chwrite( ch, "{cPermanent memory objects in use{x\n\r");
00379 chwrite( ch, separator );
00380 rpt_dy( "Characters", CHAR_DATA );
00381 rpt( "PCs", nCHAR_DATA() - mobile_count , PC_DATA );
00382 rpt_dy( "Descriptors", DESCRIPTOR_DATA );
00383 rpt( "Mob Prototypes", top_mob_index, MOB_INDEX_DATA );
00384 rpt_dy( "Objects", OBJ_DATA);
00385 rpt( "Obj Prototypes", top_obj_index, OBJ_INDEX_DATA);
00386 rpt( "Extra Descs", top_ed, EXTRA_DESCR_DATA );
00387 rpt( "Affects", top_affect, AFFECT_DATA );
00388 rpt( "Rooms", top_room, ROOM_INDEX_DATA );
00389 rpt( "Exits", top_exit, EXIT_DATA );
00390 rpt( "Shops", top_shop, SHOP_DATA );
00391 rpt( "Areas", top_area, AREA_DATA );
00392 rpt( "Resets", top_reset, RESET_DATA );
00393 rpt( "Help entries", top_help, HELP_DATA );
00394 rpt_dy( "Notes", NOTE_DATA);
00395 rpt( "Socials", social_count, struct social_type );
00396 #ifdef MPROGS_INSTALLED
00397 rpt_dy( "Mob progs", MPROG_CODE )
00398 #endif
00399 for( i= 0; i<MAX_MEM_LIST; i++)
00400 #ifndef SHOW_ALL_RGSIZES
00401 if( nAllocGP[i] )
00402 #endif
00403 chprintf( ch, "%5d GP blocks of %6d Bytes =%6d kB\n\r",
00404 nAllocGP[i], rgSizeList[i], nAllocGP[i] * rgSizeList[i] / 1024);
00405 chwrite( ch, separator );
00406 }
00407
00408
00409 #define rptf( name, type ) { int n= f##type(); rpt( name, n, type ); }
00410
00411 void do_memory_freelists( CHAR_DATA *ch, char* argument )
00412 {
00413 int i;
00414 chwrite( ch, separator );
00415 chwrite( ch, "Memory objects waiting to be recycled\n\r");
00416 chwrite( ch, separator );
00417 rptf( "Characters", CHAR_DATA );
00418 rptf( "PCs", PC_DATA );
00419 rptf( "Descriptors", DESCRIPTOR_DATA );
00420 rptf( "Objects", OBJ_DATA);
00421 rptf( "Affects", AFFECT_DATA );
00422
00423 for( i= 0; i<MAX_MEM_LIST; i++)
00424 #ifndef SHOW_ALL_RGSIZES
00425 if( rgFreeList[i] )
00426 #endif
00427 {
00428 void* p;
00429 int n = 0;
00430 for(p= rgFreeList[i]; p != NULL; p= * ((void **) p ) )
00431 n++;
00432 chprintf( ch, "%5d GP blocks of %6d Bytes =%6d kB\n\r",
00433 n, rgSizeList[i], n * rgSizeList[i] / 1024);
00434 }
00435 chwrite( ch, separator );
00436 }
00437
00438
00439 void do_memory_heap( CHAR_DATA *ch, char* argument )
00440 {
00441 chwrite( ch, separator );
00442 chprintf( ch, "Perm Block size is set to %d kB\n\r", MAX_PERM_BLOCK/1024 );
00443 chprintf( ch, "Object alignment is set to %d Bytes\n\r", ALLOC_PERM_ALIGN );
00444
00445 rptdsd( nPermBlocks , "Blocks allocated from heap", nPermBlocks * MAX_PERM_BLOCK/1024 );
00446 rptdsd( nAllocPerm, "Permanent objects occupy", sAllocPerm/1024 );
00447 rptsd( "Current alloc_perm() overhead",
00448 ( nPermBlocks * MAX_PERM_BLOCK - sAllocPerm ) / 1024 );
00449 chwrite( ch, separator );
00450
00451 rptsd( "String Space allocated at DB boot", strspace_size );
00452 rptdsd( nAllocString, "Strings in string space", sAllocString/1024 );
00453 rptsd( "Excess string space", strspace_size - sAllocString/1024 );
00454
00455 chwrite( ch, separator );
00456 rptsd( "Total managed heap memory", nPermBlocks * MAX_PERM_BLOCK/1024 + strspace_size );
00457 chwrite( ch, separator );
00458 }
00459
00460
00461
00462
00463 void do_memory_formats( CHAR_DATA *ch, char* argument )
00464 {
00465 chwrite( ch, separator );
00466 chprintf( ch, "Old format mobs: %d\n\rOld format objects: %d\n\r",
00467 top_mob_index - newmobs, top_obj_index - newobjs );
00468 chwrite( ch, separator );
00469 }
00470
00471 #undef rpt
00472 #undef rpt_dy
00473 #undef rptsd
00474 #undef rptdsd
00475
00476
00477 void do_memory_stringspace( CHAR_DATA *ch, char *argument )
00478 {
00479 if( has_system_auth(ch) )
00480 {
00481 char arg[MAX_INPUT_LENGTH];
00482 int sz = 0;
00483 argument= one_argument( argument, arg );
00484 if( is_number( arg ) )
00485 sz= atoi( arg );
00486 if( sz <= 0 || sz > 32000 )
00487 {
00488 chwrite( ch, "Invalid parameter.\n\r" );
00489 return;
00490 }
00491 if( strspace_size_set( sz ) == OK )
00492 chprintf( ch, "String space size for next DB boot set to %d kB.\n\r", sz );
00493 else
00494 chwrite( ch, "Error writing new setting to file.\n\r" );
00495 }
00496 }
00497
00498 void do_memory_help( CHAR_DATA *ch, char *argument )
00499 {
00500 chwrite(ch, ver_mkwSys );
00501 chwrite(ch, " copyright (c) 1998 Michael K. Weise\n\r"
00502 "See home.att.net/~mkw/mudframe.html for more information\n\n\r"
00503 "usage: memory <command>\n\r\ravailable commands:\n\r"
00504 "heap Report heap memory allocated by the memory manager\n\r"
00505 "perms Report managed memory objects in use by other modules\n\r"
00506 "freelists Report memory objects waiting to be recycled\n\r"
00507 "stringspace <size> Set string space size in kB for next reboot\n\r"
00508 "formats Report old format prototypes\n\r"
00509 "? This message\n\r"
00510 );
00511 }
00512
00513
00514 void do_memory( CHAR_DATA *ch, char *argument )
00515 {
00516 vinterpret( ch, argument,
00517 "perms", do_memory_perms,
00518 "heap", do_memory_heap,
00519 "freelists", do_memory_freelists,
00520 "stringspace", do_memory_stringspace,
00521 "formats", do_memory_formats,
00522 NULL, do_memory_help );
00523 }
00524
00525
00526 int strswitch( const char* arg, ... )
00527 {
00528 int i = 0;
00529 char* p;
00530 va_list caselist;
00531 if( arg[0] )
00532 {
00533 va_start( caselist, arg );
00534 while( (p = va_arg( caselist, char* )) != NULL )
00535 {
00536 i++;
00537 if( !str_prefix( arg, p ) )
00538 return i;
00539 }
00540 }
00541 return 0;
00542 }
00543
00544
00545 void vinterpret( CHAR_DATA *ch, char *argument, ... )
00546 {
00547 char arg[MAX_INPUT_LENGTH];
00548 char* iStr;
00549 DO_FUN *iFun;
00550 va_list caselist;
00551 va_start( caselist, argument );
00552 argument= one_argument( argument, arg );
00553 do
00554 {
00555 iStr = va_arg( caselist, char* );
00556 iFun = va_arg( caselist, DO_FUN* );
00557 }
00558 while( iStr != NULL && ( !arg[0] || str_prefix( arg, iStr ) ) );
00559 if( iFun != NULL )
00560 (*iFun)( ch, argument );
00561 }
00562
00563
00564 size_t rgSize_lookup( size_t size )
00565 {
00566 int iList;
00567 size += sizeof( int );
00568
00569 for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
00570 {
00571 if ( size <= rgSizeList[iList] )
00572 return rgSizeList[iList] - sizeof( int );
00573 }
00574 return 0;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584 void *alloc_mem( size_t sMem )
00585 {
00586 void *pMem;
00587 int iList;
00588
00589 #ifdef MAGIC_CHECKING
00590 int *magic;
00591 sMem += sizeof(*magic);
00592 #endif
00593
00594 for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
00595 {
00596 if ( sMem <= rgSizeList[iList] )
00597 break;
00598 }
00599
00600 if ( iList == MAX_MEM_LIST )
00601 {
00602 bug( "Alloc_mem: size %d too large.", sMem );
00603
00604 return pMem;
00605 }
00606
00607 if ( rgFreeList[iList] == NULL )
00608 {
00609 pMem = alloc_perm( rgSizeList[iList] );
00610 nAllocGP[iList]++;
00611 }
00612 else
00613 {
00614 pMem = rgFreeList[iList];
00615 rgFreeList[iList] = * ((void **) rgFreeList[iList]);
00616 }
00617
00618 #ifdef MAGIC_CHECKING
00619 magic = (int *) pMem;
00620 *magic = MAGIC_NUM;
00621 pMem = (void*) (((char*)pMem) + sizeof (*magic));
00622 #endif
00623 return pMem;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 void *alloc_perm( size_t sMem )
00635 {
00636 static int iMemPerm;
00637 static char *pMemPerm;
00638 void *pMem;
00639
00640 while ( sMem % ALLOC_PERM_ALIGN != 0 )
00641 sMem++;
00642 if ( sMem > MAX_PERM_BLOCK )
00643 {
00644 bug( "Alloc_perm: %d too large.", sMem );
00645 exit( EXIT_FAILURE );
00646 }
00647
00648 if ( pMemPerm == NULL || iMemPerm + sMem > MAX_PERM_BLOCK )
00649 {
00650 iMemPerm = 0;
00651 nPermBlocks++;
00652 if ( ( pMemPerm = calloc( 1, MAX_PERM_BLOCK ) ) == NULL )
00653 {
00654 perror( "Alloc_perm" );
00655 exit( EXIT_FAILURE );
00656 }
00657 }
00658
00659 pMem = pMemPerm + iMemPerm;
00660 iMemPerm += sMem;
00661 nAllocPerm += 1;
00662 sAllocPerm += sMem;
00663 return pMem;
00664 }
00665
00666
00667
00668
00669
00670 void free_mem( void *pMem, size_t sMem )
00671 {
00672 int iList;
00673
00674 #ifdef MAGIC_CHECKING
00675 int *magic;
00676
00677 pMem = (void*) (((char*)pMem) - sizeof (*magic));
00678 magic = (int *) pMem;
00679
00680 if (*magic != MAGIC_NUM)
00681 {
00682 bug("Attempt to recyle invalid memory of size %d.",sMem);
00683 bug((char*) pMem + sizeof(*magic),0);
00684 return;
00685 }
00686
00687 *magic = 0;
00688 sMem += sizeof(*magic);
00689 #endif
00690
00691 for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
00692 {
00693 if ( sMem <= rgSizeList[iList] )
00694 break;
00695 }
00696
00697 if ( iList == MAX_MEM_LIST )
00698 {
00699 bug( "Free_mem: size %d too large.", sMem );
00700 exit( EXIT_FAILURE );
00701 }
00702
00703 * ((void **) pMem) = rgFreeList[iList];
00704 rgFreeList[iList] = pMem;
00705
00706 return;
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 int chprintf( CHAR_DATA* ch, const char *format, ... )
00741 {
00742 static char buf[MAX_STRING_LENGTH+1];
00743 va_list arglist;
00744 int nChars= 0;
00745 va_start( arglist, format );
00746 if ( format != NULL && format[0] && ch->desc != NULL )
00747 {
00748 nChars = vsprintf( buf, format, arglist );
00749 assert( nChars <= MAX_STRING_LENGTH );
00750 write_to_buffer( ch->desc, buf, nChars );
00751 }
00752 va_end( arglist );
00753 return nChars;
00754 }
00755
00756
00757
00758