4 * Copyright (c) 2000 Artur Rataj
5 * Distributed under the terms of the GNU General Public License
11 #define ERROR_VALUE INT_MAX
13 int vm_init_pool( struct tvm_pool
** pool
,
16 int max_threads_num
) {
19 ( *pool
) = (struct tvm_pool
*)malloc( sizeof(struct tvm_pool
) );
20 ( *pool
)->area_size
= area_size
;
21 ( *pool
)->area
= (int*)malloc( (*pool
)->area_size
*sizeof(int) );
22 ( *pool
)->processes
= NULL
;
23 ( *pool
)->max_stack_size
= max_stack_size
;
24 ( *pool
)->max_threads_num
= max_threads_num
;
25 vm_enable_reverse( *pool
, 0 );
26 for( position
= 0; position
< (*pool
)->area_size
; ++position
)
27 ( *pool
)->area
[position
] = VM_OP_STOP
;
31 void vm_done_pool( struct tvm_pool
* pool
) {
32 struct tvm_process
* curr_process
;
34 curr_process
= pool
->processes
;
35 while( curr_process
) {
36 struct tvm_process
* tmp_process
;
38 tmp_process
= curr_process
;
39 curr_process
= curr_process
->next
;
40 free( tmp_process
->stack
);
46 static int push( struct tvm_pool
* pool
,
47 struct tvm_process
* process
,
49 if( process
->stack_top
== pool
->max_stack_size
)
52 process
->stack
[process
->stack_top
++] = value
;
56 static int pop( struct tvm_pool
* pool
,
57 struct tvm_process
* process
) {
58 if( process
->stack_top
== 0 )
62 return process
->stack
[--process
->stack_top
];
66 void vm_modify( struct tvm_pool
* pool
,
69 pool
->area
[position
] = op
;
72 void vm_exec( struct tvm_pool
* pool
,
76 struct tvm_process
* new_process
;
78 new_process
= (struct tvm_process
*)malloc( sizeof(struct tvm_process
) );
79 new_process
->position
= position
;
80 new_process
->stack
= (int*)malloc( pool
->max_stack_size
*sizeof(int) );
81 new_process
->stack_top
= 0;
82 new_process
->age
= age
;
83 new_process
->reverse
= reverse
;
84 new_process
->next
= pool
->processes
;
85 pool
->processes
= new_process
;
88 void vm_enable_reverse( struct tvm_pool
* pool
,
90 pool
->reverse_enabled
= enabled
;
93 int vm_get_reverse( struct tvm_pool
* pool
) {
94 if( pool
->reverse_enabled
)
95 return (int)( vm_random(&(pool
->vm_random_data
))*2.0/
96 ( VM_RAND_MAX
+ 1.0 ) );
101 void vm_iterate( struct tvm_pool
* pool
,
103 struct tvm_process
* prev_process
;
104 struct tvm_process
* curr_process
;
105 struct tvm_process
* next_process
;
110 curr_process
= pool
->processes
;
111 while( curr_process
) {
118 next_process
= curr_process
->next
;
119 op
= pool
->area
[curr_process
->position
];
120 if( curr_process
->reverse
)
121 --curr_process
->position
;
123 ++curr_process
->position
;
124 curr_process
->position
= ( curr_process
->position
+ pool
->area_size
)%
132 pool
->processes
= curr_process
->next
;
134 prev_process
->next
= curr_process
->next
;
135 free( curr_process
->stack
);
136 free( curr_process
);
137 curr_process
= prev_process
;
142 if( (arg
= pop( pool
, curr_process
)) == ERROR_VALUE
) {
144 pool
->processes
= curr_process
->next
;
146 prev_process
->next
= curr_process
->next
;
147 free( curr_process
->stack
);
148 free( curr_process
);
149 curr_process
= prev_process
;
152 arg
= curr_process
->position
+ arg
;
154 arg
+= pool
->area_size
;
155 if( arg
>= pool
->area_size
)
156 arg
-= pool
->area_size
;
157 vm_exec( pool
, arg
, curr_process
->age
, vm_get_reverse(pool
) );
162 if( (arg
= pop( pool
, curr_process
)) == ERROR_VALUE
) {
164 pool
->processes
= curr_process
->next
;
166 prev_process
->next
= curr_process
->next
;
167 free( curr_process
->stack
);
168 free( curr_process
);
169 curr_process
= prev_process
;
171 } else if( (arg_2
= pop( pool
, curr_process
)) == ERROR_VALUE
) {
173 pool
->processes
= curr_process
->next
;
175 prev_process
->next
= curr_process
->next
;
176 free( curr_process
->stack
);
177 free( curr_process
);
178 curr_process
= prev_process
;
180 } else if( 1 && (arg_3
= pop( pool
, curr_process
)) == ERROR_VALUE
) {
182 pool
->processes
= curr_process
->next
;
184 prev_process
->next
= curr_process
->next
;
185 free( curr_process
->stack
);
186 free( curr_process
);
187 curr_process
= prev_process
;
193 arg
= curr_process
->position
+ arg
;
195 arg
+= pool
->area_size
;
196 if( arg
>= pool
->area_size
)
197 arg
-= pool
->area_size
;
198 arg_2
= curr_process
->position
+ arg_2
;
200 arg_2
+= pool
->area_size
;
201 if( arg_2
>= pool
->area_size
)
202 arg_2
-= pool
->area_size
;
203 if( curr_process
->reverse
)
207 for( count
= 0; count
< arg_3
; ++count
) {
211 offset
= count
*direction
+ pool
->area_size
;
212 i
= pool
->area
[( arg_2
+ offset
)%pool
->area_size
];
213 j
= pool
->area
[( arg_2
+ offset
)%pool
->area_size
] = pool
->area
[( arg
+ offset
)%pool
->area_size
];
214 if( modified
&& i
!= j
)
215 modified
[( arg_2
+ offset
)%pool
->area_size
] = 1;
220 default: /* >= VM_OP_PUSH */
221 arg
= op
- VM_OP_PUSH
;
222 if( push(pool
, curr_process
, arg
) == ERROR_VALUE
) {
224 pool
->processes
= curr_process
->next
;
226 prev_process
->next
= curr_process
->next
;
227 free( curr_process
->stack
);
228 free( curr_process
);
229 curr_process
= prev_process
;
234 prev_process
= curr_process
;
235 curr_process
= next_process
;
238 while( processes_num
> pool
->max_threads_num
) {
240 int curr_process_num
;
242 process_num
= (int)( vm_random(&(pool
->vm_random_data
))*1.0*processes_num
/
243 ( VM_RAND_MAX
+ 1.0 ) );
245 process_num = (int)( rand()*1.0*processes_num/
246 ( RAND_MAX + 1.0 ) );
248 curr_process_num
= 0;
249 curr_process
= pool
->processes
;
251 while( curr_process_num
!= process_num
) {
252 prev_process
= curr_process
;
253 curr_process
= curr_process
->next
;
257 prev_process
->next
= curr_process
->next
;
259 pool
->processes
= curr_process
->next
;
260 free( curr_process
->stack
);
261 free( curr_process
);