diff options
Diffstat (limited to 'kscreensaver/kdesavers/vm.c')
-rw-r--r-- | kscreensaver/kdesavers/vm.c | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/kscreensaver/kdesavers/vm.c b/kscreensaver/kdesavers/vm.c new file mode 100644 index 00000000..6d4a1af2 --- /dev/null +++ b/kscreensaver/kdesavers/vm.c @@ -0,0 +1,264 @@ +/* + * 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; + } +} |