int DfsFreeBlock(int blocknum) { int fbvnum; int bitnum; int i; if((blocknum<0)||(blocknum>sb.filesys_blocknum)){ printf("Invalid blocknum = %d\n",blocknum); return DFS_FAIL; } fbvnum = (blocknum)/32; bitnum = (blocknum)%32; // printf("In DfsFreeBlock\n"); if (sb.valid == 0){ printf("File system not open!\n"); return DFS_FAIL; } LockHandleAcquire(lock_fbv); fbv[fbvnum] = (fbv[fbvnum] & invert(1<<bitnum))|(1 << bitnum); LockHandleRelease(lock_fbv); // for(i=0;i<10;i++){ // printf("fbv[%d] : 0x%x\n",i,fbv[i]); // } return DFS_SUCCESS; }
//------------------------------------------------------- // // int MboxSend(mbox_t handle,int length, void* message); // // Send a message (pointed to by "message") of length // "length" bytes to the specified mailbox. Messages of // length 0 are allowed. The call // blocks when there is not enough space in the mailbox. // Messages cannot be longer than MBOX_MAX_MESSAGE_LENGTH. // Note that the calling process must have opened the // mailbox via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxSend(mbox_t handle, int length, void* message) { // if(mbox_list[handle].msg_count >= MBOX_MAX_BUFFERS_PER_MBOX) { SemHandleWait(mbox_list[handle].empty); // } LockHandleAcquire(mbox_list[handle].lock); bcopy(message,mbox_list[handle].msgs[mbox_list[handle].head].message,length); mbox_list[handle].msgs[mbox_list[handle].head].length = length; mbox_list[handle].head = (mbox_list[handle].head + 1) % MBOX_MAX_BUFFERS_PER_MBOX; mbox_list[handle].msg_count++; // printf("MBOX INFO: handle: %d\n head: %d\n tail: %d\n in_use: %d\n msg_count: %d\n ",mbox_list[handle].handle, // mbox_list[handle].head,mbox_list[handle].tail,mbox_list[handle].in_use,mbox_list[handle].msg_count); // printf("user_list: "); // for(i = 0; i < MBOX_NUM_BUFFERS; i++) { // printf("%d",mbox_list[handle].users[i]); // } // printf("\n\n msg info: \n"); // for(i = 0; i < MBOX_MAX_MESSAGE_LENGTH; i++) { // printf("ID: %d, msg: %s, length: %d\n",mbox_list[handle].msgs[i].id, // mbox_list[handle].msgs[i].message, // mbox_list[handle].msgs[i].length); // } SemHandleSignal(mbox_list[handle].full); LockHandleRelease(mbox_list[handle].lock); return MBOX_SUCCESS; return MBOX_FAIL; }
//----------------------------------------------------------------- // DfsInodeOpen: search the list of all inuse inodes for the // specified filename. If the filename exists, return the handle // of the inode. If it does not, allocate a new inode for this // filename and return its handle. Return DFS_FAIL on failure. // Remember to use locks whenever you allocate a new inode. //----------------------------------------------------------------- uint32 DfsInodeOpen(char *filename) { uint32 i; if(!sb.valid) { printf("DfsInodeOpen: invalid file system\n"); return DFS_FAIL; } i = DfsInodeFilenameExists(filename); if(i != DFS_FAIL) { printf("[DEBUG] Opened inode:%d\n", i); return i; } while(LockHandleAcquire(dfs_inode_lock) != SYNC_SUCCESS); for(i = 0; i < sb.total_inodes; i++) { if(inodes[i].valid) { continue; } inodes[i].valid = 1; inodes[i].filesize = 0; dstrncpy(inodes[i].filename, filename, DFS_FILENAME_LENGTH); break; } LockHandleRelease(dfs_inode_lock); printf("[DEBUG] Opened inode:%d\n", i); return i; }
int DfsAllocateBlock() { // Check that file system has been validly loaded into memory // Find the first free block using the free block vector (FBV), mark it in use // Return handle to block int fbvnum; int bitnum; int block; uint32 v; int i; // printf("In DfsAllocateBlock\n"); if(sb.valid ==0){ printf("Filesystem not open!\n"); return DFS_FAIL; } LockHandleAcquire(lock_fbv); block = sb.filesys_datastart; fbvnum = block/32; while(fbv[fbvnum] == 0){ fbvnum+=1; if(fbvnum>=(DFS_FBV_MAX_NUM)){ fbvnum = block/32; } } v = fbv[fbvnum]; for (bitnum = 0;(v & (1 << bitnum)) == 0; bitnum++); fbv[fbvnum] &= invert(1 << bitnum); v = (fbvnum * 32) + bitnum; LockHandleRelease(lock_fbv); // for(i=0;i<10;i++){ // printf("fbv[%d]: 0x%x\n",i,fbv[i]); // } return (int)v; }
uint32 DfsAllocateBlock() { int i; uint32 bitnum; uint32 vector; // Check that file system has been validly loaded into memory if(!sb.valid) { printf("DfsAllocateBlock: Filesystem is not validly loaded into memory\n"); return DFS_FAIL; } while(LockHandleAcquire(dfs_fbv_lock) != SYNC_SUCCESS); // Find the first free block using the free block vector (FBV), mark it in use for(i = 0; i < sb.fbv_num_words; i++) { if(fbv[i] != 0) { break; } } if(i == sb.fbv_num_words) { printf("DfsAllocateBlock: Could not allocate block\n"); return DFS_FAIL; } vector = fbv[i]; for(bitnum = 0; (vector & (1 << bitnum)) == 0; bitnum++) {} fbv[i] &= invert(1 << bitnum); vector = (i * 32) + bitnum; dbprintf('d', "DfsAllocateBlock: Allocated block %d\n", vector); LockHandleRelease(dfs_fbv_lock); // Return handle to block return vector; }
//------------------------------------------------------- // // void MboxOpen(mbox_t); // // Open the mailbox for use by the current process. Note // that it is assumed that the internal lock/mutex handle // of the mailbox and the inuse flag will not be changed // during execution. This allows us to get the a valid // lock handle without a need for synchronization. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxOpen(mbox_t handle) { unsigned int curr_pid = GetCurrentPid(); // Check if handle is a valid number if(handle < 0 || handle >= MBOX_NUM_MBOXES){ return MBOX_FAIL; } // Check if the mbox is reserved (activated) if(system_mbox[handle].num_of_pid_inuse < 0){ return MBOX_FAIL; } // Acquire the lock if(LockHandleAcquire(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", handle); exitsim(); } // Update the number of pid used if(system_mbox[handle].mbox_pid_list[curr_pid] == 1){ printf("The mbox %d has already been opened\n", handle); } else if(system_mbox[handle].mbox_pid_list[curr_pid] == 0){ system_mbox[handle].num_of_pid_inuse += 1; system_mbox[handle].mbox_pid_list[curr_pid] = 1; } else{ printf("FATAL ERROR: Unkown Pid %d for mbox %d!\n", curr_pid, handle); // Release the lock if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } return MBOX_FAIL; } // Release the lock if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } return MBOX_SUCCESS; }
//------------------------------------------------------- // // int MboxSend(mbox_t handle,int length, void* message); // // Send a message (pointed to by "message") of length // "length" bytes to the specified mailbox. Messages of // length 0 are allowed. The call // blocks when there is not enough space in the mailbox. // Messages cannot be longer than MBOX_MAX_MESSAGE_LENGTH. // Note that the calling process must have opened the // mailbox via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxSend(mbox_t handle, int length, void* message) { int ibuff; int i; int cpid = GetCurrentPid(); char* cmessage = (char*) message; mbox* xbox = &mboxes[handle]; if(xbox->opened_pids[cpid] == false) { return MBOX_FAIL; } if(length > MBOX_MAX_MESSAGE_LENGTH) { return MBOX_FAIL; } // printf("***%d Waiting on mbox empty slot\n", cpid); SemHandleWait(xbox->s_mbox_emptyslots); // printf("******%d Done waiting on mbox empty slot\n", cpid); while(true) { // SemHandleWait(s_buff_emptyslots); while(LockHandleAcquire(l_buff) != SYNC_SUCCESS); for(ibuff = 0; ibuff < MBOX_NUM_BUFFERS; ibuff++) { if(mbox_buffers[ibuff].inuse == false) { break; } } if(ibuff != MBOX_NUM_BUFFERS) { // buffers are not full mbox_buffers[ibuff].inuse = true; LockHandleRelease(l_buff); break; } LockHandleRelease(l_buff); } // printf("=%d is waiting on mbox lock\n", cpid); while(LockHandleAcquire(xbox->l_mbox) != SYNC_SUCCESS); // printf("==%d has acquired mbox lock\n", cpid); xbox->cbobi[xbox->tail_cbobi] = ibuff; xbox->tail_cbobi = (xbox->tail_cbobi + 1) % MBOX_MAX_BUFFERS_PER_MBOX; for(i = 0; i < length; i++) { mbox_buffers[ibuff].msg[i] = cmessage[i]; } mbox_buffers[ibuff].length = length; mbox_buffers[ibuff].inuse = true; SemHandleSignal(xbox->s_mbox_fillslots); LockHandleRelease(xbox->l_mbox); // printf("===%d has released mbox lock\n", cpid); return MBOX_SUCCESS; }
int DfsInodeDelete(int handle) { int i; dfs_block indirect_table; uint32 *table; // printf("In DfsInodeDelete\n"); if (sb.valid == 0){ printf("File system not open!\n"); return DFS_FAIL; } if((handle<0)||(handle>DFS_INODE_MAX_NUM)){ printf("Invalid inode handle = %d\n",handle); return DFS_FAIL; } if(inodes[handle].inuse == 0){ printf("Inode not allocated!\n"); return DFS_FAIL; } LockHandleAcquire(lock_inode); //Free direct table then check if there is indirect address for(i=0;i<10;i++){ if(inodes[handle].direct[i]!=0){ if(DfsFreeBlock((int)inodes[handle].direct[i])==DFS_FAIL){ printf("Cannot free blocks in direct table!\n"); return DFS_FAIL; } inodes[handle].direct[i]=0; } } //Free the indirect table if(inodes[handle].indirect != 0){ table =(uint32 *)(&indirect_table); DfsReadBlock(inodes[handle].indirect,&indirect_table); for(i=0;i<(sb.filesys_blocksize)/sizeof(uint32);i++){ if(table[i]!=0){ if (DfsFreeBlock((int)table[i])== DFS_FAIL){ printf("Cannot free blocks in indirect table\n"); return DFS_FAIL; } } } if(DfsFreeBlock((int)inodes[handle].indirect)==DFS_FAIL){ printf("Cannot free blocks in indirect table\n"); } inodes[handle].indirect=0; } FreeEntry(handle); inodes[handle].filesize = 0; // for(i=0;i< FILENAME_LENGTH;i++){ // inodes[handle].filename[i]='\0'; // } inodes[handle].permission = 0; inodes[handle].type = 0; inodes[handle].ownerid = 0; inodes[handle].inuse = 0; LockHandleRelease(lock_inode); return DFS_SUCCESS; }
//------------------------------------------------------- // // int MboxRecv(mbox_t handle, int maxlength, void* message); // // Receive a message from the specified mailbox. The call // blocks when there is no message in the buffer. Maxlength // should indicate the maximum number of bytes that can be // copied from the buffer into the address of "message". // An error occurs if the message is larger than maxlength. // Note that the calling process must have opened the mailbox // via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns number of bytes written into message on success. // //------------------------------------------------------- int MboxRecv(mbox_t handle, int maxlength, void* message) { int ibuff; int cpid = GetCurrentPid(); int i; mbox* xbox = &mboxes[handle]; char* cmessage = (char*) message; if(xbox->opened_pids[cpid] == false) { return MBOX_FAIL; } // printf("***%d Waiting on mbox filled slot\n", cpid); SemHandleWait(xbox->s_mbox_fillslots); // printf("******%d Done waiting on mbox filled slot\n", cpid); // printf("=%d is waiting on mbox lock\n", cpid); while(LockHandleAcquire(xbox->l_mbox) != SYNC_SUCCESS); // printf("==%d has acquired mbox lock\n", cpid); ibuff = xbox->cbobi[xbox->head_cbobi]; if(ibuff < 0) { printf("Invalid message buffer index from cbobi.head: %d\n", xbox->head_cbobi); exitsim(); } if(mbox_buffers[ibuff].inuse == false) { LockHandleRelease(xbox->l_mbox); return MBOX_FAIL; } if(mbox_buffers[ibuff].length > maxlength) { LockHandleRelease(xbox->l_mbox); return MBOX_FAIL; } for(i = 0; i < mbox_buffers[ibuff].length; i++) { cmessage[i] = mbox_buffers[ibuff].msg[i]; } xbox->cbobi[xbox->head_cbobi] = -1; // invalidate the cbobi mbox_buffers[ibuff].inuse = false; xbox->head_cbobi = (xbox->head_cbobi + 1) % MBOX_MAX_BUFFERS_PER_MBOX; // SemHandleSignal(s_buff_emptyslots); SemHandleSignal(xbox->s_mbox_emptyslots); LockHandleRelease(xbox->l_mbox); // printf("===%d has released mbox lock\n", cpid); return mbox_buffers[ibuff].length; }
//----------------------------------------------------------------- // DfsFreeBlock deallocates a DFS block. //----------------------------------------------------------------- int DfsFreeBlock(uint32 blocknum) { if(!sb.valid) { printf("DfsFreeBlock: Filesystem is not validly loaded into memory\n"); return DFS_FAIL; } while(LockHandleAcquire(dfs_fbv_lock) != SYNC_SUCCESS); SetFreeVector(blocknum, 1); LockHandleRelease(dfs_fbv_lock); dbprintf('d', "DfsFreeBlock: Freed block %d\n", blocknum); return DFS_SUCCESS; }
//----------------------------------------------------------------- // DfsInodeDelete de-allocates any data blocks used by this inode, // including the indirect addressing block if necessary, then mark // the inode as no longer in use. Use locks when modifying the // "inuse" flag in an inode.Return DFS_FAIL on failure, and // DFS_SUCCESS on success. //----------------------------------------------------------------- int DfsInodeDelete(uint32 handle) { int i; dfs_block dfsb; int* inints = (int*) dfsb.data; if(!sb.valid) { printf("DfsInodeDelete: invalid file system\n"); return DFS_FAIL; } if(!inodes[handle].valid) { printf("DfsInodeDelete: invalid inode\n"); return DFS_FAIL; } while(LockHandleAcquire(dfs_fbv_lock) != SYNC_SUCCESS); if(DFS_IS_BLOCK_ENTRY_VALID(inodes[handle].indir_block_entry)) { DfsReadBlock(DFS_GET_BLOCK_NUM(inodes[handle].indir_block_entry), &dfsb); for(i = 0; i < (sb.blocksize / sizeof(int)); i++) { if(DFS_IS_BLOCK_ENTRY_VALID(inints[i])) { SetFreeVector(DFS_GET_BLOCK_NUM(inints[i]), 1); } } // clear out the indirect block entry table bzero(dfsb.data, sb.blocksize); DfsWriteBlock(DFS_GET_BLOCK_NUM(inodes[handle].indir_block_entry), &dfsb); SetFreeVector(DFS_GET_BLOCK_NUM(inodes[handle].indir_block_entry), 1); inodes[handle].indir_block_entry = DFS_SET_BLOCK_ENTRY(0, 0); } for(i = 0; i < 10; i++) { if(DFS_IS_BLOCK_ENTRY_VALID(inodes[handle].direct_block_entries[i])) { SetFreeVector(DFS_GET_BLOCK_NUM(inodes[handle].direct_block_entries[i]), 1); inodes[handle].direct_block_entries[i] = DFS_SET_BLOCK_ENTRY(0, 0); } } LockHandleRelease(dfs_fbv_lock); while(LockHandleAcquire(dfs_inode_lock) != SYNC_SUCCESS); inodes[handle].valid = 0; LockHandleRelease(dfs_inode_lock); return DFS_SUCCESS; }
int DfsInodeOpen(char *filename,int handle,int type,int ownerid,unsigned char permission) { int i,j; int handler; // printf("In DfsInodeOpen\n"); if(sb.valid == 0){ printf("File system not open!\n"); return DFS_FAIL; } if((handler = DfsInodeFilenameExists(filename,handle))!= DFS_FAIL){ printf("Open existing file!\n"); return handler; } else{ for(i=0;i<sb.inodenum;i++){ if(inodes[i].inuse == 0){ LockHandleAcquire(lock_inode); inodes[i].inuse = 1; inodes[i].filesize = 0; for(j=0;j<sb.dirnum;j++){ if(dir[j].inuse == 0){ inodes[i].dir = &dir[j]; break; } } inodes[i].permission = permission; inodes[i].type = type; inodes[i].ownerid = ownerid; handler=i; LockHandleRelease(lock_inode); if(InsertEntry(filename,handle,handler)== DFS_FAIL){ printf ("Error: Cannot insert inode %d into dir of inode %d\n",handler,handle); return DFS_FAIL; } return handler; } } } printf("No free inodes!\n"); return DFS_FAIL; }
//------------------------------------------------------- // // int MboxRecv(mbox_t handle, int maxlength, void* message); // // Receive a message from the specified mailbox. The call // blocks when there is no message in the buffer. Maxlength // should indicate the maximum number of bytes that can be // copied from the buffer into the address of "message". // An error occurs if the message is larger than maxlength. // Note that the calling process must have opened the mailbox // via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns number of bytes written into message on success. // //------------------------------------------------------- int MboxRecv(mbox_t handle, int maxlength, void* message) { int size; // if(mbox_list[handle].msg_count == 0) { SemHandleWait(mbox_list[handle].full); // } LockHandleAcquire(mbox_list[handle].lock); if (mbox_list[handle].msgs[mbox_list[handle].tail].length <= maxlength) { size = mbox_list[handle].msgs[mbox_list[handle].tail].length; } else { return MBOX_FAIL; } bcopy(mbox_list[handle].msgs[mbox_list[handle].tail].message,message, size); mbox_list[handle].tail = (mbox_list[handle].tail + 1) % MBOX_MAX_BUFFERS_PER_MBOX; mbox_list[handle].msg_count--; SemHandleSignal(mbox_list[handle].empty); LockHandleRelease(mbox_list[handle].lock); return size; }
//------------------------------------------------------- // // int MboxRecv(mbox_t handle, int maxlength, void* message); // // Receive a message from the specified mailbox. The call // blocks when there is no message in the buffer. Maxlength // should indicate the maximum number of bytes that can be // copied from the buffer into the address of "message". // An error occurs if the message is larger than maxlength. // Note that the calling process must have opened the mailbox // via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns number of bytes written into message on success. // //------------------------------------------------------- int MboxRecv(mbox_t handle, int maxlength, void* message) { int ct; unsigned int curr_pid = GetCurrentPid(); int system_buffer_index = system_mbox[handle].mbox_buffer_index_array[system_mbox[handle].mbox_buffer_tail]; // Check if the length of the message can fit into the buffer slot if(maxlength < 0 || maxlength > MBOX_MAX_MESSAGE_LENGTH){ return MBOX_FAIL; } // Check if handle is a valid number if(handle < 0 || handle >= MBOX_NUM_MBOXES){ return MBOX_FAIL; } // Check if the mbox is reserved (activated). If not, return FAIL if(system_mbox[handle].num_of_pid_inuse < 0){ return MBOX_FAIL; } // Check if the mbox is opened. If the mbox is not opened, return FAIL if(system_mbox[handle].mbox_pid_list[curr_pid] == 0){ printf("Mbox Send Error: The mbox %d hasn't been opened yet\n", handle); return MBOX_FAIL; } // Acquire the lock of the mbox if(LockHandleAcquire(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", handle); exitsim(); } // Else, check if the mbox is empty. If so, wait while(system_mbox[handle].mbox_buffer_slot_used == 0){ if(CondHandleWait(system_mbox[handle].mbox_buffer_fill) != SYNC_SUCCESS){ printf("FATAL ERROR: Wait on CV empty for mbox %d!\n", handle); exitsim(); } } // Acquire the lock of the mbox message buffer if(LockHandleAcquire(system_mbox_message.system_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", handle); exitsim(); } // Receive the message from the mbox for(ct = 0; ct < maxlength; ct++){ *((char *) message + ct) = system_mbox_message.system_message_buffer[system_buffer_index][ct]; } // Make the system buffer slot available again system_mbox_message.system_buffer_index_array[system_mbox[handle].mbox_buffer_tail] = 0; system_mbox_message.system_buffer_slot_used -= 1; // Update mbox used and mbox buffer tail info system_mbox[handle].mbox_buffer_slot_used -= 1; system_mbox[handle].mbox_buffer_tail = (system_mbox[handle].mbox_buffer_tail + 1) % MBOX_MAX_BUFFERS_PER_MBOX; // Signal system buffer empty CV if(CondHandleSignal(system_mbox_message.system_buffer_empty) != SYNC_SUCCESS){ printf("FATAL ERROR: Signal on CV empty for system buffer!\n"); exitsim(); } // Release the lock of the mbox message buffer if(LockHandleRelease(system_mbox_message.system_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the system buffer!\n"); exitsim(); } // Signal mbox empty CV if(CondHandleSignal(system_mbox[handle].mbox_buffer_empty) != SYNC_SUCCESS){ printf("FATAL ERROR: Signal on CV empty for mbox %d!\n", handle); exitsim(); } // Release the lock of the mbox if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } return MBOX_SUCCESS; }
//-------------------------------------------------------------------------------- // // int MboxCloseAllByPid(int pid); // // Scans through all mailboxes and removes this pid from their "open procs" list. // If this was the only open process, then it makes the mailbox available. Call // this function in ProcessFreeResources in process.c. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //-------------------------------------------------------------------------------- int MboxCloseAllByPid(int pid) { int ct; int clear_ct; int mbox_pid_status; // Check if the pid is valid if(pid < 0 || pid >= PROCESS_MAX_PROCS){ return MBOX_FAIL; } // Go througth all the mboxes for(ct = 0; ct < MBOX_NUM_MBOXES; ct++){ // Acquire the lock of the mbox if(LockHandleAcquire(system_mbox[ct].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", ct); exitsim(); } // Check if the pid is in the mbox's "open procs" list. // If so, remove the pid and make the mailbox available if no other proc opens the mbox // Else, do nothing mbox_pid_status = system_mbox[ct].mbox_pid_list[pid]; if(mbox_pid_status == 0){ // Do nothing } else if(mbox_pid_status == 1){ // Update the number of pid used system_mbox[ct].num_of_pid_inuse -= 1; system_mbox[ct].mbox_pid_list[pid] = 0; } else{ printf("FATAL ERROR: Unkown Pid %d for mbox %d\n", pid, ct); // Release the lock if(LockHandleRelease(system_mbox[ct].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", ct); exitsim(); } return MBOX_FAIL; } // Return the mbox to the pool of available mboxes for the system // Reset this mbox, clear rest of messages in this mbox (clear the linkings in the system) if(system_mbox[ct].num_of_pid_inuse == 0){ system_mbox[ct].num_of_pid_inuse = -1; for(clear_ct = 0; clear_ct < system_mbox[ct].mbox_buffer_slot_used; clear_ct++){ // Make the system buffer slot available again system_mbox_message.system_buffer_index_array[system_mbox[ct].mbox_buffer_tail] = 0; system_mbox_message.system_buffer_slot_used -= 1; system_mbox[ct].mbox_buffer_tail = (system_mbox[ct].mbox_buffer_tail + 1) % MBOX_MAX_BUFFERS_PER_MBOX; } } // Release the lock of the mbox if(LockHandleRelease(system_mbox[ct].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", ct); exitsim(); } } return MBOX_SUCCESS; }
//------------------------------------------------------- // // int MboxClose(mbox_t); // // Close the mailbox for use to the current process. // If the number of processes using the given mailbox // is zero, then disable the mailbox structure and // return it to the set of available mboxes. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxClose(mbox_t handle) { int clear_ct; unsigned int curr_pid = GetCurrentPid(); int mbox_pid_status = system_mbox[handle].mbox_pid_list[curr_pid]; // Check if handle is a valid number if(handle < 0 || handle >= MBOX_NUM_MBOXES){ return MBOX_FAIL; } // Check if the mbox is reserved (activated) if(system_mbox[handle].num_of_pid_inuse < 0){ return MBOX_FAIL; } // Acquire the lock if(LockHandleAcquire(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", handle); exitsim(); } if(mbox_pid_status == 0){ printf("The mbox %d has already been closed for process %d\n", handle, curr_pid); } else if(mbox_pid_status == 1){ // Update the number of pid used system_mbox[handle].num_of_pid_inuse -= 1; system_mbox[handle].mbox_pid_list[curr_pid] = 0; } else{ printf("FATAL ERROR: Unkown Pid %d for mbox %d\n", curr_pid, handle); // Release the lock if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } return MBOX_FAIL; } // Return the mbox to the pool of available mboxes for the system // Reset this mbox, clear rest of messages in this mbox (clear the linkings in the system) if(system_mbox[handle].num_of_pid_inuse == 0){ system_mbox[handle].num_of_pid_inuse = -1; for(clear_ct = 0; clear_ct < system_mbox[handle].mbox_buffer_slot_used; clear_ct++){ // Make the system buffer slot available again system_mbox_message.system_buffer_index_array[system_mbox[handle].mbox_buffer_tail] = 0; system_mbox_message.system_buffer_slot_used -= 1; system_mbox[handle].mbox_buffer_tail = (system_mbox[handle].mbox_buffer_tail + 1) % MBOX_MAX_BUFFERS_PER_MBOX; } } // Release the lock if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } return MBOX_SUCCESS; }
//------------------------------------------------------- // // int MboxSend(mbox_t handle,int length, void* message); // // Send a message (pointed to by "message") of length // "length" bytes to the specified mailbox. Messages of // length 0 are allowed. The call // blocks when there is not enough space in the mailbox. // Messages cannot be longer than MBOX_MAX_MESSAGE_LENGTH. // Note that the calling process must have opened the // mailbox via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxSend(mbox_t handle, int length, void* message) { int ct; int system_buffer_index; unsigned int curr_pid = GetCurrentPid(); // Check if the length of the message can fit into the buffer slot if(length < 0 || length > MBOX_MAX_MESSAGE_LENGTH){ return MBOX_FAIL; } // Check if handle is a valid number if(handle < 0 || handle >= MBOX_NUM_MBOXES){ return MBOX_FAIL; } // Check if the mbox is reserved (activated) if(system_mbox[handle].num_of_pid_inuse < 0){ return MBOX_FAIL; } // Check if the mbox is opened if(system_mbox[handle].mbox_pid_list[curr_pid] == 0){ printf("Mbox Send Error: The mbox %d hasn't been opened yet\n", handle); return MBOX_FAIL; } // Acquire the lock of the mbox if(LockHandleAcquire(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", handle); exitsim(); } // Else, check if the mbox is full. If so, wait while(system_mbox[handle].mbox_buffer_slot_used == MBOX_MAX_BUFFERS_PER_MBOX){ if(CondHandleWait(system_mbox[handle].mbox_buffer_empty) != SYNC_SUCCESS){ printf("FATAL ERROR: Wait on CV empty for mbox %d!\n", handle); exitsim(); } } // Acquire the lock of the mbox message buffer if(LockHandleAcquire(system_mbox_message.system_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the system buffer!\n"); exitsim(); } // Check if the system buffer is full. If so, wait while(system_mbox_message.system_buffer_slot_used == MBOX_NUM_BUFFERS){ // First Release the lock of the mbox if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } // Wait on the system CV if(CondHandleWait(system_mbox_message.system_buffer_empty) != SYNC_SUCCESS){ printf("FATAL ERROR: Wait on CV empty for system buffer!\n"); exitsim(); } // Re-Acquire the lock of the mbox if(LockHandleAcquire(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Acquire lock for the mbox %d!\n", handle); exitsim(); } } // Find out an available slot in the system message buffer for the message for(system_buffer_index = 0; system_buffer_index < MBOX_NUM_BUFFERS; system_buffer_index++){ if(system_mbox_message.system_buffer_index_array[system_buffer_index] == 0){ system_mbox_message.system_buffer_index_array[system_buffer_index] = 1; // Reserved the slot break; } } // Double check if the index is valid if(system_buffer_index == MBOX_NUM_BUFFERS){ printf("FATAL ERROR: System buffer sync error\n"); exitsim(); } // Put the message into the system message slot for(ct = 0; ct < length; ct++){ system_mbox_message.system_message_buffer[system_buffer_index][ct] = *((char *) message + ct); } // Set the mbox linking system_mbox[handle].mbox_buffer_index_array[system_mbox[handle].mbox_buffer_head] = system_buffer_index; // Update head and used info system_mbox_message.system_buffer_slot_used += 1; system_mbox[handle].mbox_buffer_slot_used += 1; system_mbox[handle].mbox_buffer_head = (system_mbox[handle].mbox_buffer_head + 1) % MBOX_MAX_BUFFERS_PER_MBOX; // Release the lock of the mbox message buffer if(LockHandleRelease(system_mbox_message.system_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the system buffer %d!\n", handle); exitsim(); } // Signal mbox fill CV if(CondHandleSignal(system_mbox[handle].mbox_buffer_fill) != SYNC_SUCCESS){ printf("FATAL ERROR: Signal on CV fill for mbox %d!\n", handle); exitsim(); } // Release the lock of the mbox if(LockHandleRelease(system_mbox[handle].mbox_buffer_lock) != SYNC_SUCCESS){ printf("FATAL ERROR: Release lock for the mbox %d!\n", handle); exitsim(); } return MBOX_SUCCESS; }
//------------------------------------------------------- // // int MboxSend(mbox_t handle,int length, void* message); // // Send a message (pointed to by "message") of length // "length" bytes to the specified mailbox. Messages of // length 0 are allowed. The call // blocks when there is not enough space in the mailbox. // Messages cannot be longer than MBOX_MAX_MESSAGE_LENGTH. // Note that the calling process must have opened the // mailbox via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxSend(mbox_t handle, int length, void* message) { int intrs; int wasEmpty = 0; Link * mbuffer_link; if(MailBox[handle].inuse == 0) { printf("Currently passed mailbox handle : %d by calling process : %d is unallocated\n", handle, GetCurrentPid()); return MBOX_FAIL; } if(MailBox[handle].procs_link[GetCurrentPid()] == false) { printf("Mailbox : %d not already opened by calling proces :%d\n", handle, GetCurrentPid()); return MBOX_FAIL; } intrs = DisableIntrs(); LockHandleAcquire(MailBox[handle].lock); while(AQueueLength(&MailBox[handle].buffers) == MBOX_MAX_BUFFERS_PER_MBOX || used_buffers == MBOX_NUM_BUFFERS) { CondHandleWait(MailBox[handle].moreSpace); } //printf("Buffer size of queue before inserting messager by : %d is : %d\n", GetCurrentPid(), AQueueLength(&MailBox[handle].buffers)); if(AQueueLength(&MailBox[handle].buffers) == 0) wasEmpty = 1; if(AQueueLength(&MailBox[handle].buffers) != MBOX_MAX_BUFFERS_PER_MBOX) { if(length > MBOX_MAX_MESSAGE_LENGTH) { printf("Messge passed by user process : %d larger than accepted message length (Messge length sent - %d)", GetCurrentPid(), length); return MBOX_FAIL; } bcopy(message, Messg_Buffers[used_buffers++].message, 8); Messg_Buffers[used_buffers - 1].size = length; //printf("Original Message : %s Copied : %s in : %d\n", (char *)message, (char *)(Messg_Buffers[used_buffers - 1].message), handle); if((mbuffer_link = AQueueAllocLink(&Messg_Buffers[used_buffers - 1])) == QUEUE_FAIL) { printf("FATAL Error : Link object could not be created for message buffer : %d in process : %d",used_buffers - 1, GetCurrentPid()); exitsim(); } if(AQueueInsertLast(&MailBox[handle].buffers, mbuffer_link) != QUEUE_SUCCESS) { printf("FATAL Error : Link object could not be created for message buffer : %d in process : %d",used_buffers - 1, GetCurrentPid()); exitsim(); } } //printf("Message inserted by process : %d using buffer : %d with current count : %d\n", GetCurrentPid(), buffer_no, AQueueLength(&MailBox[handle].buffers)); //if(wasEmpty) CondHandleSignal(MailBox[handle].moreData); LockHandleRelease(MailBox[handle].lock); RestoreIntrs(intrs); return MBOX_SUCCESS; }
//---------------------------------------------------------------------- // // doInterrupt // // Handle an interrupt or trap. // //---------------------------------------------------------------------- void dointerrupt (unsigned int cause, unsigned int iar, unsigned int isr, uint32 *trapArgs) { int result; int i; uint32 args[4]; int intrs; uint32 handle; int ihandle; dbprintf ('t',"Interrupt cause=0x%x iar=0x%x isr=0x%x args=0x%08x.\n", cause, iar, isr, (int)trapArgs); // If the TRAP_INSTR bit is set, this was from a trap instruction. // If the bit isn't set, this was a system interrupt. if (cause & TRAP_TRAP_INSTR) { cause &= ~TRAP_TRAP_INSTR; switch (cause) { case TRAP_CONTEXT_SWITCH: dbprintf ('t', "Got a context switch trap!\n"); ProcessSchedule (); ClkResetProcess(); break; case TRAP_EXIT: case TRAP_USER_EXIT: dbprintf ('t', "Got an exit trap!\n"); ProcessDestroy (currentPCB); ProcessSchedule (); ClkResetProcess(); break; case TRAP_PROCESS_FORK: dbprintf ('t', "Got a fork trap!\n"); break; case TRAP_PROCESS_SLEEP: dbprintf ('t', "Got a process sleep trap!\n"); ProcessSuspend (currentPCB); ProcessSchedule (); ClkResetProcess(); break; case TRAP_PRINTF: // Call the trap printf handler and pass the arguments and a flag // indicating whether the trap was called from system mode. dbprintf ('t', "Got a printf trap!\n"); TrapPrintfHandler (trapArgs, isr & DLX_STATUS_SYSMODE); break; case TRAP_OPEN: // Get the arguments to the trap handler. If this is a user mode trap, // copy them from user space. if (isr & DLX_STATUS_SYSMODE) { args[0] = trapArgs[0]; args[1] = trapArgs[1]; } else { char filename[32]; // trapArgs points to the trap arguments in user space. There are // two of them, so copy them to to system space. The first argument // is a string, so it has to be copied to system space and the // argument replaced with a pointer to the string in system space. MemoryCopyUserToSystem (currentPCB, (char *)trapArgs, (char *)args, sizeof(args[0])*2); MemoryCopyUserToSystem (currentPCB, (char *)(args[0]), (char *)filename, 31); // Null-terminate the string in case it's longer than 31 characters. filename[31] = '\0'; // Set the argument to be the filename args[0] = (uint32)filename; } // Allow Open() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, args[1] + 0x10000); printf ("Got an open with parameters ('%s',0x%x)\n", (char *)(args[0]), args[1]); RestoreIntrs (intrs); break; case TRAP_CLOSE: // Allow Close() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_READ: // Allow Read() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_WRITE: // Allow Write() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_DELETE: intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_SEEK: intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_PROCESS_GETPID: ProcessSetResult(currentPCB, GetCurrentPid()); break; case TRAP_PROCESS_CREATE: TrapProcessCreateHandler(trapArgs, isr & DLX_STATUS_SYSMODE); break; case TRAP_SEM_CREATE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = SemCreate(ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_SEM_WAIT: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = SemHandleWait(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_SEM_SIGNAL: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = SemHandleSignal(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_MALLOC: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = (int)malloc(currentPCB, ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_MFREE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = mfree(currentPCB, (void*)ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_LOCK_CREATE: ihandle = LockCreate(); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_LOCK_ACQUIRE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = LockHandleAcquire(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_LOCK_RELEASE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = LockHandleRelease(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_COND_CREATE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondCreate(ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_COND_WAIT: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondHandleWait(ihandle); ProcessSetResult(currentPCB, ihandle); //Return 1 or 0 break; case TRAP_COND_SIGNAL: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondHandleSignal(ihandle); ProcessSetResult(currentPCB, ihandle); //Return 1 or 0 break; case TRAP_COND_BROADCAST: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondHandleBroadcast(ihandle); ProcessSetResult(currentPCB, ihandle); //Return 1 or 0 break; default: printf ("Got an unrecognized trap (0x%x) - exiting!\n", cause); exitsim (); break; } } else { switch (cause) { case TRAP_TIMER: dbprintf ('t', "Got a timer interrupt!\n"); // ClkInterrupt returns 1 when 1 "process quantum" has passed, meaning // that it's time to call ProcessSchedule again. if (ClkInterrupt()) { ProcessSchedule (); } break; case TRAP_KBD: do { i = *((uint32 *)DLX_KBD_NCHARSIN); result = *((uint32 *)DLX_KBD_GETCHAR); printf ("Got a keyboard interrupt (char=0x%x(%c), nleft=%d)!\n", result, result, i); } while (i > 1); break; case TRAP_ACCESS: printf ("Exiting after illegal access at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_ADDRESS: printf ("Exiting after illegal address at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_ILLEGALINST: printf ("Exiting after illegal instruction at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_PAGEFAULT: MemoryPageFaultHandler(currentPCB); break; default: printf ("Got an unrecognized system interrupt (0x%x) - exiting!\n", cause); exitsim (); break; } } dbprintf ('t',"About to return from dointerrupt.\n"); // Note that this return may schedule a new process! intrreturn (); }
//------------------------------------------------------- // // int MboxRecv(mbox_t handle, int maxlength, void* message); // // Receive a message from the specified mailbox. The call // blocks when there is no message in the buffer. Maxlength // should indicate the maximum number of bytes that can be // copied from the buffer into the address of "message". // An error occurs if the message is larger than maxlength. // Note that the calling process must have opened the mailbox // via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns number of bytes written into message on success. // //------------------------------------------------------- int MboxRecv(mbox_t handle, int maxlength, void* message) { int intrs; int wasFull = 0, buffersSaturated = 0; mbox_message * user_mesg; Link *l; if(MailBox[handle].inuse == false) { printf("Currently passed mailbox handle : %d by calling process : %d is unallocated\n", handle, GetCurrentPid()); return MBOX_FAIL; } if(MailBox[handle].procs_link[GetCurrentPid()] == false) { printf("Mailbox : %d not already opened by calling proces :%d\n", handle, GetCurrentPid()); return MBOX_FAIL; } intrs = DisableIntrs(); LockHandleAcquire(MailBox[handle].lock); while(AQueueLength(&MailBox[handle].buffers) == 0) { //printf("Waiting for mailbox to have more messages\n"); CondHandleWait(MailBox[handle].moreData); } //printf("Received mailbox lock by calling process : %d with mailbox buffer count : %d\n", GetCurrentPid(), AQueueLength(&MailBox[handle].buffers)); if(AQueueLength(&MailBox[handle].buffers) == MBOX_MAX_BUFFERS_PER_MBOX) wasFull = 1; if(AQueueLength(&MailBox[handle].buffers) < MBOX_MAX_BUFFERS_PER_MBOX && used_buffers == MBOX_NUM_BUFFERS) buffersSaturated = 1; //printf("Obtained message in receiver : %d from buffer index : %d\n", user_mesg->size, (user_mesg - Messg_Buffers)); if((user_mesg = (mbox_message *)AQueueObject(MailBox[handle].buffers.first)) == NULL) { printf("Undefined/unallocated Link pointer obtained from mailbox queue with handle :%d in process : %d\n", handle, GetCurrentPid()); //printf("MailBox buffer size : %d\n", AQueueLength(&MailBox[handle].buffers)); return MBOX_FAIL; } if(maxlength < user_mesg->size) { printf("Message : %s requested by user process : %d larger than acceptable message length : %d (Messge length received : %d)\n", user_mesg->message, GetCurrentPid(), maxlength, user_mesg->size); return MBOX_FAIL; } bcopy(user_mesg->message, message, user_mesg->size); l = MailBox[handle].buffers.first; MailBox[handle].buffers.first = AQueueNext(MailBox[handle].buffers.first); if(AQueueRemove(&l) == QUEUE_FAIL) { printf("FATAL Error : Message object Link for buffer : %d received by process : %d could not be removed from queue of mailbox handle : %d",used_buffers, GetCurrentPid(), handle); exitsim(); } used_buffers--; //if(wasFull || buffersSaturated) CondHandleSignal(MailBox[handle].moreSpace); LockHandleRelease(MailBox[handle].lock); RestoreIntrs(intrs); return user_mesg; }
//------------------------------------------------------- // // int MboxSend(mbox_t handle,int length, void* message); // // Send a message (pointed to by "message") of length // "length" bytes to the specified mailbox. Messages of // length 0 are allowed. The call // blocks when there is not enough space in the mailbox. // Messages cannot be longer than MBOX_MAX_MESSAGE_LENGTH. // Note that the calling process must have opened the // mailbox via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns MBOX_SUCCESS on success. // //------------------------------------------------------- int MboxSend(mbox_t handle, int length, void* message) { int i; int qlen; Link *l; int exists = 0; //check if mailbox is real if(!&mboxs[handle]) return MBOX_FAIL; //check if pid opened this mailbox if(!AQueueEmpty(&mboxs[handle].pids ) ){ qlen = AQueueLength(&mboxs[handle].pids); l = AQueueFirst(&mboxs[handle].pids); for(i=0; i < qlen; i++){ if((int)AQueueObject(l) == GetCurrentPid()){ exists = 1; break; } l = AQueueNext(l); } //actuall checks if pid exists if(exists == 0){ return MBOX_FAIL; } //check if message longer than max length if(length > MBOX_MAX_MESSAGE_LENGTH) { return MBOX_FAIL; } //check for space in mailbox if((SemHandleWait(mboxs[handle].s_msg_empty)) == SYNC_FAIL ){ printf("bad sem handle wait in mbox send\n"); exitsim(); } //lock if(LockHandleAcquire(mboxs[handle].l) != SYNC_SUCCESS){ printf("FATAL ERROR: could not get lock in Mbox send!\n"); exitsim(); } for(i=0; i<MBOX_NUM_BUFFERS; i++){ if(mbox_messages[i].inuse == 0){ mbox_messages[i].inuse = 1; break; } } //creating mbox_message structure dstrncpy(mbox_messages[i].message, (char *) message, length); mbox_messages[i].length = length; if ((l = AQueueAllocLink(&mbox_messages[i])) == NULL) { printf("FATAL ERROR: could not allocate link for pid queue in Mbox Open!\n"); exitsim(); } //add message to end of queue AQueueInsertLast(&mboxs[handle].messages, l); //unlock if(LockHandleRelease(mboxs[handle].l) != SYNC_SUCCESS){ printf("FATAL ERROR: could not release lock in Mbox send!\n"); exitsim(); } if(SemHandleSignal(mboxs[handle].s_msg_full) == SYNC_FAIL){ printf("bad sem handle signal in mbox send\n"); exitsim(); } }else{ return MBOX_FAIL; } return MBOX_SUCCESS; }
//------------------------------------------------------- // // int MboxRecv(mbox_t handle, int maxlength, void* message); // // Receive a message from the specified mailbox. The call // blocks when there is no message in the buffer. Maxlength // should indicate the maximum number of bytes that can be // copied from the buffer into the address of "message". // An error occurs if the message is larger than maxlength. // Note that the calling process must have opened the mailbox // via MboxOpen. // // Returns MBOX_FAIL on failure. // Returns number of bytes written into message on success. // //------------------------------------------------------- int MboxRecv(mbox_t handle, int maxlength, void* message) { int i; int qlen; Link *l; int exists = 0; mbox_message *m; //check if mailbox is real if(!&mboxs[handle]) return MBOX_FAIL; //check if pid opened this mailbox if(!AQueueEmpty(&mboxs[handle].pids ) ){ qlen = AQueueLength(&mboxs[handle].pids); l = AQueueFirst(&mboxs[handle].pids); for(i=0; i < qlen; i++){ if((int)AQueueObject(l) == GetCurrentPid()){ exists = 1; break; } l = AQueueNext(l); } //actualy checks if pid exists if(exists == 0){ return MBOX_FAIL; } //wait until queue has something in it if(SemHandleWait(mboxs[handle].s_msg_full) == SYNC_FAIL){ printf("bad sem handle wait in mbox recv\n"); exitsim(); } //lock if(LockHandleAcquire(mboxs[handle].l) != SYNC_SUCCESS){ printf("FATAL ERROR: could not get lock in Mbox send!\n"); exitsim(); } l = AQueueFirst(&mboxs[handle].messages); m = (mbox_message *) l->object; //check if message longer than max length if(m->length > maxlength) { return MBOX_FAIL; } //copy message to local variable dstrncpy(message,(void*) m->message, m->length); //reset structure for use elsewhere m->inuse =0; //delete link AQueueRemove(&l); //unlock if(LockHandleRelease(mboxs[handle].l) != SYNC_SUCCESS){ printf("FATAL ERROR: could not release lock in Mbox send!\n"); exitsim(); } if(SemHandleSignal(mboxs[handle].s_msg_empty) == SYNC_FAIL){ printf("bad sem handle signal in mbox recv\n"); exitsim(); } }else{ return MBOX_FAIL; } return MBOX_SUCCESS; }