Back to index

kdeartwork  4.3.2
vm.c
Go to the documentation of this file.
00001 /*
00002  * vm.c
00003  *
00004  * Copyright (c) 2000 Artur Rataj
00005  * Distributed under the terms of the GNU General Public License
00006  *
00007  */
00008 
00009 #include "vm.h"
00010 
00011 #define       ERROR_VALUE   INT_MAX
00012 
00013 int vm_init_pool( struct tvm_pool**       pool,
00014                   int                     area_size,
00015                   int                     max_stack_size,
00016                   int                     max_threads_num ) {
00017  int position;
00018  
00019  ( *pool ) = (struct tvm_pool*)malloc( sizeof(struct tvm_pool) );
00020  ( *pool )->area_size = area_size;
00021  ( *pool )->area = (int*)malloc( (*pool)->area_size*sizeof(int) );
00022  ( *pool )->processes = NULL;
00023  ( *pool )->max_stack_size = max_stack_size;
00024  ( *pool )->max_threads_num = max_threads_num;
00025  vm_enable_reverse( *pool, 0 ); 
00026  for( position = 0; position < (*pool)->area_size; ++position )
00027   ( *pool )->area[position] = VM_OP_STOP;
00028  return 1;
00029 }
00030 
00031 void vm_done_pool( struct tvm_pool*       pool ) {
00032  struct tvm_process* curr_process;
00033  free( pool->area );
00034  curr_process = pool->processes;
00035  while( curr_process ) {
00036   struct tvm_process*       tmp_process;
00037   
00038   tmp_process = curr_process;
00039   curr_process = curr_process->next;
00040   free( tmp_process->stack );
00041   free( tmp_process );
00042  }
00043  free( pool );
00044 }
00045 
00046 static int push( struct tvm_pool*  pool,
00047                  struct tvm_process*      process,
00048                  int               value ) {
00049  if( process->stack_top == pool->max_stack_size )
00050   return ERROR_VALUE;
00051  else
00052   process->stack[process->stack_top++] = value;
00053  return 1;
00054 }
00055 
00056 static int pop( struct tvm_pool*   pool,
00057                 struct tvm_process*       process ) {
00058  if( process->stack_top == 0 )
00059   return ERROR_VALUE;
00060  else
00061 {
00062   return process->stack[--process->stack_top];
00063 }
00064 }
00065 
00066 void vm_modify( struct tvm_pool*   pool,
00067                 int                position,
00068                 int                op ) {
00069  pool->area[position] = op;
00070 }
00071 
00072 void vm_exec( struct tvm_pool*     pool,
00073               int           position,
00074               int           age,
00075               int           reverse ) {
00076  struct tvm_process* new_process;
00077               
00078  new_process = (struct tvm_process*)malloc( sizeof(struct tvm_process) );
00079  new_process->position = position;
00080  new_process->stack = (int*)malloc( pool->max_stack_size*sizeof(int) );
00081  new_process->stack_top = 0;
00082  new_process->age = age;
00083  new_process->reverse = reverse;
00084  new_process->next = pool->processes;
00085  pool->processes = new_process;
00086 }
00087 
00088 void vm_enable_reverse( struct tvm_pool*  pool,
00089                         const int         enabled ) {
00090  pool->reverse_enabled = enabled;
00091 }
00092 
00093 int vm_get_reverse( struct tvm_pool*       pool ) {
00094  if( pool->reverse_enabled )
00095   return (int)( vm_random(&(pool->vm_random_data))*2.0/
00096                 ( VM_RAND_MAX + 1.0 ) ); 
00097  else
00098   return 0;
00099 }
00100 
00101 void vm_iterate( struct tvm_pool*  pool,
00102                  char*                    modified ) {
00103  struct tvm_process* prev_process;
00104  struct tvm_process* curr_process;
00105  struct tvm_process* next_process;
00106  int                 processes_num;
00107  
00108  processes_num = 0;
00109  prev_process = NULL;
00110  curr_process = pool->processes;
00111  while( curr_process ) {
00112   int                op;
00113   int                arg;
00114   int                arg_2;
00115   int                arg_3;
00116   
00117   ++curr_process->age;
00118   next_process = curr_process->next;
00119   op = pool->area[curr_process->position];
00120   if( curr_process->reverse )
00121    --curr_process->position;
00122   else
00123    ++curr_process->position;
00124   curr_process->position = ( curr_process->position + pool->area_size )%
00125                            pool->area_size;
00126   switch( op ) {
00127    case VM_OP_WAIT:
00128     break;
00129     
00130    case VM_OP_STOP:
00131     if( !prev_process )
00132      pool->processes = curr_process->next;
00133     else
00134      prev_process->next = curr_process->next;
00135     free( curr_process->stack );
00136     free( curr_process );
00137     curr_process = prev_process;
00138     --processes_num; 
00139     break;
00140     
00141    case VM_OP_EXEC:
00142     if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
00143      if( !prev_process )
00144       pool->processes = curr_process->next;
00145      else
00146       prev_process->next = curr_process->next;
00147      free( curr_process->stack );
00148      free( curr_process );
00149      curr_process = prev_process;
00150      --processes_num; 
00151     } else {
00152      arg = curr_process->position + arg;
00153      if( arg < 0 )
00154       arg += pool->area_size;
00155      if( arg >= pool->area_size )
00156       arg -= pool->area_size;
00157      vm_exec( pool, arg, curr_process->age, vm_get_reverse(pool) );
00158     }
00159     break;
00160     
00161    case VM_OP_COPY:
00162     if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
00163      if( !prev_process )
00164       pool->processes = curr_process->next;
00165      else
00166       prev_process->next = curr_process->next;
00167      free( curr_process->stack );
00168      free( curr_process );
00169      curr_process = prev_process;
00170      --processes_num; 
00171     } else if( (arg_2 = pop( pool, curr_process )) == ERROR_VALUE ) {
00172      if( !prev_process )
00173       pool->processes = curr_process->next;
00174      else
00175       prev_process->next = curr_process->next;
00176      free( curr_process->stack );
00177      free( curr_process );
00178      curr_process = prev_process;
00179      --processes_num; 
00180     } else if( 1 && (arg_3 = pop( pool, curr_process )) == ERROR_VALUE ) {
00181      if( !prev_process )
00182       pool->processes = curr_process->next;
00183      else
00184       prev_process->next = curr_process->next;
00185      free( curr_process->stack );
00186      free( curr_process );
00187      curr_process = prev_process;
00188      --processes_num; 
00189     } else {
00190      int      count;
00191      int direction;
00192      
00193      arg = curr_process->position + arg;
00194      if( arg < 0 )
00195       arg += pool->area_size;
00196      if( arg >= pool->area_size )
00197       arg -= pool->area_size;
00198      arg_2 = curr_process->position + arg_2;
00199      if( arg_2 < 0 )
00200       arg_2 += pool->area_size;
00201      if( arg_2 >= pool->area_size )
00202       arg_2 -= pool->area_size;
00203      if( curr_process->reverse )
00204       direction = -1;
00205      else
00206       direction = 1;
00207      for( count = 0; count < arg_3; ++count ) {
00208       int     i, j;
00209       int     offset;
00210       
00211       offset = count*direction + pool->area_size;
00212       i = pool->area[( arg_2 + offset )%pool->area_size];
00213       j = pool->area[( arg_2 + offset )%pool->area_size] = pool->area[( arg + offset )%pool->area_size];
00214       if( modified && i != j )
00215        modified[( arg_2 + offset )%pool->area_size] = 1;
00216      }
00217     }
00218     break;
00219     
00220    default: /* >= VM_OP_PUSH */
00221     arg = op - VM_OP_PUSH;
00222     if( push(pool, curr_process, arg) == ERROR_VALUE ) {
00223      if( !prev_process )
00224       pool->processes = curr_process->next;
00225      else
00226       prev_process->next = curr_process->next;
00227      free( curr_process->stack );
00228      free( curr_process );
00229      curr_process = prev_process;
00230      --processes_num; 
00231     }
00232     break;
00233   }
00234   prev_process = curr_process;
00235   curr_process = next_process;
00236   ++processes_num;
00237  }
00238  while( processes_num > pool->max_threads_num ) {
00239   int  process_num;
00240   int  curr_process_num;
00241   
00242   process_num = (int)( vm_random(&(pool->vm_random_data))*1.0*processes_num/
00243                        ( VM_RAND_MAX + 1.0 ) );
00244 /*
00245   process_num = (int)( rand()*1.0*processes_num/
00246                        ( RAND_MAX + 1.0 ) );
00247  */
00248   curr_process_num = 0;
00249   curr_process = pool->processes;
00250   prev_process = NULL;
00251   while( curr_process_num != process_num ) {
00252    prev_process = curr_process;
00253    curr_process = curr_process->next;
00254    ++curr_process_num;
00255   }
00256   if( prev_process )
00257    prev_process->next = curr_process->next;
00258   else
00259    pool->processes = curr_process->next;
00260   free( curr_process->stack );
00261   free( curr_process );
00262   --processes_num;
00263  }
00264 }