Changeset 9012
- Timestamp:
- 08/18/11 16:00:15 (21 months ago)
- Location:
- branches/Orange-Branch/src/client/usrint
- Files:
-
- 2 modified
Legend:
- Unmodified
- Added
- Removed
-
branches/Orange-Branch/src/client/usrint/ucache.c
r9001 r9012 1 1 /* 2 * (C) 2011 Clemson University and The University of Chicago2 * (C) 2011 Clemson University 3 3 * 4 4 * See COPYING in top-level directory. 5 5 */ 6 6 7 /* Experimental cache for user data 8 * Currently under development. 9 */ 10 11 /* 12 * Note: When unsigned ints are set to NIL, their values are based on type: 7 /* Experimental cache for user data 8 * Currently under development. 9 * 10 * Note: When unsigned ints are set to NIL, their values are based on type: 13 11 * ex: 16 0xFFFF 14 12 * 32 0XFFFFFFFF 15 13 * 64 0XFFFFFFFFFFFFFFFF 16 * ALL EQUAL THE SIGNED REPRESENTATION OF -1, CALLED NIL .14 * ALL EQUAL THE SIGNED REPRESENTATION OF -1, CALLED NIL IN ucache.h 17 15 */ 18 16 19 17 #include "ucache.h" 20 18 19 /* Global Variables */ 21 20 static union user_cache_u *ucache; 22 21 static int ucache_blk_cnt; 23 static ucache_lock_t *ucache_lock; /* For maintaining concurrency */ 24 static FILE *out; /* For Logging Purposes */ 22 static ucache_lock_t *ucache_lock; /* For maintaining concurrency */ 23 static FILE *out; /* For Logging Purposes */ 24 25 /* Internal Only Function Declarations */ 26 27 /* Global Cache Lock */ 28 static int lock_init(ucache_lock_t * lock); 29 static int lock_lock(ucache_lock_t * lock); 30 static int lock_unlock(ucache_lock_t * lock); 31 static int lock_destroy(ucache_lock_t * lock); 32 33 /* Initialization */ 34 static void add_free_mtbls(int blk); 35 static void init_memory_table(int blk, int ent); 36 37 /* Gets */ 38 static int get_next_free_mtbl(uint32_t *free_mtbl_blk, uint16_t *free_mtbl_ent); 39 static int get_free_fent(void); 40 static int get_free_ment(struct mem_table_s *mtbl); 41 static uint16_t get_free_blk(void); 42 43 /* Puts */ 44 static void put_free_mtbl(struct mem_table_s *mtbl, struct file_ent_s *file); 45 static void put_free_fent(int fent); 46 static void put_free_ment(struct mem_table_s *mtbl, int ent); 47 static void put_free_blk(int blk); 48 49 /* File Entry Chain Iterator */ 50 static int file_done(int index); 51 static int file_next(struct file_table_s *ftbl, int index); 52 53 /* Memory Entry Chain Iterator */ 54 static int ment_done(int index); 55 static int ment_next(struct mem_table_s *mtbl, int index); 56 57 /* Dirty List Iterator */ 58 static int dirty_done(uint16_t index); 59 static int dirty_next(struct mem_table_s *mtbl, uint16_t index); 60 61 /* File and Memory Insertion */ 62 static struct mem_table_s *insert_file(uint32_t fs_id, uint64_t handle); 63 static void *insert_mem(struct mem_table_s *mtbl, uint64_t offset); 64 static void *set_item(struct mem_table_s *mtbl,uint64_t offset, uint16_t index); 65 66 /* File and Memory Lookup */ 67 static struct mem_table_s *lookup_file( 68 uint32_t fs_id, 69 uint64_t handle, 70 uint32_t *file_mtbl_blk, /* Can be NULL if not desired TODO: remove these later? */ 71 uint16_t *file_mtbl_ent, 72 uint16_t *file_ent_index, 73 uint16_t *file_ent_prev_index 74 ); 75 static void *lookup_mem(struct mem_table_s *mtbl, 76 uint64_t offset, 77 uint32_t *item_index, 78 uint16_t *mem_ent_index, 79 uint16_t *mem_ent_prev_index 80 ); 81 82 /* File and Memory Entry Removal */ 83 static int remove_file(uint32_t fs_id, uint64_t handle); 84 static void remove_all_memory_entries(struct mem_table_s *mtbl); 85 static int remove_mem(struct mem_table_s *mtbl, uint64_t offset); 86 87 /* Eviction Utilities */ 88 static int evict_file(unsigned int index); 89 static int locate_max_mtbl(struct mem_table_s **mtbl); 90 static void update_lru(struct mem_table_s *mtbl, uint16_t index); 91 static int evict_LRU(struct mem_table_s *mtbl); 92 93 /* List Printing Functions */ 94 /* 95 * static void print_lru(struct mem_table_s *mtbl); 96 * static void print_dirty(struct mem_table_s *mtbl); 97 */ 25 98 26 99 /* Externally Visible API … … 29 102 */ 30 103 31 /* Initializes the cache.104 /** Initializes the cache. 32 105 * Mainly, it aquires a shared memory segment used to cache data. 33 106 * … … 37 110 * Currently using posix semaphores 38 111 */ 39 externvoid ucache_initialize(void)40 { 41 /* Aquire shared memory for ucache_lock*/112 void ucache_initialize(void) 113 { 114 /* Aquire shared memory for ucache_lock */ 42 115 ucache_lock = shmat(shmget(ftok(GET_KEY_FILE, 'a'), 43 116 sizeof(ucache_lock_t), CACHE_FLAGS), NULL, AT_FLAGS); 44 ucache_lock_init(ucache_lock); 45 ucache_lock_lock(ucache_lock); 46 /* Aquire shared memory for lock for ucache */ 117 lock_init(ucache_lock); 118 lock_lock(ucache_lock); 119 #if LOCK_TYPE==0 120 int lockVal; 121 ucache_lock_getvalue(ucache_lock, &lockVal); 122 printf("lock value = %d\n", lockVal); 123 #endif 124 /* Aquire shared memory for lock for ucache */ 47 125 int key, id, i; 48 126 char *key_file_path; 49 127 /* Direct output */ 50 128 if(!out)out = stdout; 51 /* Note: had to set: kernel.shmmax amd kernel.shmall*/129 /* Note: had to set: kernel.shmmax amd kernel.shmall */ 52 130 /* set up shared memory region */ 53 131 key_file_path = GET_KEY_FILE; … … 76 154 for (i = 0; i < FILE_TABLE_HASH_MAX; i++) 77 155 { 156 ucache->ftbl.file[i].tag_handle = NIL; 157 ucache->ftbl.file[i].tag_id = NIL; 78 158 ucache->ftbl.file[i].mtbl_blk = NIL; 79 159 ucache->ftbl.file[i].mtbl_ent = NIL; … … 89 169 } 90 170 ucache->ftbl.file[FILE_TABLE_ENTRY_COUNT - 1].next = NIL; 91 ucache_lock_unlock(ucache_lock);92 } 93 94 externint ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle)95 { 96 ucache_lock_lock(ucache_lock);171 lock_unlock(ucache_lock); 172 } 173 174 int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 175 { 176 lock_lock(ucache_lock); 97 177 struct mem_table_s *mtbl= lookup_file( 98 178 (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); … … 101 181 insert_file((uint32_t)*fs_id, (uint64_t)*handle); 102 182 } 103 ucache_lock_unlock(ucache_lock);183 lock_unlock(ucache_lock); 104 184 return 1; 105 185 } 106 186 107 /* Returns ptr to block in cache based on file and offset*/108 externvoid *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset)109 { 110 ucache_lock_lock(ucache_lock);187 /** Returns ptr to block in cache based on file and offset */ 188 void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 189 { 190 lock_lock(ucache_lock); 111 191 struct mem_table_s *mtbl= lookup_file( 112 192 (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 113 193 if((int)mtbl!=NIL) 114 194 { 115 char *retVal = (char *)lookup_mem(mtbl, (uint64_t)offset, NULL, NULL, NULL); 116 ucache_lock_unlock(ucache_lock); 195 char *retVal = (char *)lookup_mem(mtbl, (uint64_t)offset, NULL, NULL, 196 NULL); 197 lock_unlock(ucache_lock); 117 198 return((void *)retVal); 118 199 } 119 ucache_lock_unlock(ucache_lock);200 lock_unlock(ucache_lock); 120 201 return (void *)NIL; 121 202 } 122 203 123 /* Inserts block of data into cache */ 124 extern void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 125 { 126 ucache_lock_lock(ucache_lock); 204 /** Prepares the data structures for block storage. 205 * On success, returns a pointer to where the block of data should be written. 206 * On failure, returns NIL. 207 */ 208 void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 209 { 210 lock_lock(ucache_lock); 127 211 struct mem_table_s *mtbl= lookup_file( 128 212 (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 129 213 if((int)mtbl==NIL) 130 214 { 131 ucache_lock_unlock(ucache_lock);215 lock_unlock(ucache_lock); 132 216 return (void *)NIL; 133 217 } 134 218 else 135 219 { 136 remove_mem(mtbl, (uint64_t)offset); 220 if(remove_mem(mtbl, (uint64_t)offset)==NIL){ 221 lock_unlock(ucache_lock); 222 return (void *)NIL; 223 } 137 224 char * retVal= insert_mem(mtbl, (uint64_t)offset); 138 ucache_lock_unlock(ucache_lock);225 lock_unlock(ucache_lock); 139 226 return ((void *)retVal); 140 227 } 141 228 } 142 229 143 /* Removes a cached block of data from mtbl*/144 externint ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset)145 { 146 ucache_lock_lock(ucache_lock);230 /** Removes a cached block of data from mtbl */ 231 int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 232 { 233 lock_lock(ucache_lock); 147 234 struct mem_table_s *mtbl= lookup_file( 148 235 (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); … … 150 237 { 151 238 int retVal = remove_mem(mtbl, (uint64_t)offset); 152 ucache_lock_unlock(ucache_lock);239 lock_unlock(ucache_lock); 153 240 return retVal; 154 241 } 155 ucache_lock_unlock(ucache_lock);242 lock_unlock(ucache_lock); 156 243 return NIL; 157 244 } 158 245 159 /* Flushes dirty blocks to the I/O Nodes*/160 externint ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle)161 { 162 ucache_lock_lock(ucache_lock);246 /** Flushes dirty blocks to the I/O Nodes */ 247 int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 248 { 249 lock_lock(ucache_lock); 163 250 struct mem_table_s *mtbl= lookup_file( 164 251 (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); … … 174 261 break; 175 262 } 176 /* //flush block to disk */ 263 /* //flush block to disk - 2 means write */ 264 //iocommon_readorwrite_nocache(2,); 177 265 } 178 266 mtbl->dirty_list = NIL; 179 ucache_lock_unlock(ucache_lock);267 lock_unlock(ucache_lock); 180 268 return 1; 181 269 } 182 270 183 /* Removes all memory entries in the mtbl corresponding to the file info184 * provided as parameters. It also removes the mtbl and the file entry from185 * the cache.186 */ 187 externint ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle)188 { 189 ucache_lock_lock(ucache_lock);271 /** Removes all memory entries in the mtbl corresponding to the file info 272 * provided as parameters. It also removes the mtbl and the file entry from 273 * the cache. 274 */ 275 int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 276 { 277 lock_lock(ucache_lock); 190 278 uint32_t file_mtbl_blk; 191 279 uint16_t file_mtbl_ent; … … 201 289 if((int)mtbl==NIL) 202 290 { 203 ucache_lock_unlock(ucache_lock);291 lock_unlock(ucache_lock); 204 292 return NIL; 205 293 } … … 208 296 put_free_mtbl(mtbl, file); 209 297 put_free_fent(file_ent_index); 210 ucache_lock_unlock(ucache_lock);298 lock_unlock(ucache_lock); 211 299 return 1; 212 300 } 213 301 214 /* Use the following function to decrement the reference count of a particular 215 * mtbl. This function must be called when a user's code is done with the 216 * pointer provided via any of the pointer returning external functions listed 217 * above. 218 */ 219 extern int ucache_dec_ref_cnt(struct mem_table_s * mtbl) 220 { 221 ucache_lock_lock(ucache_lock); 222 /* decrement ref_cnt of mtbl */ 223 mtbl->ref_cnt--; 224 ucache_lock_unlock(ucache_lock); 225 } 226 /***************************************** End of Externally Visible API */ 227 228 229 /* Beginning of internal only (static) functions 230 */ 231 232 /* Internally Available Locking Mechanism - using POSIX semaphores 233 */ 234 static int ucache_lock_init(ucache_lock_t * lock) 302 /** Decrements the reference count of a particular mtbl. */ 303 void ucache_dec_ref_cnt(struct mem_table_s * mtbl) 304 { 305 lock_lock(ucache_lock); 306 /* decrement ref_cnt of mtbl */ 307 if(mtbl->ref_cnt!=0) 308 mtbl->ref_cnt--; 309 lock_unlock(ucache_lock); 310 } 311 312 /** Increments the reference count of a particular mtbl. */ 313 void ucache_inc_ref_cnt(struct mem_table_s * mtbl) 314 { 315 lock_lock(ucache_lock); 316 /* increment ref_cnt of mtbl */ 317 mtbl->ref_cnt++; 318 lock_unlock(ucache_lock); 319 } 320 321 /** Dumps all cache related information. */ 322 void ucache_info( 323 FILE *out, 324 union user_cache_u *ucache, 325 ucache_lock_t *ucache_lock) 326 { 327 fprintf(out, "\n#defines:\n"); 328 /* First, print many of the #define values */ 329 fprintf(out, "MEM_TABLE_ENTRY_COUNT = %d\n", MEM_TABLE_ENTRY_COUNT); 330 fprintf(out, "FILE_TABLE_ENTRY_COUNT = %d\n", FILE_TABLE_ENTRY_COUNT); 331 fprintf(out, "CACHE_BLOCK_SIZE_K = %d\n", CACHE_BLOCK_SIZE_K); 332 fprintf(out, "MEM_TABLE_HASH_MAX = %d\n", MEM_TABLE_HASH_MAX); 333 fprintf(out, "FILE_TABLE_HASH_MAX = %d\n", FILE_TABLE_HASH_MAX); 334 fprintf(out, "MTBL_PER_BLOCK = %d\n", MTBL_PER_BLOCK ); 335 fprintf(out, "GET_KEY_FILE = %s\n", GET_KEY_FILE); 336 fprintf(out, "PROJ_ID = %d\n", PROJ_ID); 337 fprintf(out, "BLOCKS_IN_CACHE = %d\n", BLOCKS_IN_CACHE); 338 fprintf(out, "CACHE_SIZE = %d(B)\t%d(MB)\n", CACHE_SIZE, 339 (CACHE_SIZE/(1024*1024))); 340 fprintf(out, "AT_FLAGS = %d\n", AT_FLAGS); 341 fprintf(out, "SVSHM_MODE = %d\n", SVSHM_MODE); 342 fprintf(out, "CACHE_FLAGS = %d\n", CACHE_FLAGS); 343 fprintf(out, "NIL = %d\n\n", NIL); 344 345 /* Lock's Shared Memory Info */ 346 fprintf(out, "address of ucache_lock ptr:\t0X%X\n", 347 (unsigned int) &ucache_lock); 348 fprintf(out, "ucache_lock ptr:\t\t0X%X\n", (unsigned int) ucache_lock); 349 /* Lock's Value */ 350 int lockValue = 0; 351 #if LOCK_TYPE == 0 352 ucache_lock_getvalue(ucache_lock, &lockValue); 353 #endif 354 fprintf(out, "ucache_lock value = %d\n", lockValue); 355 /* ucache Shared Memory Info */ 356 fprintf(out, "address of ucache ptr:\t0X%X\n", (unsigned int)&ucache); 357 fprintf(out, "ucache ptr:\t\t0X%X\n", (unsigned int)ucache); 358 359 struct file_table_s *ftbl = &(ucache->ftbl); 360 361 /* FTBL Info */ 362 fprintf(out, "ftbl ptr:\t\t0X%X\n", (unsigned int)&(ucache->ftbl)); 363 fprintf(out, "free_blk = %d\n", (int32_t)ftbl->free_blk); 364 fprintf(out, "free_mtbl_blk = %d\n", (int32_t)ftbl->free_mtbl_blk); 365 fprintf(out, "free_mtbl_ent = %d\n", (int16_t)ftbl->free_mtbl_ent); 366 fprintf(out, "free_list = %d\n", (int16_t)ftbl->free_list); 367 368 /* Other Free Blocks */ 369 fprintf(out, "\nIterating Over Free Blocks:\n\n"); 370 unsigned int i; 371 for(i = ftbl->free_blk; (int16_t)i != NIL; i = ucache->b[i].mtbl[0]. 372 free_list) 373 { 374 fprintf(out, "Free Block:\tCurrent: %d\tNext: %d\n", i, 375 ucache->b[i].mtbl[0].free_list); 376 } 377 fprintf(out, "End of Free Blocks List\n"); 378 379 /* Iterate Over Free Mtbls */ 380 fprintf(out, "\nIterating Over Free Mtbls:\n"); 381 uint32_t current_blk = ftbl->free_mtbl_blk; 382 uint16_t current_ent = ftbl->free_mtbl_ent; 383 while((int16_t)current_blk != NIL) 384 { 385 fprintf(out, "free mtbl: block = %d\tentry = %d\n", 386 (int16_t)current_blk, (int16_t)current_ent); 387 current_blk = (uint16_t)ucache->b[current_blk].mtbl[current_ent]. 388 free_list_blk; 389 current_ent = (uint16_t)ucache->b[current_blk].mtbl[current_ent]. 390 free_list; 391 } 392 fprintf(out, "End of Free Mtbl List\n\n"); 393 394 /* Iterating Over Free File Entries */ 395 fprintf(out, "Iterating Over Free File Entries:\n"); 396 uint16_t current_fent; 397 for(current_fent = ftbl->free_list; (int16_t)current_fent!=NIL; 398 current_fent = ftbl->file[current_fent].next) 399 { 400 fprintf(out, "free file entry: index = %d\n", (int16_t)current_fent); 401 } 402 fprintf(out, "End of Free File Entry List\n\n"); 403 404 fprintf(out, "Iterating Over File Entries in Hash Table:\n\n"); 405 /* iterate over file table entries */ 406 for(i = 0; i < FILE_TABLE_HASH_MAX; i++) 407 { 408 if(((int64_t)ftbl->file[i].tag_handle != NIL) && 409 ((int64_t)ftbl->file[i].tag_handle != 0)) 410 { 411 /* iterate accross file table chain */ 412 int j; 413 for(j = i; !file_done(j); j = file_next(ftbl, j)) 414 { 415 fprintf(out, "FILE ENTRY INDEX %d ********************\n", j); 416 struct file_ent_s * fent = &(ftbl->file[j]); 417 fprintf(out, "tag_handle = 0X%llX\n", 418 (uint64_t)fent->tag_handle); 419 fprintf(out, "tag_id = 0X%X\n", (uint32_t)fent->tag_id); 420 fprintf(out, "mtbl_blk = %d\n", (int32_t)fent->mtbl_blk); 421 fprintf(out, "mtbl_ent = %d\n", (int16_t)fent->mtbl_ent); 422 fprintf(out, "next = %d\n", (int16_t)fent->next); 423 424 struct mem_table_s * mtbl = &(ucache->b[fent->mtbl_blk]. 425 mtbl[fent->mtbl_ent]); 426 fprintf(out, "\tMTBL INFO ********************\n"); 427 fprintf(out, "\tnum_blocks = %d\n", (int16_t)mtbl->num_blocks); 428 fprintf(out, "\tfree_list = %d\n", (int16_t)mtbl->free_list); 429 fprintf(out, "\tfree_list_blk = %d\n", 430 (int16_t)mtbl->free_list_blk); 431 fprintf(out, "\tlru_first = %d\n", (int16_t)mtbl->lru_first); 432 fprintf(out, "\tlru_last = %d\n", (int16_t)mtbl->lru_last); 433 fprintf(out, "\tdirty_list = %d\n", (int16_t)mtbl->dirty_list); 434 fprintf(out, "\tref_cnt = %d\n\n", (int16_t)mtbl->ref_cnt); 435 436 /* Iterate Over Memory Entries */ 437 int k; 438 for(k = 0; k < MEM_TABLE_HASH_MAX; k++) 439 { 440 if(((int64_t)mtbl->mem[k].tag != NIL) && 441 ((int64_t)mtbl->mem[k].tag != 0)) 442 { 443 int l; 444 for(l = k; !ment_done(l); l = ment_next(mtbl, l)){ 445 struct mem_ent_s * ment = &(mtbl->mem[l]); 446 fprintf(out, "\t\tMEMORY ENTRY INDEX %d ***********" 447 "*********\n", l); 448 fprintf(out, "\t\ttag = 0X%llX\n", 449 (uint64_t)ment->tag); 450 fprintf(out, "\t\titem = %d\n", 451 (int32_t)ment->item); 452 fprintf(out, "\t\tnext = %d\n", 453 (int16_t)ment->next); 454 fprintf(out, "\t\tdirty_next = %d\n", 455 (int16_t)ment->dirty_next); 456 fprintf(out, "\t\tlru_next = %d\n", 457 (int16_t)ment->lru_next); 458 fprintf(out, "\t\tlru_prev = %d\n\n", 459 (int16_t)ment->lru_prev); 460 } 461 } 462 else 463 if((uint16_t)mtbl->num_blocks != 0) 464 { 465 fprintf(out, "\tvacant memory entry @ index = %d\n", 466 k); 467 } 468 } 469 } 470 fprintf(out, "End of chain @ Hash Table Index %d\n\n", i); 471 } 472 else 473 fprintf(out, "vacant file entry @ index = %d\n", i); 474 } 475 } 476 /***************************************** End of Externally Visible API */ 477 478 479 /* Beginning of internal only (static) functions */ 480 481 /** Initializes the proper lock based on the LOCK_TYPE */ 482 static int lock_init(ucache_lock_t * lock) 235 483 { 236 484 /* Set pshared (2nd arg) to non-zero value to share semaphore b/w forked 237 485 * processes 238 486 */ 239 return sem_init(lock, 1, 1); 240 } 241 242 /* Returns 0 when lock is locked; otherwise, return -1 and sets errno*/ 243 static int ucache_lock_lock(ucache_lock_t * lock) 244 { 487 /* TODO: ability to disable locking */ 488 #if LOCK_TYPE==0 489 return sem_init(lock, 1, 1); 490 #elif LOCK_TYPE==1 491 return pthread_mutex_init(lock, NULL); 492 #elif LOCK_TYPE==2 493 return pthread_spin_init(lock, 1); 494 #endif 495 } 496 497 /** Returns 0 when lock is locked; otherwise, return -1 and sets errno */ 498 static int lock_lock(ucache_lock_t * lock) 499 { 500 #if LOCK_TYPE==0 245 501 return sem_wait(lock); 246 } 247 248 /* If successful, return zero; otherwise, return -1 and sets errno */ 249 static int ucache_lock_unlock(ucache_lock_t * lock) 250 { 502 #elif LOCK_TYPE==1 503 return pthread_mutex_lock(lock); 504 #elif LOCK_TYPE==2 505 return pthread_spin_lock(lock); 506 #endif 507 } 508 509 /** If successful, return zero; otherwise, return -1 and sets errno */ 510 static int lock_unlock(ucache_lock_t * lock) 511 { 512 #if LOCK_TYPE==0 251 513 return sem_post(lock); 252 } 253 254 /* Upon successful completion, returns zero; otherwise, returns and sets errno. 255 */ 256 static int ucache_lock_getvalue(ucache_lock_t * lock, int *sval) 514 #elif LOCK_TYPE==1 515 return pthread_mutex_unlock(lock); 516 #elif LOCK_TYPE==2 517 return pthread_spin_unlock(lock); 518 #endif 519 } 520 521 /** Upon successful completion, returns zero; 522 * Otherwise, returns -1 and sets errno. 523 */ 524 #if LOCK_TYPE==0 525 int ucache_lock_getvalue(ucache_lock_t * lock, int *sval) 257 526 { 258 527 return sem_getvalue(lock, sval); 259 528 } 260 261 /* Upon successful completion, returns zero; otherwise returns 1 and sets errno. 262 */ 263 static int ucache_lock_destroy(ucache_lock_t * lock) 264 { 529 #endif 530 531 /** Upon successful completion, returns zero. 532 * Otherwise, returns 1 and sets errno. 533 */ 534 static int lock_destroy(ucache_lock_t * lock) 535 { 536 #if LOCK_TYPE==0 265 537 return sem_destroy(lock); 266 } 267 268 /* Dirty List Iterator */ 538 #elif LOCK_TYPE==1 539 return pthread_mutex_destroy(lock); 540 #elif LOCK_TYPE==2 541 return pthread_spin_destroy(lock); 542 #endif 543 } 544 545 /* Dirty List Iterator */ 546 /** Returns true if current index is NIL, otherwise, returns 0 */ 269 547 static int dirty_done(uint16_t index) 270 548 { … … 272 550 } 273 551 552 /** Returns the next index in the dirty list for the provided mtbl and index */ 274 553 static int dirty_next(struct mem_table_s *mtbl, uint16_t index) 275 554 { … … 278 557 279 558 /* Memory Entry Chain Iterator */ 559 /** Returns true if current index is NIL, otherwise, returns 0 */ 280 560 static int ment_done(int index) 281 561 { … … 283 563 } 284 564 565 /** Returns the next index in the memory entry chain for the provided mtbl 566 * and index. 567 */ 285 568 static int ment_next(struct mem_table_s *mtbl, int index) 286 569 { … … 289 572 290 573 /* File Entry Chain Iterator */ 574 /** Returns true if current index is NIL, otherwise, returns 0 */ 291 575 static int file_done(int index) 292 576 { … … 294 578 } 295 579 580 /** Returns the next index in the file entry chain for the provided mtbl 581 * and index. 582 */ 296 583 static int file_next(struct file_table_s *ftbl, int index) 297 584 { … … 299 586 } 300 587 301 /* 302 * This function should only be called when the ftbl has no free mtbls. 588 /**This function should only be called when the ftbl has no free mtbls. 589 * It initizializes MTBL_PER_BLOCK additional mtbls in the block provided, 590 * meaning this block will no longer be used for storing file data but 591 * hash table related data instead. 303 592 */ 304 593 static void add_free_mtbls(int blk) … … 328 617 } 329 618 619 /** Initializes a mtbl which is a hash table of memory entries. 620 * The mtbl will be located at the provided entry index within 621 * the provided block. 622 */ 330 623 static void init_memory_table(int blk, int ent) 331 624 { 332 625 int i; 333 626 struct mem_table_s *mtbl = &(ucache->b[blk].mtbl[ent]); 334 335 627 mtbl->lru_first = NIL; 336 628 mtbl->lru_last = NIL; 337 629 mtbl->dirty_list = NIL; 338 630 mtbl->num_blocks = 0; 631 mtbl->ref_cnt = 0; 339 632 /* set up hash table */ 340 633 for (i = 0; i < MEM_TABLE_HASH_MAX; i++) … … 355 648 } 356 649 650 /** This function asks the file table if a free block is avaialable. 651 * If so, returns the block's index; otherwise, returns NIL. 652 */ 357 653 static uint16_t get_free_blk(void) 358 654 { … … 361 657 if((int16_t)free_blk!=NIL) 362 658 { 363 /* Use zero since free_blks have no ititialized mem tables */659 /* Use mtbl index zero since free_blks have no ititialized mem tables */ 364 660 ftbl->free_blk = ucache->b[free_blk].mtbl[0].free_list; 365 661 return free_blk; … … 369 665 } 370 666 667 /** Accepts an index corresponding to a block that is put back on the file 668 * table free list. 669 */ 371 670 static void put_free_blk(int blk) 372 671 { 373 672 if(DBG)fprintf(out, "freeing blk @ index = %d\n", blk); 374 673 struct file_table_s *ftbl = &(ucache->ftbl); 674 /* set the block's next value to the current head of the block free list */ 375 675 ucache->b[blk].mtbl[0].free_list = ftbl->free_blk; 676 /* set this to NIL, since only used when mtbl is on mtbl free list */ 376 677 ucache->b[blk].mtbl[0].free_list_blk = NIL; 678 /* blk is now the head of the ftbl blk free list */ 377 679 ftbl->free_blk = blk; 378 680 } 379 681 682 /** Consults the file table to retrieve an index corresponding to a file entry 683 * If available, returns the file entry index, otherwise returns NIL. 684 */ 380 685 static int get_free_fent(void) 381 686 { … … 396 701 } 397 702 703 /** Places the file entry located at the provided index back on the file table's 704 * free file entry list. If the index is < FILE_TABLE_HASH_MAX, then set next 705 * to NIL since this index must remain the head of the linked list. Otherwise, 706 * set next to the current head of fent free list and set the free list head to 707 * the provided index. 708 */ 398 709 static void put_free_fent(int fent) 399 710 { … … 402 713 ftbl->file[fent].tag_handle = NIL; 403 714 ftbl->file[fent].tag_id = NIL; 404 /* Set fent index as the head of the free_list */ 405 if(fent>(FILE_TABLE_HASH_MAX-1)) 406 { 715 if(fent<FILE_TABLE_HASH_MAX) 716 { 717 ftbl->file[fent].next = NIL; 718 } 719 else 720 { 721 /* Set next index to the current head of the free list */ 407 722 ftbl->file[fent].next = ftbl->free_list; 723 /* Set fent index as the head of the free_list */ 408 724 ftbl->free_list = fent; 409 725 } 410 else 411 { 412 ftbl->file[fent].next = NIL; 413 }414 } 415 726 } 727 728 /** Consults the provided mtbl's memory entry free list to get the index of the 729 * next free memory entry. Returns the index if one is available, otherwise 730 * returns NIL. 731 */ 416 732 static int get_free_ment(struct mem_table_s *mtbl) 417 733 { 418 uint16_t ret = mtbl->free_list; 419 if((int16_t)ret!=NIL) 420 { 421 mtbl->free_list = mtbl->mem[ret].next; 422 mtbl->mem[ret].next = NIL; 423 mtbl->mem[ret].lru_prev = NIL; 424 mtbl->mem[ret].lru_next = NIL; 425 return ret; 426 } 427 return NIL; 428 } 429 734 uint16_t ment = mtbl->free_list; 735 if((int16_t)ment!=NIL) 736 { 737 mtbl->free_list = mtbl->mem[ment].next; 738 mtbl->mem[ment].next = NIL; 739 /* mtbl->mem[ment].lru_prev = NIL; 740 mtbl->mem[ment].lru_next = NIL; */ 741 } 742 return ment; 743 } 744 745 /** Puts the memory entry corresponding to the provided mtbl and entry index 746 * back on the mtbl's memory entry free list. 747 * 748 * If the entry index is < MEM_TABLE_HASH_MAX, then set next to NIL since this 749 * index must remain the head of the linked list. Otherwise, set next to the 750 * current head of ment free list and set the free list head to the provided 751 * index. 752 */ 430 753 static void put_free_ment(struct mem_table_s *mtbl, int ent) 431 754 { 432 755 if(DBG)fprintf(out, "freeing memory entry = %d\n", ent); 433 /* Reset ment values*/756 /* Reset ment values */ 434 757 mtbl->mem[ent].tag = NIL; 435 758 mtbl->mem[ent].item = NIL; … … 437 760 mtbl->mem[ent].lru_next = NIL; 438 761 mtbl->mem[ent].lru_prev = NIL; 439 /* Update free list to include this entry */ 440 if(ent>(MEM_TABLE_HASH_MAX-1)) 441 { 762 if(ent<MEM_TABLE_HASH_MAX) 763 { 764 mtbl->mem[ent].next = NIL; 765 } 766 else{ 767 /* Set next index to the current head of the free list */ 442 768 mtbl->mem[ent].next = mtbl->free_list; 769 /* Update free list to include this entry */ 443 770 mtbl->free_list = ent; 444 771 } 445 772 } 446 773 774 /** Perform a file lookup on the ucache using the provided fs_id and handle. 775 * 776 * Additional parameters (references) may used that will be set to values 777 * pertaining to mtbl and file entry location. If NULL is passed in place of 778 * these parameters, then they cannot be set. 779 * 780 * If the file is found, a pointer to the mtbl is returned and the parameter 781 * references set accordingly. Otherwise, NIL is returned. 782 */ 447 783 static struct mem_table_s *lookup_file( 448 784 uint32_t fs_id, 449 785 uint64_t handle, 450 uint32_t *file_mtbl_blk, /* Can be NULL if not desired */451 uint16_t *file_mtbl_ent, /* Can be NULL if not desired */452 uint16_t *file_ent_index, /* Can be NULL if not desired */453 uint16_t *file_ent_prev_index /* Can be NULL if not desired */786 uint32_t *file_mtbl_blk, 787 uint16_t *file_mtbl_ent, 788 uint16_t *file_ent_index, 789 uint16_t *file_ent_prev_index 454 790 ) 455 791 { 456 int16_t p,c,n; /* previous, current, next fent index */457 792 if(DBG)fprintf(out, "performing lookup...\n"); 458 struct file_table_s *ftbl = &(ucache->ftbl); 459 struct file_ent_s *current; /* Current ptr for iteration */ 460 /* Index into file hash table */ 793 794 /* Index into file hash table */ 461 795 int index = handle % FILE_TABLE_HASH_MAX; 462 796 if(DBG)fprintf(out, "\thashed index: %d\n", index); 463 current = &(ftbl->file[index]); 464 p=NIL; c = index; n = current->next; 797 798 struct file_table_s *ftbl = &(ucache->ftbl); 799 struct file_ent_s *current = &(ftbl->file[index]); 800 801 /* previous, current, next fent index */ 802 uint16_t p = NIL; 803 uint16_t c = index; 804 uint16_t n = current->next; 805 465 806 while(1) 466 807 { 467 if(DBG)fprintf(out, "\tp=%d\tc=%d\tn=%d\n", (int)p, (int)c, (int)n); 468 if(current->tag_id==fs_id && current->tag_handle==handle) 808 if(DBG)fprintf(out, "\tp=%d\tc=%d\tn=%d\n", (int16_t)p, (int16_t)c, 809 (int16_t)n); 810 if((current->tag_id == fs_id) && (current->tag_handle == handle)) 469 811 { 470 812 if(DBG)fprintf(out, "\tFile located in chain\n"); 471 /* If params !NULL, set their values*/813 /* If params !NULL, set their values */ 472 814 if(file_mtbl_blk!=NULL && file_mtbl_ent!=NULL && 473 815 file_ent_index!=NULL && file_ent_prev_index!=NULL) … … 478 820 *file_ent_prev_index = p; 479 821 } 480 return (struct mem_table_s *)&(ucache->b[ 481 current->mtbl_blk].mtbl[482 current->mtbl_ent]);483 }484 else /* No match yet */822 return (struct mem_table_s *)&(ucache->b[current->mtbl_blk].mtbl[ 823 current->mtbl_ent]); 824 } 825 /* No match yet */ 826 else 485 827 { 486 if((int16_t)current->next ==NIL)828 if((int16_t)current->next == NIL) 487 829 { 488 830 if(DBG)fprintf(out, "\tlookup failure: mtbl not found\n"); … … 502 844 } 503 845 846 /** Function that locates the next free mtbl. 847 * On success, Returns 1 and sets reference parameters to proper indexes. 848 * On failure, returns NIL; 849 */ 504 850 static int get_next_free_mtbl(uint32_t *free_mtbl_blk, uint16_t *free_mtbl_ent) 505 851 { 506 852 struct file_table_s *ftbl = &(ucache->ftbl); 507 /* get next free mtbl_blk and ent */ 853 854 /* Get next free mtbl_blk and ent from ftbl */ 508 855 *free_mtbl_blk = ftbl->free_mtbl_blk; 509 856 *free_mtbl_ent = ftbl->free_mtbl_ent; 510 /* is free mtbl_blk available? */ 511 if((int32_t)*free_mtbl_blk!=NIL && (int16_t)*free_mtbl_ent!=NIL) 857 858 /* Is free mtbl_blk available? */ 859 if(((int32_t)*free_mtbl_blk == NIL) || ((int16_t)*free_mtbl_ent == NIL)) 512 860 { 513 ftbl->free_mtbl_blk = ucache->b[*free_mtbl_blk]. 514 mtbl[*free_mtbl_ent].free_list_blk; 515 ftbl->free_mtbl_ent = ucache->b[*free_mtbl_blk]. 516 mtbl[*free_mtbl_ent].free_list; 517 /* Set free info to NIL - NECESSARY? */ 518 ucache->b[*free_mtbl_blk]. 519 mtbl[*free_mtbl_ent].free_list = NIL; 520 ucache->b[*free_mtbl_blk]. 521 mtbl[*free_mtbl_ent].free_list_blk = NIL; 522 return 1; 523 } 524 return NIL; 525 } 526 861 return NIL; 862 } 863 864 /* Update ftbl to contain new next free mtbl */ 865 ftbl->free_mtbl_blk = ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent]. 866 free_list_blk; 867 ftbl->free_mtbl_ent = ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent]. 868 free_list; 869 870 /* Set free info to NIL - NECESSARY? */ 871 ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent].free_list = NIL; 872 ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent].free_list_blk = NIL; 873 return 1; 874 } 875 876 /** Removes all memory entries belonging to mtbl and places corresponding blocks 877 * back on the ftbl block free list, provided the mtbl->ref_cnt is 0. 878 */ 527 879 static void remove_all_memory_entries(struct mem_table_s *mtbl) 528 880 { 529 /* remove all ments, including their associated blocks */ 530 int i = 0; 531 for(i=0;i<MEM_TABLE_HASH_MAX;i++) 881 /* Don't do anything if this mtbl is referenced.*/ 882 if(mtbl->ref_cnt != 0) 883 { 884 return; 885 } 886 887 int i; 888 for(i = 0; i < MEM_TABLE_HASH_MAX; i++) 532 889 { 533 890 if(DBG)fprintf(out, "\tremoving memory entry %d\n", i); 534 891 int j; 535 for(j =i;!ment_done(j); j=ment_next(mtbl, j))892 for(j = i;!ment_done(j); j = ment_next(mtbl, j)) 536 893 { 894 /* Current Memory Entry */ 537 895 struct mem_ent_s *ment = &(mtbl->mem[j]); 538 if(DBG)fprintf(out, "\t(tag, item)=(%lld, %d)\n", \539 (int64_t)ment->tag,(int32_t)ment->item);896 if(DBG)fprintf(out, "\t(tag, item)=(%lld, %d)\n", 897 (int64_t)ment->tag,(int32_t)ment->item); 540 898 /* Account for empty head of ment chain */ 541 if((int64_t)ment->tag==NIL || (int32_t)ment->item==NIL){ 899 if(((int64_t)ment->tag == NIL) || ((int32_t)ment->item == NIL)) 900 { 542 901 break; 543 902 } … … 548 907 } 549 908 909 /** Places the provided mtbl back on the ftbl's mtbl free list provided it 910 * isn't currently referenced. 911 */ 550 912 static void put_free_mtbl(struct mem_table_s *mtbl, struct file_ent_s *file) 551 913 { 552 /* remove mtbl */ 553 mtbl->num_blocks = NIL; /* number of used blocks in this mtbl */ 914 /* Don't do anything if this mtbl is referenced.*/ 915 if(mtbl->ref_cnt != 0) 916 { 917 return; 918 } 919 920 /* Remove mtbl */ 921 mtbl->num_blocks = 0; /* number of used blocks in this mtbl */ 554 922 mtbl->lru_first = NIL; /* index of first block on lru list */ 555 923 mtbl->lru_last = NIL; /* index of last block on lru list */ 556 924 mtbl->dirty_list = NIL; /* index of first dirty block */ 557 mtbl->ref_cnt = NIL; /* number of clients using this record */ 558 /* add mem_table back to free list */ 559 /* Temporarily store copy of current head (the new next) */ 925 mtbl->ref_cnt = 0; /* number of clients using this record */ 926 927 /* Add mem_table back to free list */ 928 /* Temporarily store copy of current head (the new next) */ 560 929 uint32_t tmp_blk = ucache->ftbl.free_mtbl_blk; 561 930 uint16_t tmp_ent = ucache->ftbl.free_mtbl_ent; 562 /* newly free mtbl becomes new head of free mtbl list*/931 /* newly free mtbl becomes new head of free mtbl list */ 563 932 ucache->ftbl.free_mtbl_blk = file->mtbl_blk; 564 933 ucache->ftbl.free_mtbl_ent = file->mtbl_ent; 565 /* Point to the next free mtbl (the former head) */934 /* Point to the next free mtbl (the former head) */ 566 935 mtbl->free_list_blk = tmp_blk; 567 936 mtbl->free_list = tmp_ent; 568 937 } 569 938 939 /** Evict the file entry at the provided index. 940 * On Success, returns 1. If file is currently referenced, do not evict and 941 * return 0. 942 */ 570 943 /* evict the file @ index, must be less than FILE_TABLE_HASH_MAX */ 571 static voidevict_file(unsigned int index)944 static int evict_file(unsigned int index) 572 945 { 573 946 if(DBG)fprintf(out, "evicting data @ index %d...\n", index); … … 575 948 struct mem_table_s *mtbl = 576 949 &(ucache->b[file->mtbl_blk].mtbl[file->mtbl_ent]); 950 951 if(mtbl->ref_cnt != 0){ 952 return 0; 953 } 954 577 955 remove_all_memory_entries(mtbl); 578 956 put_free_mtbl(mtbl, file); 579 /* instead of removing, simply prepare fent for it's next occupant */ 957 958 /* Prepare fent for its next occupant */ 580 959 file->tag_handle = NIL; 581 960 file->tag_id = NIL; 582 961 file->mtbl_blk = NIL; /* block index of this mtbl */ 583 962 file->mtbl_ent = NIL; /* entry index of this mtbl */ 584 } 585 963 return 1; 964 } 965 966 /** Insert information about file into ucache (no file data inserted) 967 * Returns pointer to mtbl on success. 968 * 969 * Returns NIL if necessary data structures could not be aquired from the free 970 * lists or through an eviction policy (meaning references are held). 971 */ 586 972 static struct mem_table_s *insert_file(uint32_t fs_id, uint64_t handle) 587 973 { 588 974 if(DBG)fprintf(out, "trying to insert file...\n"); 589 975 struct file_table_s *ftbl = &(ucache->ftbl); 590 struct file_ent_s *current; /* Current ptr for iteration*/591 uint16_t free_fent ; /*Index of next free fent */592 /* index into file hash table*/976 struct file_ent_s *current; /* Current ptr for iteration */ 977 uint16_t free_fent = NIL; /* Index of next free fent */ 978 /* index into file hash table */ 593 979 unsigned int index = handle % FILE_TABLE_HASH_MAX; 594 980 if(DBG)fprintf(out, "\thashed index: %u\n", index); 595 981 current = &(ftbl->file[index]); 596 /* Get next free mem_table*/597 uint32_t free_mtbl_blk ;598 uint16_t free_mtbl_ent ;599 /* Create free mtbls if none are available */600 if(get_next_free_mtbl(&free_mtbl_blk, &free_mtbl_ent) !=1)982 /* Get free mtbl */ 983 uint32_t free_mtbl_blk = NIL; 984 uint16_t free_mtbl_ent = NIL; 985 /* Create free mtbls if none are available */ 986 if(get_next_free_mtbl(&free_mtbl_blk, &free_mtbl_ent) != 1) 601 987 { 602 if((int16_t)ucache->ftbl.free_blk ==NIL)988 if((int16_t)ucache->ftbl.free_blk == NIL) 603 989 { 604 /* Evict a block from mtbl with most mem entries*/990 /* Evict a block from mtbl with most mem entries */ 605 991 struct mem_table_s *max_mtbl; 606 int num_blocks = locate_max_mtbl(&max_mtbl); 607 if(DBG)fprintf(out, "\tget_free_blk returned NIL, evicting a block from max mtbl which has %d entries\n",max_mtbl->num_blocks); 992 locate_max_mtbl(&max_mtbl); 993 if(DBG)fprintf(out, "\tget_free_mtbl returned NIL\n"); 994 if(DBG)fprintf(out, "\tevicting blk from max mtbl: has %d entries\n" 995 ,max_mtbl->num_blocks); 608 996 evict_LRU(max_mtbl); 609 997 } 610 /* Intitialize remaining blocks' memory tables */611 if((int16_t)ucache->ftbl.free_blk !=NIL)998 /* Intitialize remaining blocks' memory tables */ 999 if((int16_t)ucache->ftbl.free_blk != NIL) 612 1000 { 613 1001 if(DBG)fprintf(out, "\tadding memory tables to free block\n"); … … 616 1004 } 617 1005 } 618 /* Insert at index, relocating data @ index if occupied */ 619 if((int32_t)current->mtbl_blk!=NIL && (int16_t)current->mtbl_ent!=NIL) 1006 1007 /* Insert at index, relocating data @ index if occupied */ 1008 if(((int32_t)current->mtbl_blk != NIL) && 1009 ((int16_t)current->mtbl_ent != NIL)) 620 1010 { 621 1011 if(DBG)fprintf(out, "\tmust relocate head data\n"); 622 /* get free file entry and update ftbl */1012 /* get free file entry and update ftbl */ 623 1013 free_fent = get_free_fent(); 624 if((int16_t)free_fent !=NIL)1014 if((int16_t)free_fent != NIL) 625 1015 { 626 /* copy data from 1 struct to the other*/1016 /* copy data from 1 struct to the other */ 627 1017 ftbl->file[free_fent] = *current; 628 629 /* point new head's "next" to former head */ 1018 /* point new head's "next" to former head */ 630 1019 current->next = free_fent; 631 1020 } 632 1021 else 633 { /* No free file entries available: policy? */1022 { /* No free file entries available: policy? */ 634 1023 if(DBG)fprintf(out, "\tno free file entries\n"); 635 evict_file(index); 1024 /* Attempt to evict a file in a chain corresponding to the hashed 1025 * index into the ftbl. 1026 * Return NIL if it isn't possible. 1027 */ 1028 /* Stop when the file has been evicted or end of chain reached */ 1029 int file_evicted = evict_file(index); 1030 int i; 1031 for(i = index; !file_done(i) && (!file_evicted); i = 1032 file_next(ftbl,index)) 1033 { 1034 i = ftbl->file[i].next; 1035 current = &(ftbl->file[i]); 1036 file_evicted = evict_file((unsigned int)i); 1037 } 1038 if(!file_evicted) 1039 { 1040 /* Could not get file entry */ 1041 return (struct mem_table_s *)NIL; 1042 } 636 1043 } 637 1044 } … … 640 1047 if(DBG)fprintf(out, "\tno head data @ index\n"); 641 1048 } 642 /* insert file data @ index*/1049 /* Insert file data @ index */ 643 1050 current->tag_id = fs_id; 644 1051 current->tag_handle = handle; 645 /* Update fent with it's new mtbl: blk and ent */1052 /* Update fent with it's new mtbl: blk and ent */ 646 1053 current->mtbl_blk = free_mtbl_blk; 647 1054 current->mtbl_ent = free_mtbl_ent; 648 /* Initialize Memory Table */1055 /* Initialize Memory Table */ 649 1056 init_memory_table(free_mtbl_blk, free_mtbl_ent); 650 1057 if(DBG)fprintf(out, "\trecieved free memory table: 0X%X\n", 651 (unsigned int)&(ucache->b[current->mtbl_blk].mtbl[ 652 current->mtbl_ent])); 653 return &(ucache->b[current->mtbl_blk].mtbl[ 654 current->mtbl_ent]); 655 } 656 1058 (unsigned int)&(ucache->b[current->mtbl_blk].mtbl[current->mtbl_ent])); 1059 return &(ucache->b[current->mtbl_blk].mtbl[current->mtbl_ent]); 1060 } 1061 1062 /** Remove file entry and memory table of file identified by parameters 1063 * Returns 1 following removal 1064 * Returns NIL if file is referenced or if the file could not be located. 1065 */ 657 1066 static int remove_file(uint32_t fs_id, uint64_t handle) 658 1067 { 659 1068 if(DBG)fprintf(out, "trying to remove file...\n"); 1069 uint32_t file_mtbl_blk = NIL; 1070 uint16_t file_mtbl_ent = NIL; 1071 uint16_t file_ent_index = NIL; 1072 uint16_t file_ent_prev_index = NIL; 1073 660 1074 struct file_table_s *ftbl = &(ucache->ftbl); 661 int32_t file_mtbl_blk; 662 int16_t file_mtbl_ent; 663 int16_t file_ent_index; 664 int16_t file_ent_prev_index; 665 struct mem_table_s *mtbl = lookup_file(fs_id, handle, 666 &file_mtbl_blk, &file_mtbl_ent, &file_ent_index, 667 &file_ent_prev_index); 668 /* Verify we've recieved the necessary info */ 669 if((int32_t)file_mtbl_blk==NIL || (int16_t)file_mtbl_ent==NIL) 1075 struct mem_table_s *mtbl = lookup_file(fs_id, handle, &file_mtbl_blk, 1076 &file_mtbl_ent, &file_ent_index, &file_ent_prev_index); 1077 1078 if(mtbl->ref_cnt != 0) 1079 { 1080 if(DBG)fprintf(out, "\tremoval failure: ref_cnt==%d\n", mtbl->ref_cnt); 1081 return NIL; 1082 } 1083 1084 /* Verify we've recieved the necessary info */ 1085 if(((int32_t)file_mtbl_blk == NIL) || ((int16_t)file_mtbl_ent == NIL)) 670 1086 { 671 1087 if(DBG)fprintf(out, "\tremoval failure: no mtbl matching file\n"); 672 1088 return NIL; 673 1089 } 674 /* add mem_table back to free list */ 675 /* Temporarily store copy of current head (the new next) */ 676 uint32_t tmp_blk = ftbl->free_mtbl_blk; 677 uint16_t tmp_ent = ftbl->free_mtbl_ent; 678 /* newly free mtbl becomes new head of free mtbl list */ 679 ftbl->free_mtbl_blk = file_mtbl_blk; 680 ftbl->free_mtbl_ent = file_mtbl_ent; 681 /* Point to the next free mtbl (the former head) */ 682 mtbl->free_list_blk = tmp_blk; 683 mtbl->free_list = tmp_ent; 684 /* Free the file entry */ 1090 1091 /* Free the mtbl */ 1092 put_free_mtbl(mtbl, &(ftbl->file[file_ent_index])); 1093 1094 /* Free the file entry */ 685 1095 ftbl->file[file_ent_prev_index].next = ftbl->file[file_ent_index].next; 686 1096 put_free_fent(file_ent_index); 1097 687 1098 if(DBG)fprintf(out, "\tremoval sucessful\n"); 688 1099 return(1); 689 1100 } 690 1101 1102 /** Lookup the memory location of a block of data in cache that is identified 1103 * by the mtbl and offset parameters. 1104 * 1105 * If located, returns a pointer to memory where the desired block of data is 1106 * stored. Otherwise, NIL is returned. 1107 * 1108 * Additional parameters (references) may be used that will be set to values 1109 * pertaining to the memory entry's location. If NULLs are passed in place of 1110 * these parameters, then they will not be set. 1111 */ 691 1112 static void *lookup_mem(struct mem_table_s *mtbl, 692 1113 uint64_t offset, … … 696 1117 { 697 1118 if(DBG)fprintf(out, "performing ment lookup...\n"); 698 /* index into mem hash table */ 1119 1120 /* index into mem hash table */ 699 1121 unsigned int index = offset % MEM_TABLE_HASH_MAX; 700 if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n",\ 701 offset, index); 1122 if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n", offset, 1123 index); 1124 702 1125 struct mem_ent_s *current = &(mtbl->mem[index]); 703 /* previous, current, next memory entry index in mtbl */ 704 int16_t p,c,n; 705 p = NIL; c = index; n = current->next; 1126 1127 /* previous, current, next memory entry index in mtbl */ 1128 int16_t p = NIL; 1129 int16_t c = index; 1130 int16_t n = current->next; 1131 706 1132 while(1) 707 1133 { 708 if(offset ==current->tag)1134 if(offset == current->tag) 709 1135 { 710 if(DBG)fprintf(out, "\tmatch located: 0X%llX==0X%llX\n", \711 offset,current->tag);712 713 /* If params !NULL, set their values*/714 if( item_index!=NULL && mem_ent_index!=NULL&&715 mem_ent_prev_index!=NULL)1136 if(DBG)fprintf(out, "\tmatch located: 0X%llX==0X%llX\n", offset, 1137 current->tag); 1138 1139 /* If parameters !NULL, set their values */ 1140 if((item_index != NULL) && (mem_ent_index != NULL) && 1141 (mem_ent_prev_index != NULL)) 716 1142 { 717 1143 *item_index = current->item; … … 723 1149 else 724 1150 { 725 /* if(DBG)fprintf(out, "\t0X%llX!=0X%llX\n", offset,\ 726 current->tag); */ 727 /* if next available iterate */ 728 if((int16_t)current->next==NIL) 1151 if((int16_t)current->next == NIL) 729 1152 { 730 1153 if(DBG)fprintf(out, "\tmemory entry not found\n"); … … 733 1156 else 734 1157 { 1158 /* Iterate */ 735 1159 current = &(mtbl->mem[current->next]); 736 p=c; c=n; n=current->next; 1160 p = c; 1161 c = n; 1162 n = current->next; 737 1163 } 738 1164 } … … 740 1166 } 741 1167 1168 /** Update the provided mtbl's LRU doubly-linked list by placing the memory 1169 * entry, identified by the provided index, at the head of the list (lru_first). 1170 * 1171 */ 742 1172 static void update_lru(struct mem_table_s *mtbl, uint16_t index) 743 1173 { 744 1174 if(DBG)fprintf(out, "updating lru...\n"); 745 if((int16_t)index<MEM_TABLE_HASH_MAX) 1175 /* Do not place an entry with index < MEM_TABLE_HASH_MAX because 1176 * they must remain the heads of the hash table chains 1177 */ 1178 if((int16_t)index < MEM_TABLE_HASH_MAX) 746 1179 { 747 if(DBG)fprintf(out, "\t%d<MEM_TABLE_HASH_MAX, not adding to LRU\n", index); 1180 if(DBG)fprintf(out, 1181 "\t%d<MEM_TABLE_HASH_MAX, not adding to LRU\n", index); 748 1182 return; 749 1183 } 750 /* update LRU List */ 751 if((int16_t)mtbl->lru_first==NIL && (int16_t)mtbl->lru_last==NIL) 1184 1185 /* First memory entry used becomes the head and tail of the list */ 1186 if(((int16_t)mtbl->lru_first == NIL) && 1187 ((int16_t)mtbl->lru_last == NIL)) 752 1188 { 753 1189 if(DBG)fprintf(out, "\tsetting lru first and last\n"); … … 757 1193 mtbl->mem[index].lru_next = NIL; 758 1194 } 759 else if(mtbl->lru_first==mtbl->lru_last) 1195 /* 2nd Memory Entry */ 1196 else if(mtbl->lru_first == mtbl->lru_last) 760 1197 { 761 if(mtbl->lru_first!=index) 762 { /* if not already the first and last */ 763 if(DBG)fprintf(out, "\tinserting second record in LRU\n"); 764 /* point tail.prev to new */ 1198 /* Do nothing if this index is already the only entry */ 1199 if(mtbl->lru_first == index) 1200 { 1201 return; 1202 } 1203 else 1204 { /* Must be 2nd unique memory entry */ 1205 if(DBG)fprintf(out, "\tinserting second record in LRU\n"); 1206 /* point tail.prev to new */ 765 1207 mtbl->mem[mtbl->lru_last].lru_prev = index; 766 /* point new.prev to nil*/1208 /* point new.prev to NIL */ 767 1209 mtbl->mem[index].lru_prev = NIL; 768 /* point the new.next to the tail*/1210 /* point the new.next to the tail */ 769 1211 mtbl->mem[index].lru_next = mtbl->lru_last; 770 /* point the head to the new*/1212 /* point the head to the new */ 771 1213 mtbl->lru_first = index; 772 1214 } 773 1215 } 1216 /* 3rd+ Memory Entry */ 774 1217 else 775 1218 { 776 if(DBG)fprintf(out,"\trepairing previous LRU links and inserting record in LRU\n"); 777 /* repair links */ 778 if((int16_t)mtbl->mem[index].lru_prev!=NIL) 1219 if(DBG)fprintf(out, "\trepairing previous LRU links and " 1220 "inserting record in LRU\n"); 1221 /* repair links */ 1222 if((int16_t)mtbl->mem[index].lru_prev != NIL) 779 1223 { 780 1224 mtbl->mem[mtbl->mem[index].lru_prev].lru_next = 781 1225 mtbl->mem[index].lru_next; 782 1226 } 783 if((int16_t)mtbl->mem[index].lru_next !=NIL)1227 if((int16_t)mtbl->mem[index].lru_next != NIL) 784 1228 { 785 1229 mtbl->mem[mtbl->mem[index].lru_next].lru_prev = 786 1230 mtbl->mem[index].lru_prev; 787 1231 } 788 /* update nodes own link*/1232 /* update nodes own link */ 789 1233 mtbl->mem[mtbl->lru_first].lru_prev = index; 790 1234 mtbl->mem[index].lru_next = mtbl->lru_first; 791 1235 mtbl->mem[index].lru_prev = NIL; 792 /* Finally, establish this entry as the first on lru*/1236 /* Finally, establish this entry as the first on LRU list */ 793 1237 mtbl->lru_first = index; 794 1238 } 795 1239 } 796 1240 1241 /** Searches the ftbl for the mtbl with the most entries. 1242 * Returns the number of memory entries the max mtbl has. The double ptr 1243 * parameter is used to store a reference to the mtbl pointer with the most 1244 * memory entries. 1245 */ 797 1246 static int locate_max_mtbl(struct mem_table_s **mtbl) 798 1247 { 799 800 1248 if(DBG)fprintf(out, "locating mtbl with most entries...\n"); 801 1249 struct file_table_s *ftbl = &(ucache->ftbl); 802 uint32_t index_of_max_blk ;803 uint16_t index_of_max_ent ;1250 uint32_t index_of_max_blk = NIL; 1251 uint16_t index_of_max_ent = NIL; 804 1252 uint16_t value_of_max = 0; 1253 /* Iterate over file hash table indices */ 805 1254 int i; 806 for(i =0;i<FILE_TABLE_HASH_MAX;i++)1255 for(i = 0; i < FILE_TABLE_HASH_MAX; i++) 807 1256 { 808 1257 if(DBG)fprintf(out, "\texamining ftbl index %d\n", i); 1258 /* Iterate over hash table chain */ 809 1259 int j; 810 for(j =i; !file_done(j); j=file_next(ftbl, j))1260 for(j = i; !file_done(j); j = file_next(ftbl, j)) 811 1261 { 812 1262 struct file_ent_s *fent = &(ftbl->file[j]); 813 if(DBG)fprintf(out, "\t(blk, ent)=(%d, %d)\n", fent->mtbl_blk,\ 814 (int16_t)fent->mtbl_ent); 815 if((int32_t)fent->mtbl_blk==NIL || (int16_t)fent->mtbl_ent==NIL){ 1263 if(DBG)fprintf(out, "\t(blk, ent)=(%d, %d)\n", fent->mtbl_blk, 1264 (int16_t)fent->mtbl_ent); 1265 //TODO: this might can be removed: test it 1266 if(((int32_t)fent->mtbl_blk == NIL) || 1267 ((int16_t)fent->mtbl_ent==NIL)) 1268 { 816 1269 break; 817 1270 } 818 struct mem_table_s *current_mtbl = &(ucache->b[fent->mtbl_blk].\ 819 mtbl[fent->mtbl_ent]); 820 if(current_mtbl->num_blocks>value_of_max){ 1271 /* Examine the mtbl's value of num_blocks to see if it's the 1272 * greatest. 1273 */ 1274 struct mem_table_s *current_mtbl = &(ucache->b[fent->mtbl_blk]. 1275 mtbl[fent->mtbl_ent]); 1276 if(current_mtbl->num_blocks > value_of_max) 1277 { 821 1278 if(DBG)fprintf(out, "\tmax updated @ %d\n", j); 822 *mtbl = current_mtbl; 1279 *mtbl = current_mtbl; /* Set the parameter to this mtbl */ 823 1280 index_of_max_blk = fent->mtbl_blk; 824 1281 index_of_max_ent = fent->mtbl_ent; … … 830 1287 } 831 1288 832 static void evict_LRU(struct mem_table_s *mtbl) 1289 /** Evicts the LRU memory entry from the tail (lru_last) of the provided 1290 * mtbl's LRU list. 1291 * Returns 1 on success; 0 on failure, meaning there was no lru 1292 */ 1293 static int evict_LRU(struct mem_table_s *mtbl) 833 1294 { 834 1295 if(DBG)fprintf(out, "evicting LRU...\n"); 835 if(mtbl->num_blocks !=0)1296 if(mtbl->num_blocks != 0) 836 1297 { 837 1298 remove_mem(mtbl, mtbl->mem[mtbl->lru_last].tag); 1299 return 1; 838 1300 } 839 1301 else 840 1302 { /* Worst Case */ 841 1303 if(DBG)fprintf(out, "\tno LRU on this mtbl\n"); 842 } 843 } 844 845 /* Set the block index where data is stored */ 1304 return 0; 1305 } 1306 } 1307 1308 1309 /** Used to obtain a block for storage of data identified by the offset 1310 * parameter and maintained in the mtbl at the memory entry identified by the 1311 * index parameter. 1312 * 1313 * If a free block could be aquired, returns the memory address of the block 1314 * just inserted. Otherwise, returns NIL. 1315 */ 846 1316 static void *set_item(struct mem_table_s *mtbl, 847 1317 uint64_t offset, … … 849 1319 { 850 1320 int16_t free_blk = get_free_blk(); 851 if(free_blk==NIL) 1321 /* No Free Blocks Available */ 1322 if(free_blk == NIL) 852 1323 { 853 if(DBG)fprintf(out, "\tget_free_blk returned NIL, attempting removal of LRU\n"); 854 evict_LRU(mtbl); 1324 if(DBG)fprintf(out, "\tget_free_blk returned NIL, attempting " 1325 "removal of LRU\n"); 1326 //TODO this probably wont work since we cannot evict a block that is current referenced 1327 evict_LRU(mtbl); 855 1328 free_blk = get_free_blk(); 856 1329 } 857 1330 858 if(free_blk==NIL) 1331 /* After Eviction Routine - No Free Blocks Available, Evict from mtbl 1332 * with the most memory entries (and therefore blocks) 1333 */ 1334 if(free_blk == NIL) 859 1335 { 860 /* Evict block from mtbl with most memory entries */861 1336 struct mem_table_s *max_mtbl; 862 int num_blocks =locate_max_mtbl(&max_mtbl);863 if(DBG)fprintf(out, "\tget_free_blk returned NIL, evicting a block from max mtbl which has %d entries\n",\864 max_mtbl->num_blocks);1337 locate_max_mtbl(&max_mtbl); 1338 if(DBG)fprintf(out, "\tget_free_blk returned NIL, evicting a block " 1339 "from max mtbl which has %d entries\n", max_mtbl->num_blocks); 865 1340 evict_LRU(max_mtbl); 866 1341 free_blk = get_free_blk(); 867 1342 } 868 if(free_blk!=NIL)869 { /* got block */870 /* increment num_blocks used by this mtbl */1343 /* A Free Block is Avaiable for Use */ 1344 if(free_blk != NIL) 1345 { 871 1346 mtbl->num_blocks++; 872 1347 update_lru(mtbl, index); 873 if(DBG)fprintf(out, "\tsuccessfully inserted memory entry @ blk: %d\n", (int16_t) free_blk); 874 /* set item to block number */ 1348 if(DBG)fprintf(out, "\tsuccessfully inserted memory entry @ blk: " 1349 "%d\n", (int16_t) free_blk); 1350 /* set item to block number */ 875 1351 mtbl->mem[index].tag = offset; 876 1352 mtbl->mem[index].item = free_blk; 877 /* add to dirty list*/1353 /* add block index to head of dirty list */ 878 1354 if(DBG)fprintf(out, "\tadding memory entry to dirty list\n"); 879 1355 mtbl->mem[index].dirty_next = mtbl->dirty_list; 880 1356 mtbl->dirty_list = index; 881 /* Return the address of the block where data is stored*/1357 /* Return the address of the block where data is stored */ 882 1358 return (void *)&(ucache->b[free_blk]); 883 1359 } 884 } 885 1360 return (void *)(NIL); 1361 } 1362 1363 /** Requests a location in memory to place the data identified by the mtbl and 1364 * offset parameters. Also inserts the necessary info into the mtbl. 1365 * 1366 */ 886 1367 static void *insert_mem(struct mem_table_s *mtbl, uint64_t offset) 887 1368 { 888 1369 if(DBG)fprintf(out, "trying to insert mem...\n"); 889 /* index into mem hash table */ 1370 1371 /* Index into mem hash table */ 890 1372 unsigned int index = offset % MEM_TABLE_HASH_MAX; 891 if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n",\ 892 offset, index); 1373 if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n", 1374 offset, index); 1375 893 1376 struct mem_ent_s *current = &(mtbl->mem[index]); 894 /* lookup first*/1377 /* Lookup first */ 895 1378 void *returnValue = lookup_mem(mtbl, offset, NULL, NULL, NULL); 896 if((int)returnValue!=NIL) 897 { 898 if(DBG)fprintf(out, "\tblock for this offset already exists @ 0X%X",\ 899 (unsigned int)returnValue); 1379 if((int)returnValue != NIL) 1380 { 1381 if(DBG)fprintf(out, "\tblock for this offset already exists @ 0X%X", 1382 (unsigned int)returnValue); 1383 /* Already exists in mtbl so just return a ptr to the blk */ 900 1384 return returnValue; 901 1385 } 1386 1387 /* Entry doesn't exist, insertion required */ 902 1388 if(DBG)fprintf(out, "\tlookup returned NIL\n"); 903 if((int64_t)mtbl->mem[index].tag!=NIL) 904 { /* if head occupied, need to get free ment */ 1389 if((int64_t)mtbl->mem[index].tag != NIL) 1390 { 1391 /* If head occupied, need to get free ment */ 905 1392 int mentIndex = get_free_ment(mtbl); 906 if(mentIndex ==NIL)907 { /* no free memory entry available*/1393 if(mentIndex == NIL) 1394 { /* No free ment available, so attempt eviction, and try again */ 908 1395 if(DBG)fprintf(out, "\tno ment\n"); 909 1396 evict_LRU(mtbl); 910 mentIndex = get_free_ment(mtbl); /* try to get ment again */ 911 } 912 if(mentIndex!=NIL) 1397 mentIndex = get_free_ment(mtbl); 1398 } 1399 /* Procede with memory insertion if eviction was successful */ 1400 if(mentIndex != NIL) 913 1401 { 914 if(DBG)fprintf(out, "\tfound free memory entry @ index = %d\n", \915 mentIndex);916 /* insert after head of chain*/1402 if(DBG)fprintf(out, "\tfound free memory entry @ index = %d\n", 1403 mentIndex); 1404 /* Insert directly after head of chain */ 917 1405 uint16_t next_ment = current->next; 918 1406 current->next = mentIndex; … … 920 1408 return set_item(mtbl, offset, mentIndex); 921 1409 } 922 } 923 else 924 { /* No need to iterate to next in chain, just use head */ 925 return set_item(mtbl, offset, index); 926 } 927 } 928 1410 /* Eviction Failed */ 1411 else 1412 { 1413 return (void *)NULL; 1414 } 1415 } 1416 /* Head vacant. No need to iterate to next in chain, just use head */ 1417 return set_item(mtbl, offset, index); 1418 } 1419 1420 /** Removes all table info regarding the block identified by the mtbl and 1421 * offset, provided the mtbl has a reference count of 0 and the entry exists. 1422 * 1423 * On success returns 1, on failure returns 0. 1424 * 1425 */ 929 1426 static int remove_mem(struct mem_table_s *mtbl, uint64_t offset) 930 1427 { 931 1428 if(DBG)fprintf(out, "trying to remove memory entry...\n"); 932 /* some indexes */ 933 int32_t item_index; 934 int16_t mem_ent_index; 935 int16_t mem_ent_prev_index; 1429 /* Some Indices */ 1430 uint32_t item_index = NIL; 1431 uint16_t mem_ent_index = NIL; 1432 uint16_t mem_ent_prev_index = NIL; 1433 1434 1435 /* Previous, Current, Next */ 1436 uint16_t p = NIL; 1437 uint16_t c = NIL; 1438 uint16_t n = NIL; 1439 1440 /* Check reference count */ 1441 if(mtbl->ref_cnt != 0) 1442 { 1443 if(DBG)fprintf(out, "removal failure: ref_cnt==%d\n", mtbl->ref_cnt); 1444 return 0; 1445 } 936 1446 void *retValue = lookup_mem(mtbl, offset, &item_index, &mem_ent_index, 937 &mem_ent_prev_index); 938 /* Verify we've recieved the necessary info */ 939 if((int)retValue==NIL) 940 { 941 if(DBG)fprintf(out, "\tremoval failure: memory entry not found matching offset"); 942 return NIL; 943 } 944 /* Remove from LRU */ 945 /* update each of adjacent nodes' link */ 946 if((int16_t)mtbl->mem[mem_ent_index].lru_prev!=NIL) 1447 &mem_ent_prev_index); 1448 /* Verify we've recieved the necessary info */ 1449 if((int)retValue == NIL) 1450 { 1451 if(DBG)fprintf(out, "\tremoval failure: memory entry not found " 1452 "matching offset"); 1453 return 0; 1454 } 1455 /* Remove from LRU */ 1456 /* Update each of the adjacent nodes' link */ 1457 if((int16_t)mtbl->mem[mem_ent_index].lru_prev != NIL) 947 1458 { 948 1459 mtbl->mem[mtbl->mem[mem_ent_index].lru_prev].lru_next = 949 mtbl->mem[mem_ent_index].lru_next;950 } 951 if((int16_t)mtbl->mem[mem_ent_index].lru_next !=NIL)1460 mtbl->mem[mem_ent_index].lru_next; 1461 } 1462 if((int16_t)mtbl->mem[mem_ent_index].lru_next != NIL) 952 1463 { 953 1464 mtbl->mem[mtbl->mem[mem_ent_index].lru_next].lru_prev = 954 mtbl->mem[mem_ent_index].lru_prev; 955 } 956 if(mem_ent_index==mtbl->lru_first) 957 { /* is node the head */ 1465 mtbl->mem[mem_ent_index].lru_prev; 1466 } 1467 if(mem_ent_index == mtbl->lru_first) 1468 { 1469 /* Is node the head? */ 958 1470 mtbl->lru_first = mtbl->mem[mem_ent_index].lru_next; 959 1471 } 960 if(mem_ent_index==mtbl->lru_last) 961 { /* is node the tail */ 1472 if(mem_ent_index == mtbl->lru_last) 1473 { 1474 /* Is node the tail? */ 962 1475 mtbl->lru_last = mtbl->mem[mem_ent_index].lru_prev; 963 1476 } 964 /* Remove from dirty list if Dirty */1477 /* Remove from dirty list if Dirty */ 965 1478 if(DBG)fprintf(out, "\tremoving from dirty list\n"); 966 uint16_t p, c, n; /* Previous, Current, Next */ 967 p = NIL; 1479 968 1480 c = mtbl->dirty_list; 969 1481 n = mtbl->mem[c].dirty_next; 970 while(c!=mem_ent_index) 971 { 972 /*if(DBG)fprintf(out, "\tp: %d\tc: %d\tn: %d\n", 973 (int16_t)p, (int16_t)c, (int16_t)n);*/ 1482 1483 while(c != mem_ent_index) 1484 { 974 1485 p = c; 975 1486 c = n; 976 1487 n = mtbl->mem[c].dirty_next; 977 if((int16_t)c == NIL)break; 1488 if((int16_t)c == NIL) 1489 { 1490 break; 1491 } 978 1492 } 979 1493 if((int16_t)c != NIL) 980 { /* if memory entry was located on the dirty_list */ 1494 { 1495 /* If memory entry was located on the dirty_list */ 981 1496 mtbl->mem[p].dirty_next = mtbl->mem[c].dirty_next; 982 1497 mtbl->mem[c].dirty_next = NIL; 983 1498 } 984 /* add memory block back to free list*/1499 /* Add memory block back to free list */ 985 1500 put_free_blk(item_index); 986 /* Repair link */987 if((int16_t)mem_ent_prev_index !=NIL)1501 /* Repair link */ 1502 if((int16_t)mem_ent_prev_index != NIL) 988 1503 { 989 1504 mtbl->mem[mem_ent_prev_index].next = mtbl->mem[mem_ent_index].next; 990 1505 } 991 /* newly free mem entry becomes new head of free mem entry list if less 992 than hash table max */ 1506 /* Newly free mem entry becomes new head of free mem entry list if index 1507 * is less than hash table max 1508 */ 993 1509 put_free_ment(mtbl, mem_ent_index); 994 1510 mtbl->num_blocks--; … … 998 1514 999 1515 /* The following two functions are provided for error checking purposes. 1000 */1001 1516 static void print_lru(struct mem_table_s *mtbl) 1002 1517 { … … 1025 1540 } 1026 1541 } 1542 */ 1543 1027 1544 /* End of Internal Only Functions */ 1028 1545 -
branches/Orange-Branch/src/client/usrint/ucache.h
r9001 r9012 1 1 /* 2 * (C) 2011 Clemson University and The University of Chicago2 * (C) 2011 Clemson University 3 3 * 4 4 * See COPYING in top-level directory. 5 5 */ 6 6 7 #ifndef UCACHE_INTERNAL_H 8 #define UCACHE_INTERNAL_H 7 #ifndef UCACHE_H 8 #define UCACHE_H 9 10 #define UCACHE_ENABLED 11 #define UCACHE_LOCKING_ENABLED 9 12 10 13 #include <stdio.h> … … 12 15 #include <stdint.h> 13 16 #include <semaphore.h> 17 #include <pthread.h> 14 18 15 19 /* The following includes may end up not being needed. … … 36 40 #define NIL (-1) 37 41 38 #define DBG 042 #define DBG 1 39 43 #define INTERNAL_TESTING 0 44 45 46 #define LOCK_TYPE 0 /* 0 for Semaphore, 1 for Mutex, 2 for Spinlock */ 47 #if LOCK_TYPE==0 40 48 #define ucache_lock_t sem_t 49 #elif LOCK_TYPE==1 50 #define ucache_lock_t pthread_mutex_t 51 #elif LOCK_TYPE==2 52 #define ucache_lock_t pthread_spinlock_t 53 #endif 41 54 42 55 typedef uint32_t PVFS_fs_id; … … 122 135 123 136 /* externally visible API */ 124 extern void ucache_initialize(void); 125 extern int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 126 extern void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 127 extern void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 128 extern int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 129 extern int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 130 extern int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 137 void ucache_initialize(void); 138 int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 139 void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 140 void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 141 int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 142 int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 143 int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 144 void ucache_dec_ref_cnt(struct mem_table_s * mtbl); 145 void ucache_inc_ref_cnt(struct mem_table_s * mtbl); 146 void ucache_info( 147 FILE * out, 148 union user_cache_u * ucache, 149 ucache_lock_t * ucache_lock 150 ); 131 151 132 /* Internal Only Function Declarations */ 133 /* Cache Locking Functions */ 134 static int ucache_lock_init(ucache_lock_t * lock); 135 static int ucache_lock_lock(ucache_lock_t * lock); 136 static int ucache_lock_unlock(ucache_lock_t * lock); 137 static int ucache_lock_getvalue(ucache_lock_t * lock, int *sval); 138 static int ucache_lock_destroy(ucache_lock_t * lock); 139 140 /* Dirty List Iterator */ 141 static int dirty_done(uint16_t index); 142 static int dirty_next(struct mem_table_s *mtbl, uint16_t index); 143 144 /* Memory Entry Chain Iterator */ 145 static int ment_done(int index); 146 static int ment_next(struct mem_table_s *mtbl, int index); 147 148 /* File Entry Chain Iterator */ 149 static int file_done(int index); 150 static int file_next(struct file_table_s *ftbl, int index); 151 152 static void add_free_mtbls(int blk); 153 static void init_memory_table(int blk, int ent); 154 static uint16_t get_free_blk(void); 155 static void put_free_blk(int blk); 156 static int get_free_fent(void); 157 static void put_free_fent(int fent); 158 static int get_free_ment(struct mem_table_s *mtbl); 159 static void put_free_ment(struct mem_table_s *mtbl, int ent); 160 static struct mem_table_s *lookup_file( 161 uint32_t fs_id, 162 uint64_t handle, 163 uint32_t *file_mtbl_blk, /* Can be NULL if not desired */ 164 uint16_t *file_mtbl_ent, /* Can be NULL if not desired */ 165 uint16_t *file_ent_index, /* Can be NULL if not desired */ 166 uint16_t *file_ent_prev_index /* Can be NULL if not desired */ 167 ); 168 static int get_next_free_mtbl(uint32_t *free_mtbl_blk, uint16_t *free_mtbl_ent); 169 static void remove_all_memory_entries(struct mem_table_s *mtbl); 170 static void put_free_mtbl(struct mem_table_s *mtbl, struct file_ent_s *file); 171 static void evict_file(unsigned int index); 172 static struct mem_table_s *insert_file(uint32_t fs_id, uint64_t handle); 173 static int remove_file(uint32_t fs_id, uint64_t handle); 174 static void *lookup_mem(struct mem_table_s *mtbl, 175 uint64_t offset, 176 uint32_t *item_index, 177 uint16_t *mem_ent_index, 178 uint16_t *mem_ent_prev_index 179 ); 180 static void update_lru(struct mem_table_s *mtbl, uint16_t index); 181 static int locate_max_mtbl(struct mem_table_s **mtbl); 182 static void evict_LRU(struct mem_table_s *mtbl); 183 static void *set_item(struct mem_table_s *mtbl, 184 uint64_t offset, 185 uint16_t index 186 ); 187 static void *insert_mem(struct mem_table_s *mtbl, uint64_t offset); 188 static int remove_mem(struct mem_table_s *mtbl, uint64_t offset); 189 /* list printing functions */ 190 static void print_lru(struct mem_table_s *mtbl); 191 static void print_dirty(struct mem_table_s *mtbl); 152 #if LOCK_TYPE==0 153 int ucache_lock_getvalue(ucache_lock_t * lock, int *sval); 154 #endif 192 155 /**************************************** End of Internal Only Functions */ 193 156 #endif 194 195 157 /* 196 158 * Local variables:
