3 #include <stdio.h> // temporary
11 struct process *processes;
16 struct lru_item lru_head, *victim;
18 void process_init(int n, int spare) {
19 processes = calloc(n, sizeof(struct process));
25 process_avail = core_table.avail + swap_table.avail - spare;
26 #else /* INDIRECT_SWAP */
27 process_avail = core_table.avail + swap_block_pool.avail - spare;
28 #endif /* INDIRECT_SWAP */
29 #else /* INDIRECT_CORE */
31 process_avail = core_block_pool.avail + swap_table.avail - spare;
32 #else /* INDIRECT_SWAP */
33 process_avail = core_block_pool.avail + swap_block_pool.avail - spare;
34 #endif /* INDIRECT_SWAP */
35 if (process_avail > core_table.avail)
36 process_avail = core_table.avail;
37 #endif /* INDIRECT_CORE */
38 if (process_avail > swap_table.avail)
39 process_avail = swap_table.avail;
40 printf("process_avail %d\n", process_avail);
42 lru_head.prev = &lru_head;
43 lru_head.next = &lru_head;
47 static void do_swap_read_write(
48 struct process *process,
49 struct process_calc *calc,
56 calc->core_origin + calc->in_core_block,
57 calc->swap_origin + calc->in_core_block,
61 #else /* INDIRECT_SWAP */
62 int core_block, swap_block, i;
64 core_block = calc->core_origin + calc->in_core_block;
65 swap_block = calc->swap_origin + calc->in_core_block;
67 for (i = 0; i < blocks; ++i)
69 printf(" %s%d", dir ? "->" : "<-", swap_table_mem[swap_block + i]);
72 swap_table_mem[swap_block + i],
78 #endif /* INDIRECT_SWAP */
79 #else /* INDIRECT_CORE */
80 int core_block, swap_block, i;
82 core_block = calc->core_origin + calc->in_core_block;
83 swap_block = calc->swap_origin + calc->in_core_block;
85 for (i = 0; i < blocks; ++i)
88 printf(" %d%s", core_table_mem[core_block + i], dir ? "->" : "<-");
89 #else /* INDIRECT_SWAP */
90 printf(" %d%s%d", core_table_mem[core_block + i], dir ? "->" : "<-", swap_table_mem[swap_block + i]);
93 core_table_mem[core_block + i],
96 #else /* INDIRECT_SWAP */
97 swap_table_mem[swap_block + i],
104 #endif /* INDIRECT_CORE */
107 // note: swap_out argument can be negative, indicates a no-op
108 // note: not allowed to move any core, or caller must refresh
109 static bool do_swap_out(int swap_out) {
110 struct process *process;
111 struct process_calc calc;
114 for (; swap_out > 0; swap_out -= blocks) {
116 if (swap_block_pool.avail == 0)
118 #endif /* INDIRECT_SWAP */
120 assert(victim->prev != &lru_head);
121 process = (struct process *)(
122 (char *)victim->prev - offsetof(struct process, lru_item)
124 process_calc(process, &calc);
126 // calculate amount to swap out
127 blocks = calc.in_core_block - calc.block_base;
129 if (blocks > swap_block_pool.avail)
130 blocks = swap_block_pool.avail;
131 #endif /* INDIRECT_SWAP */
132 if (blocks > swap_out)
134 printf("victim %d, swap out %d of %d\n", (int)(process - processes), blocks, calc.in_core_block - calc.block_base);
136 // adjust swap pointer
137 calc.in_core_block -= blocks;
139 process->in_core_block = calc.in_core_block;
142 // transfer data to swap
147 swap_table_mem + calc.swap_origin + calc.in_core_block,
151 #endif /* INDIRECT_SWAP */
152 printf("write core [%d,%d) to swap [%d,%d)\n", calc.core_origin + calc.in_core_block, calc.core_origin + calc.in_core_block + blocks, calc.swap_origin + calc.in_core_block, calc.swap_origin + calc.in_core_block + blocks);
153 do_swap_read_write(process, &calc, blocks, true);
157 core_table_mem + calc.core_origin + calc.in_core_block,
160 #endif /* INDIRECT_CORE */
162 // see if victim fully swapped out
163 if (calc.in_core_block > calc.block_base) {
164 #ifndef INDIRECT_CORE
165 // no, reduce core allocation
170 calc.in_core_block - calc.block_base,
171 POOL_ALLOC_MODE_MOVEABLE | POOL_ALLOC_MODE_REALLOC,
175 #endif /* ! INDIRECT_CORE */
177 // in this case there can't be any further victim to swap
178 // report whether aborted due to swap space or user request
179 return swap_out == blocks;
181 printf("victimized %d\n", (int)(process - processes));
183 #ifndef INDIRECT_CORE
184 // remove from core pool
185 pool_free(&core_table, &process->core_item);
186 process->flags &= ~PROCESS_FLAGS_CORE_ITEM;
187 #endif /* ! INDIRECT_CORE */
188 victim = &process->lru_item;
193 static int calc_blocks(int para_base, int para_limit) {
195 ((para_limit + (BLOCK_PARAS - 1)) >> BLOCK_PARAS_SHIFT) -
196 (para_base >> BLOCK_PARAS_SHIFT);
200 struct process *process,
205 int block_base, block_limit, blocks, blocks_change;
206 struct process_calc calc;
210 block_base = para_base >> BLOCK_PARAS_SHIFT;
211 block_limit = (para_limit + (BLOCK_PARAS - 1)) >> BLOCK_PARAS_SHIFT;
212 blocks = block_limit - block_base;
215 blocks_change = blocks;
216 if ((mode & PROCESS_ALLOC_MODE_REALLOC) == 0) {
217 // alloc, must not be already allocated
218 assert((process->flags & PROCESS_FLAGS_ACTIVE) == 0);
220 // set up dummy calculations
221 calc.block_base = block_base;
222 calc.block_limit = block_base;
223 calc.core_origin = 0;
226 // realloc, must be already allocated
227 assert(process->flags & PROCESS_FLAGS_ACTIVE);
229 // for now, not allowed to resize both ends at once
230 // (in case we free physical blocks then fail to resize)
232 para_base == process->para_base ||
233 para_limit == process->para_limit
236 // must be fully in core
237 process_calc(process, &calc);
238 assert(calc.in_core_block == calc.block_limit);
239 #ifndef INDIRECT_CORE
240 assert(process->flags & PROCESS_FLAGS_CORE_ITEM);
241 #endif /* ! INDIRECT_CORE */
243 old_blocks = calc.block_limit - calc.block_base;
244 blocks_change -= old_blocks;
246 if (process_avail < blocks_change)
256 0 //calc.block_base - block_base
261 #ifndef INDIRECT_CORE
262 // free up as much core as we need to
263 rassert(do_swap_out(blocks_change - core_table.avail));
271 mode | POOL_ALLOC_MODE_MOVEABLE,
272 calc.block_base - block_base
275 #else /* INDIRECT_CORE */
276 // discard physical blocks as needed
277 // note: base pointer is garbage in the alloc case
280 core_table_mem + calc.core_origin + calc.block_base,
281 block_base - calc.block_base
285 core_table_mem + calc.core_origin + block_limit,
286 calc.block_limit - block_limit
296 calc.block_base - block_base
299 // note: if we get to here we are resizing larger,
300 // so we can't have freed any physical blocks above
301 if ((mode & PROCESS_ALLOC_MODE_REALLOC) == 0)
302 pool_free(&swap_table, &process->swap_item);
310 0 //calc.block_base - block_base
315 calc.core_origin = process->core_item.base - block_base;
317 // free up as much core as we need to
318 rassert(do_swap_out(blocks_change - core_block_pool.avail));
320 // populate physical blocks as needed
324 core_table_mem + calc.core_origin + block_base,
325 calc.block_base - block_base
329 core_table_mem + calc.core_origin + calc.block_limit,
330 block_limit - calc.block_limit
333 #endif /* INDIRECT_CORE */
335 // for alloc, perform remaining initialization
336 if ((process->flags & PROCESS_ALLOC_MODE_REALLOC) == 0) {
337 // insert at head of LRU list
338 process->lru_item.prev = &lru_head;
339 process->lru_item.next = lru_head.next;
340 process->lru_item.prev->next = &process->lru_item;
341 process->lru_item.next->prev = &process->lru_item;
343 #ifndef INDIRECT_CORE
344 process->flags = PROCESS_FLAGS_ACTIVE | PROCESS_FLAGS_CORE_ITEM;
345 #else /* INDIRECT_CORE */
346 process->flags = PROCESS_FLAGS_ACTIVE;
347 #endif /* INDIRECT_CORE */
350 // track total allocation
351 process->para_base = para_base;
352 process->para_limit = para_limit;
354 process->in_core_block = block_limit;
356 process_avail -= blocks_change;
360 void process_run(struct process *process) {
361 struct process_calc calc;
364 // must be already allocated
365 assert(process->flags & PROCESS_FLAGS_ACTIVE);
367 // remove from LRU list
368 if (victim == &process->lru_item)
369 victim = process->lru_item.next;
370 process->lru_item.prev->next = process->lru_item.next;
371 process->lru_item.next->prev = process->lru_item.prev;
373 // loop to swap out then swap in
374 process_calc(process, &calc);
376 swap_in = calc.block_limit - calc.in_core_block;
377 #ifndef INDIRECT_CORE
378 (process->flags & PROCESS_FLAGS_CORE_ITEM) == 0 || swap_in > 0;
384 // free up as much core as we can
385 #ifndef INDIRECT_CORE
386 do_swap_out(swap_in - core_table.avail);
387 blocks = core_table.avail;
388 #else /* INDIRECT_CORE */
389 do_swap_out(swap_in - core_block_pool.avail);
390 blocks = core_block_pool.avail;
391 #endif /* INDIRECT_CORE */
392 if (blocks > swap_in)
395 #ifndef INDIRECT_CORE
396 // increase core allocation
401 calc.in_core_block - calc.block_base + blocks,
402 process->flags & PROCESS_FLAGS_CORE_ITEM ?
403 POOL_ALLOC_MODE_MOVEABLE | POOL_ALLOC_MODE_REALLOC :
404 POOL_ALLOC_MODE_MOVEABLE,
408 process->flags |= PROCESS_FLAGS_CORE_ITEM;
409 calc.core_origin = process->core_item.base - calc.block_base;
410 #endif /* ! INDIRECT_CORE */
412 // transfer data to core
417 core_table_mem + calc.core_origin + calc.in_core_block,
421 #endif /* INDIRECT_CORE */
422 printf("read swap [%d,%d) to core [%d,%d)\n", calc.swap_origin + calc.in_core_block, calc.swap_origin + calc.in_core_block + blocks, calc.core_origin + calc.in_core_block, calc.core_origin + calc.in_core_block + blocks);
423 do_swap_read_write(process, &calc, blocks, false);
427 swap_table_mem + calc.swap_origin + calc.in_core_block,
430 #endif /* INDIRECT_SWAP */
432 // adjust swap pointer
433 calc.in_core_block += blocks;
435 process->in_core_block = calc.in_core_block;
436 #endif /* INDIRECT_CORE */
439 // insert at head of LRU list
440 process->lru_item.prev = &lru_head;
441 process->lru_item.next = lru_head.next;
442 process->lru_item.prev->next = &process->lru_item;
443 process->lru_item.next->prev = &process->lru_item;
446 void process_free(struct process *process) {
449 #endif /* INDIRECT_SWAP */
451 // must be already allocated
452 assert(process->flags & PROCESS_FLAGS_ACTIVE);
454 // remove from LRU list
455 if (victim == &process->lru_item)
456 victim = process->lru_item.next;
457 process->lru_item.prev->next = process->lru_item.next;
458 process->lru_item.next->prev = process->lru_item.prev;
461 // calculate blocks before freeing anything
462 #ifndef INDIRECT_CORE
464 process->flags & PROCESS_FLAGS_CORE_ITEM ?
465 process->core_item.limit - process->core_item.base :
467 #else /* INDIRECT_CORE */
469 process->in_core_block - (process->para_base >> BLOCK_PARAS_SHIFT);
470 #endif /* INDIRECT_CORE */
472 process->swap_item.limit - process->swap_item.base - block;
473 #endif /* INDIRECT_SWAP */
475 // remove from core pool
476 #ifndef INDIRECT_CORE
477 if (process->flags & PROCESS_FLAGS_CORE_ITEM)
478 pool_free(&core_table, &process->core_item);
479 #else /* INDIRECT_CORE */
482 core_table_mem + process->core_item.base,
485 #else /* ! INDIRECT_SWAP */
486 process->in_core_block - (process->para_base >> BLOCK_PARAS_SHIFT)
487 #endif /* ! INDIRECT_SWAP */
489 pool_free(&core_table, &process->core_item);
490 #endif /* INDIRECT_CORE */
492 // remove from swap pool
496 swap_table_mem + process->swap_item.base + block,
499 #endif /* INDIRECT_SWAP */
500 pool_free(&swap_table, &process->swap_item);
502 // track total allocation
503 process_avail += calc_blocks(process->para_base, process->para_limit);
507 void process_calc(struct process *process, struct process_calc *calc) {
509 process->para_base >> BLOCK_PARAS_SHIFT;
511 (process->para_limit + (BLOCK_PARAS - 1)) >> BLOCK_PARAS_SHIFT;
514 process->core_item.limit - process->core_item.base ==
515 calc->block_limit - calc->block_base
517 #endif /* INDIRECT_CORE */
518 // note: following can fail during realloc because swap reallocated first:
520 // process->swap_item.limit - process->swap_item.base ==
521 // calc->block_limit - calc->block_base
524 #ifndef INDIRECT_CORE
525 calc->core_origin = (
526 process->flags & PROCESS_FLAGS_CORE_ITEM ? process->core_item.base : 0
527 ) - calc->block_base;
528 #else /* INDIRECT_CORE */
529 calc->core_origin = process->core_item.base - calc->block_base;
530 assert(calc->core_origin == process->core_item.limit - calc->block_limit);
532 // note: following can fail during realloc because swap reallocated first:
533 calc->swap_origin = process->swap_item.base - calc->block_base;
534 //assert(calc->swap_origin == process->swap_item.limit - calc->block_limit);
536 #ifndef INDIRECT_CORE
537 calc->in_core_block = (
538 process->flags & PROCESS_FLAGS_CORE_ITEM ? process->core_item.limit : 0
539 ) - calc->core_origin;
540 //printf("para [%d,%d) in_core_blocks %d block [%d,%d) core_origin %d swap_origin %d in_core_block %d\n", process->para_base, process->para_limit, process->flags & PROCESS_FLAGS_CORE_ITEM ? process->core_item.limit - process->core_item.base : 0, calc->block_base, calc->block_limit, calc->core_origin, calc->swap_origin, calc->in_core_block);
542 calc->in_core_block = process->in_core_block;
543 //printf("para [%d,%d) in_core_blocks %d block [%d,%d) core_origin %d swap_origin %d in_core_block %d\n", process->para_base, process->para_limit, process->in_core_blocks, calc->block_base, calc->block_limit, calc->core_origin, calc->swap_origin, calc->in_core_block);