You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeartwork/kscreensaver/kdesavers/vm.c

265 lines
7.0 KiB

/*
* vm.c
*
* Copyright (c) 2000 Artur Rataj
* Distributed under the terms of the GNU General Public License
*
*/
#include "vm.h"
#define ERROR_VALUE INT_MAX
int vm_init_pool( struct tvm_pool** pool,
int area_size,
int max_stack_size,
int max_threads_num ) {
int position;
( *pool ) = (struct tvm_pool*)malloc( sizeof(struct tvm_pool) );
( *pool )->area_size = area_size;
( *pool )->area = (int*)malloc( (*pool)->area_size*sizeof(int) );
( *pool )->processes = NULL;
( *pool )->max_stack_size = max_stack_size;
( *pool )->max_threads_num = max_threads_num;
vm_enable_reverse( *pool, 0 );
for( position = 0; position < (*pool)->area_size; ++position )
( *pool )->area[position] = VM_OP_STOP;
return 1;
}
void vm_done_pool( struct tvm_pool* pool ) {
struct tvm_process* curr_process;
free( pool->area );
curr_process = pool->processes;
while( curr_process ) {
struct tvm_process* tmp_process;
tmp_process = curr_process;
curr_process = curr_process->next;
free( tmp_process->stack );
free( tmp_process );
}
free( pool );
}
static int push( struct tvm_pool* pool,
struct tvm_process* process,
int value ) {
if( process->stack_top == pool->max_stack_size )
return ERROR_VALUE;
else
process->stack[process->stack_top++] = value;
return 1;
}
static int pop( struct tvm_pool* pool,
struct tvm_process* process ) {
if( process->stack_top == 0 )
return ERROR_VALUE;
else
{
return process->stack[--process->stack_top];
}
}
void vm_modify( struct tvm_pool* pool,
int position,
int op ) {
pool->area[position] = op;
}
void vm_exec( struct tvm_pool* pool,
int position,
int age,
int reverse ) {
struct tvm_process* new_process;
new_process = (struct tvm_process*)malloc( sizeof(struct tvm_process) );
new_process->position = position;
new_process->stack = (int*)malloc( pool->max_stack_size*sizeof(int) );
new_process->stack_top = 0;
new_process->age = age;
new_process->reverse = reverse;
new_process->next = pool->processes;
pool->processes = new_process;
}
void vm_enable_reverse( struct tvm_pool* pool,
const int enabled ) {
pool->reverse_enabled = enabled;
}
int vm_get_reverse( struct tvm_pool* pool ) {
if( pool->reverse_enabled )
return (int)( vm_random(&(pool->vm_random_data))*2.0/
( VM_RAND_MAX + 1.0 ) );
else
return 0;
}
void vm_iterate( struct tvm_pool* pool,
char* modified ) {
struct tvm_process* prev_process;
struct tvm_process* curr_process;
struct tvm_process* next_process;
int processes_num;
processes_num = 0;
prev_process = NULL;
curr_process = pool->processes;
while( curr_process ) {
int op;
int arg;
int arg_2;
int arg_3;
++curr_process->age;
next_process = curr_process->next;
op = pool->area[curr_process->position];
if( curr_process->reverse )
--curr_process->position;
else
++curr_process->position;
curr_process->position = ( curr_process->position + pool->area_size )%
pool->area_size;
switch( op ) {
case VM_OP_WAIT:
break;
case VM_OP_STOP:
if( !prev_process )
pool->processes = curr_process->next;
else
prev_process->next = curr_process->next;
free( curr_process->stack );
free( curr_process );
curr_process = prev_process;
--processes_num;
break;
case VM_OP_EXEC:
if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
if( !prev_process )
pool->processes = curr_process->next;
else
prev_process->next = curr_process->next;
free( curr_process->stack );
free( curr_process );
curr_process = prev_process;
--processes_num;
} else {
arg = curr_process->position + arg;
if( arg < 0 )
arg += pool->area_size;
if( arg >= pool->area_size )
arg -= pool->area_size;
vm_exec( pool, arg, curr_process->age, vm_get_reverse(pool) );
}
break;
case VM_OP_COPY:
if( (arg = pop( pool, curr_process )) == ERROR_VALUE ) {
if( !prev_process )
pool->processes = curr_process->next;
else
prev_process->next = curr_process->next;
free( curr_process->stack );
free( curr_process );
curr_process = prev_process;
--processes_num;
} else if( (arg_2 = pop( pool, curr_process )) == ERROR_VALUE ) {
if( !prev_process )
pool->processes = curr_process->next;
else
prev_process->next = curr_process->next;
free( curr_process->stack );
free( curr_process );
curr_process = prev_process;
--processes_num;
} else if( 1 && (arg_3 = pop( pool, curr_process )) == ERROR_VALUE ) {
if( !prev_process )
pool->processes = curr_process->next;
else
prev_process->next = curr_process->next;
free( curr_process->stack );
free( curr_process );
curr_process = prev_process;
--processes_num;
} else {
int count;
int direction;
arg = curr_process->position + arg;
if( arg < 0 )
arg += pool->area_size;
if( arg >= pool->area_size )
arg -= pool->area_size;
arg_2 = curr_process->position + arg_2;
if( arg_2 < 0 )
arg_2 += pool->area_size;
if( arg_2 >= pool->area_size )
arg_2 -= pool->area_size;
if( curr_process->reverse )
direction = -1;
else
direction = 1;
for( count = 0; count < arg_3; ++count ) {
int i, j;
int offset;
offset = count*direction + pool->area_size;
i = pool->area[( arg_2 + offset )%pool->area_size];
j = pool->area[( arg_2 + offset )%pool->area_size] = pool->area[( arg + offset )%pool->area_size];
if( modified && i != j )
modified[( arg_2 + offset )%pool->area_size] = 1;
}
}
break;
default: /* >= VM_OP_PUSH */
arg = op - VM_OP_PUSH;
if( push(pool, curr_process, arg) == ERROR_VALUE ) {
if( !prev_process )
pool->processes = curr_process->next;
else
prev_process->next = curr_process->next;
free( curr_process->stack );
free( curr_process );
curr_process = prev_process;
--processes_num;
}
break;
}
prev_process = curr_process;
curr_process = next_process;
++processes_num;
}
while( processes_num > pool->max_threads_num ) {
int process_num;
int curr_process_num;
process_num = (int)( vm_random(&(pool->vm_random_data))*1.0*processes_num/
( VM_RAND_MAX + 1.0 ) );
/*
process_num = (int)( rand()*1.0*processes_num/
( RAND_MAX + 1.0 ) );
*/
curr_process_num = 0;
curr_process = pool->processes;
prev_process = NULL;
while( curr_process_num != process_num ) {
prev_process = curr_process;
curr_process = curr_process->next;
++curr_process_num;
}
if( prev_process )
prev_process->next = curr_process->next;
else
pool->processes = curr_process->next;
free( curr_process->stack );
free( curr_process );
--processes_num;
}
}