//---------------------------------------------------------------------- // // SemWait // // Wait on a semaphore. As described in Section 6.4 of _OSC_, // we decrement the counter and suspend the process if the // semaphore's value is less than 0. To ensure atomicity, // interrupts are disabled for the entire operation, but must be // turned on before going to sleep. // //---------------------------------------------------------------------- int SemWait (Sem *sem) { Link *l; int intrval; if (!sem) return SYNC_FAIL; intrval = DisableIntrs (); dbprintf ('I', "SemWait: Old interrupt value was 0x%x.\n", intrval); dbprintf ('s', "SemWait: Proc %d waiting on sem %d, count=%d.\n", GetCurrentPid(), (int)(sem-sems), sem->count); if (sem->count <= 0) { dbprintf('s', "SemWait: putting process %d to sleep\n", GetCurrentPid()); if ((l = AQueueAllocLink ((void *)currentPCB)) == NULL) { printf("FATAL ERROR: could not allocate link for semaphore queue in SemWait!\n"); exitsim(); } if (AQueueInsertLast (&sem->waiting, l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not insert new link into semaphore waiting queue in SemWait!\n"); exitsim(); } ProcessSleep(); // Don't decrement couter here because that's handled in SemSignal for us } else { sem->count--; // Decrement internal counter dbprintf('s', "SemWait: Proc %d granted permission to continue by sem %d\n", GetCurrentPid(), (int)(sem-sems)); } RestoreIntrs (intrval); return SYNC_SUCCESS; }
//--------------------------------------------------------------------------- // CondHandleSignal // // This call wakes up exactly one process waiting on the condition // variable, if at least one is waiting. If there are no processes // waiting on the condition variable, it does nothing. In either case, // the calling process must have acquired the lock associated with // condition variable for this call to succeed, in which case it returns // 0. If the calling process does not own the lock, it returns 1, // indicating that the call was not successful. This function should be // written in such a way that the calling process should retain the // acquired lock even after the call completion (in other words, it // should not release the lock it has already acquired before the call). // // Note that the process woken up by this call tries to acquire the lock // associated with the condition variable as soon as it wakes up. Thus, // for such a process to run, the process invoking CondHandleSignal // must explicitly release the lock after the call is complete. //--------------------------------------------------------------------------- int CondSignal(Cond *c) { Link *l; int intrs; PCB *pcb; if (!c) return SYNC_FAIL; intrs = DisableIntrs (); dbprintf ('s', "CondSignal: Proc %d signalling cond %d.\n", GetCurrentPid(), (int)(c-conds)); if (c->lock->pid != GetCurrentPid()) { dbprintf('s', "CondSignal: Proc %d does not own cond %d.\n", GetCurrentPid(), (int)(c-conds)); return SYNC_FAIL; } if (!AQueueEmpty(&c->waiting)) { // there is a process to wake up l = AQueueFirst(&c->waiting); pcb = (PCB *)AQueueObject(l); if (AQueueRemove(&l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not remove link from cond queue in CondSignal!\n"); exitsim(); } dbprintf ('s', "CondSignal: Waking up PID %d, it still needs to acquire lock.\n", GetPidFromAddress(pcb)); ProcessWakeup (pcb); } else { dbprintf('s', "CondSignal: Proc %d signalled, but no processes were waiting.\n", GetCurrentPid()); } RestoreIntrs (intrs); return SYNC_SUCCESS; }
//--------------------------------------------------------------------------- // LockHandleRelease // // This procedure releases the unique lock described by the handle. It // first checks whether the lock is a valid lock. If not, it returns SYNC_FAIL. // If the lock is a valid lock, it should check whether the calling // process actually holds the lock. If not it returns SYNC_FAIL. Otherwise it // releases the lock, and returns SYNC_SUCCESS. //--------------------------------------------------------------------------- int LockRelease(Lock *k) { Link *l; int intrs; PCB *pcb; if (!k) return SYNC_FAIL; intrs = DisableIntrs (); dbprintf ('s', "LockRelease: Proc %d releasing lock %d.\n", GetCurrentPid(), (int)(k-locks)); if (k->pid != GetCurrentPid()) { dbprintf('s', "LockRelease: Proc %d does not own lock %d.\n", GetCurrentPid(), (int)(k-locks)); return SYNC_FAIL; } k->pid = -1; if (!AQueueEmpty(&k->waiting)) { // there is a process to wake up l = AQueueFirst(&k->waiting); pcb = (PCB *)AQueueObject(l); if (AQueueRemove(&l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not remove link from lock queue in LockRelease!\n"); exitsim(); } dbprintf ('s', "LockRelease: Waking up PID %d, assigning lock.\n", (int)(GetPidFromAddress(pcb))); k->pid = GetPidFromAddress(pcb); ProcessWakeup (pcb); } RestoreIntrs (intrs); return SYNC_SUCCESS; }
//--------------------------------------------------------------------------- // CondHandleWait // // This function makes the calling process block on the condition variable // till either ConditionHandleSignal or ConditionHandleBroadcast is // received. The process calling CondHandleWait must have acquired the // lock associated with the condition variable (the lock that was passed // to CondCreate. This implies the lock handle needs to be stored // somewhere. hint! hint!) for this function to // succeed. If the calling process has not acquired the lock, it does not // block on the condition variable, but a value of 1 is returned // indicating that the call was not successful. Return value of 0 implies // that the call was successful. // // This function should be written in such a way that the calling process // should release the lock associated with this condition variable before // going to sleep, so that the process that intends to signal this // process could acquire the lock for that purpose. After waking up, the // blocked process should acquire (i.e. wait on) the lock associated with // the condition variable. In other words, this process does not // "actually" wake up until the process calling CondHandleSignal or // CondHandleBroadcast releases the lock explicitly. //--------------------------------------------------------------------------- int CondWait(Cond *c) { Link *l; int intrval; if (!c) return SYNC_FAIL; // Conds are atomic intrval = DisableIntrs (); dbprintf ('I', "CondWait: Old interrupt value was 0x%x.\n", intrval); // Check to see if the current process owns the lock if (c->lock->pid != GetCurrentPid()) { dbprintf('s', "CondWait: Proc %d does not own cond %d\n", GetCurrentPid(), (int)(c-conds)); RestoreIntrs(intrval); return SYNC_FAIL; } dbprintf ('s', "CondWait: Proc %d waiting on cond %d. Putting to sleep.\n", GetCurrentPid(), (int)(c-conds)); if ((l = AQueueAllocLink ((void *)currentPCB)) == NULL) { printf("FATAL ERROR: could not allocate link for cond queue in CondWait!\n"); exitsim(); } if (AQueueInsertLast (&c->waiting, l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not insert new link into cond waiting queue in CondWait!\n"); exitsim(); } // Release the lock before going to sleep LockRelease(c->lock); RestoreIntrs(intrval); // Don't want interrupts disabled while we sleep ProcessSleep(); // Immediately acquire the lock upon waking LockAcquire(c->lock); return SYNC_SUCCESS; }
//------------------------------------------------------- // // 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) { int i; for(i = 0; i < MBOX_NUM_BUFFERS; i++) { if(GetCurrentPid() == mbox_list[handle].users[i]) { printf("Process has already opened this mailbox\n"); return MBOX_FAIL; } } // PrintUsersByHandle(handle); if (handle >= 0 && handle < MBOX_NUM_MBOXES) { //modified (MBOX_NUM_BOXES) // printf("handle = %d, in_use = %d, message count = %d\n",handle, mbox_list[handle].in_use, mbox_list[handle].msg_count); if (mbox_list[handle].in_use >= 0 //&& // mbox_list[handle].msg_count < MBOX_MAX_BUFFERS_PER_MBOX ) { // printf("second if\n"); for (i = 0; i < MBOX_NUM_BUFFERS; i++) { if (mbox_list[handle].users[i] == -1) { // printf("free users space"); mbox_list[handle].users[i] = GetCurrentPid(); mbox_list[handle].in_use++; return MBOX_SUCCESS; } } } } return MBOX_FAIL; }
int FileClose(int handle) { if(handle > (FILE_MAX_OPEN_FILES-1)) { printf("FileClose -- FD handle number greater than %d!\n", FILE_MAX_OPEN_FILES-1); return(FILE_FAIL); } if(fd_array[handle].FD_Valid == 0) { printf("FileClose -- FD handle not valid!\n"); return(FILE_FAIL); } if(fd_array[handle].FD_PID != GetCurrentPid()) { printf("FileClose -- FD handle does not belong to current process #%d,\n", GetCurrentPid()); return(FILE_FAIL); } // Close the file descriptor handle (mark as not valid) fd_array[handle].FD_Valid = 0; dbprintf('F', "FileClose -- Successfully closed file descriptor #%d,\n", handle); return(FILE_SUCCESS); }
//------------------------------------------------------- // // mbox_t MboxCreate(); // // Allocate an available mailbox structure for use. // // Returns the mailbox handle on success // Returns MBOX_FAIL on error. // //------------------------------------------------------- mbox_t MboxCreate() { mbox_t mbox_no = MBOX_NUM_MBOXES; for(i = 0; i < MBOX_NUM_MBOXES;i++) { if(MailBox[i].inuse == false) { mbox_no = i; break; } } if(mbox_no == MBOX_NUM_MBOXES) { printf("MailBox cannot be assigned to the calling process : %d\n", GetCurrentPid()); return MBOX_FAIL; } MailBox[mbox_no].inuse = true; if((MailBox[mbox_no].lock = LockCreate()) == SYNC_FAIL) { printf("MailBox cannot associate a lock with itself for calling process : %d\n", GetCurrentPid()); return MBOX_FAIL; } if((MailBox[mbox_no].moreData = CondCreate(MailBox[mbox_no].lock)) == SYNC_FAIL) { printf("MailBox cannot associate a cond var for buffer emptiness calling process : %d\n", GetCurrentPid()); return MBOX_FAIL; } if((MailBox[mbox_no].moreSpace = CondCreate(MailBox[mbox_no].lock)) == SYNC_FAIL) { printf("MailBox cannot associate a cond var for buffer saturation for calling process : %d\n", GetCurrentPid()); return MBOX_FAIL; } if(AQueueInit(&MailBox[mbox_no].buffers) == QUEUE_FAIL) { printf("FATAL Error : Available mailbox : %d cannot have its buffer queue initialized for process : %d\n", mbox_no, GetCurrentPid()); return MBOX_FAIL; //exitsim(); } for(i = 0; i < PROCESS_MAX_PROCS; i++) { MailBox[mbox_no].procs_link[i] = 0; } //MailBox[mbox_no].tail = 0; //MailBox[mbox_no].head = 1; MailBox[mbox_no].process_count = 0; //printf("Created mailbox with handle : %d\n", mbox_no); return mbox_no; }
int FileWrite(int handle, void *mem, int num_bytes) { int bytes_written; if(handle > (FILE_MAX_OPEN_FILES-1)) { printf("FileWrite -- FD handle number greater than %d!\n", FILE_MAX_OPEN_FILES-1); return(FILE_FAIL); } if(fd_array[handle].FD_Valid == 0) { printf("FileWrite -- FD handle not valid!\n"); return(FILE_FAIL); } if(fd_array[handle].FD_PID != GetCurrentPid()) { printf("FileWrite -- FD handle does not belong to current process #%d,\n", GetCurrentPid()); return(FILE_FAIL); } if(fd_array[handle].FD_Mode == FILE_READ) { printf("FileWrite -- FD handle does not have write privileges\n"); return(FILE_FAIL); } if(num_bytes < 0) { printf("FileWrite -- num_bytes is less than zero!\n"); return(FILE_FAIL); } if( (fd_array[handle].FD_CurrentPosition+num_bytes) > (10*sb.FS_BlockSize+(sb.FS_BlockSize*sb.FS_BlockSize/4)) ) { printf("FileWrite -- File is too big!\n"); return(FILE_FAIL); } bytes_written = DfsInodeWriteBytes(fd_array[handle].FD_InodeHandle, mem, fd_array[handle].FD_CurrentPosition, num_bytes); if(bytes_written == -1) { printf("FileWrite -- Write to file failed!\n"); return(FILE_FAIL); } fd_array[handle].FD_CurrentPosition += bytes_written; dbprintf('F', "FileWrite -- write of %d bytes successful\n", bytes_written); dbprintf('F',"FileWrite -- New position for File Descriptor #%d ", handle); dbprintf('F',"is %d\n", fd_array[handle].FD_CurrentPosition); return(bytes_written); }
int FileSeek(int handle, int num_bytes, int from_where) { int filesize; int new_position; if(handle > (FILE_MAX_OPEN_FILES-1)) { printf("FileSeek -- FD handle number greater than %d!\n", FILE_MAX_OPEN_FILES-1); return(FILE_FAIL); } if(fd_array[handle].FD_Valid == 0) { printf("FileSeek -- FD handle not valid!\n"); return(FILE_FAIL); } if(fd_array[handle].FD_PID != GetCurrentPid()) { printf("FileSeek -- FD handle does not belong to current process #%d,\n", GetCurrentPid()); return(FILE_FAIL); } filesize = DfsInodeFilesize(fd_array[handle].FD_InodeHandle); if(filesize == -1) { printf("FileSeek -- Could not get filesize\n"); return(FILE_FAIL); } dbprintf('F',"FileSeek -- Filesize for File Descriptor #%d ", handle); dbprintf('F',"is %d\n", filesize); if(from_where == FILE_SEEK_SET) new_position = num_bytes; else if(from_where == FILE_SEEK_END) new_position = filesize + num_bytes; else if(from_where == FILE_SEEK_CUR) new_position = fd_array[handle].FD_CurrentPosition + num_bytes; else { printf("FileSeek -- Invalid from_where value!\n"); return(FILE_FAIL); } if(new_position < 0) new_position = 0; fd_array[handle].FD_CurrentPosition = new_position; fd_array[handle].FD_EOF_Flag = 0; dbprintf('F',"FileSeek -- New position for File Descriptor #%d ", handle); dbprintf('F',"is %d\n", fd_array[handle].FD_CurrentPosition); return(FILE_SUCCESS); }
//---------------------------------------------------------------------- // // SemSignal // // Signal on a semaphore. Again, details are in Section 6.4 of // _OSC_. // //---------------------------------------------------------------------- int SemSignal (Sem *sem) { Link *l; int intrs; PCB *pcb; if (!sem) return SYNC_FAIL; intrs = DisableIntrs (); dbprintf ('s', "SemSignal: Process %d Signalling on sem %d, count=%d.\n", GetCurrentPid(), (int)(sem-sems), sem->count); // Increment internal counter before checking value sem->count++; if (sem->count > 0) { // check if there is a process to wake up if (!AQueueEmpty(&sem->waiting)) { // there is a process to wake up l = AQueueFirst(&sem->waiting); pcb = (PCB *)AQueueObject(l); if (AQueueRemove(&l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not remove link from semaphore queue in SemSignal!\n"); exitsim(); } dbprintf ('s', "SemSignal: Waking up PID %d.\n", (int)(GetPidFromAddress(pcb))); ProcessWakeup (pcb); // Decrement counter on behalf of woken up PCB sem->count--; } } RestoreIntrs (intrs); return SYNC_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 cpid = GetCurrentPid(); uint32 intrval; int j; mbox* xbox = &mboxes[handle]; if(xbox->opened_pids[cpid] == false) { return MBOX_FAIL; } xbox->opened_pids[cpid] = false; intrval = DisableIntrs(); xbox->opened_pids_count -= 1; if(xbox->opened_pids_count == 0) { // reset the mbox for(j = xbox->head_cbobi; j <= xbox->tail_cbobi; (j = (j+1) % MBOX_MAX_BUFFERS_PER_MBOX)) { mbox_buffers[xbox->cbobi[j]].inuse = false; xbox->cbobi[j] = -1; } //sems[xbox->s_mbox_emptyslots].inuse = false; //sems[xbox->s_mbox_fillslots].inuse = false; //locks[xbox->l_mbox].inuse = false; xbox->head_cbobi = 0; xbox->tail_cbobi = 0; xbox->inuse = false; } RestoreIntrs(intrval); return MBOX_SUCCESS; }
TProcessHandle CProcess::GetCurrentHandle(void) { #if defined(NCBI_OS_MSWIN) return GetCurrentProcess(); #elif defined(NCBI_OS_UNIX) return GetCurrentPid(); #endif }
//---------------------------------------------------------------------- // // ProcessDestroy // // Destroy a process by setting its status to zombie and putting it // on the zombie queue. The next time the scheduler is called, this // process will be marked as free. We can't necessarily do it now // because we might be the currently running process. // // NOTE: This must only be called from an interrupt or trap. However, // it need not be followed immediately by a ProcessSchedule() because // the process can continue running. // //---------------------------------------------------------------------- void ProcessDestroy (PCB *pcb) { dbprintf ('p', "ProcessDestroy (%d): function started\n", GetCurrentPid()); ProcessSetStatus (pcb, PROCESS_STATUS_ZOMBIE); if (AQueueRemove(&(pcb->l)) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not remove link from queue in ProcessDestroy!\n"); GracefulExit(); } if ((pcb->l = AQueueAllocLink(pcb)) == NULL) { printf("FATAL ERROR: could not get link for zombie PCB in ProcessDestroy!\n"); GracefulExit(); } if (AQueueInsertFirst(&zombieQueue, pcb->l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not insert link into runQueue in ProcessWakeup!\n"); GracefulExit(); } dbprintf ('p', "ProcessDestroy (%d): function complete\n", GetCurrentPid()); }
//--------------------------------------------------------------------------- // CondHandleBroadcast // // This function is very similar to CondHandleSignal. But instead of // waking only one process, it wakes up all the processes waiting on the // condition variable. For this call to succeed, the calling process must // have acquired the lock associated with the condition variable. This // function should be written in such a way that the calling process // should retain the lock even after call completion. // // Note that the process woken up by this call tries to acquire the lock // associated with the condition variable as soon as it wakes up. Thus, // for such a process to run, the process invoking CondHandleBroadcast // must explicitly release the lock after the call completion. //--------------------------------------------------------------------------- int CondBroadcast(Cond *c) { if (!c) return SYNC_FAIL; if (c->lock->pid != GetCurrentPid()) { dbprintf('s', "CondBroadcast: Proc %d tried to broadcast, but it doesn't own cond %d\n", GetCurrentPid(), (int)(c-conds)); return SYNC_FAIL; } while (!AQueueEmpty(&c->waiting)) { if (CondSignal(c) != SYNC_SUCCESS) { dbprintf('s', "CondBroadcast: Proc %d failed in signalling cond %d\n", GetCurrentPid(), (int)(c-conds)); return SYNC_FAIL; } } dbprintf('s', "CondBroadcast: Proc %d successful broadcast on cond %d, still needs to release lock\n", GetCurrentPid(), (int)(c-conds)); return SYNC_SUCCESS; }
//---------------------------------------------------------------------- // // ProcessSuspend // // Place a process in suspended animation until it's // awakened by ProcessAwaken. // // NOTE: This must only be called from an interrupt or trap. It // should be immediately followed by ProcessSchedule(). // //---------------------------------------------------------------------- void ProcessSuspend (PCB *suspend) { // Make sure it's already a runnable process. dbprintf ('p', "ProcessSuspend (%d): function started\n", GetCurrentPid()); ASSERT (suspend->flags & PROCESS_STATUS_RUNNABLE, "Trying to suspend a non-running process!\n"); ProcessSetStatus (suspend, PROCESS_STATUS_WAITING); if (AQueueRemove(&(suspend->l)) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not remove process from run Queue in ProcessSuspend!\n"); GracefulExit(); } if ((suspend->l = AQueueAllocLink(suspend)) == NULL) { printf("FATAL ERROR: could not get Queue Link in ProcessSuspend!\n"); GracefulExit(); } if (AQueueInsertLast(&waitQueue, suspend->l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not insert suspend PCB into waitQueue!\n"); GracefulExit(); } dbprintf ('p', "ProcessSuspend (%d): function complete\n", GetCurrentPid()); }
//------------------------------------------------------- // // 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; }
//------------------------------------------------------- // // 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) { Link *l; if(!&mboxs[handle]) return MBOX_FAIL; if ((l = AQueueAllocLink ((void *)GetCurrentPid())) == NULL) { printf("FATAL ERROR: could not allocate link for pid queue in Mbox Open!\n"); exitsim(); } if (AQueueInsertLast (&mboxs[handle].pids, l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not insert new link into pid queue in Mbox Open!\n"); exitsim(); } return MBOX_SUCCESS; }
//------------------------------------------------------- // // 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) { int intrs; if(MailBox[handle].inuse == false) { printf("Currently passed mailbox handle : %d by calling process : %d is unallocated\n", handle ,GetCurrentPid()); return MBOX_FAIL; } intrs = DisableIntrs (); MailBox[handle].process_count++; MailBox[handle].procs_link[GetCurrentPid()] = 1; RestoreIntrs (intrs); return MBOX_SUCCESS; }
//------------------------------------------------------- // // 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) { int cpid = GetCurrentPid(); uint32 intrval; if(handle > MBOX_NUM_MBOXES || handle < 0) { return MBOX_FAIL; } if(mboxes[handle].inuse == false) { return MBOX_FAIL; } if(mboxes[handle].opened_pids[cpid] == false) { mboxes[handle].opened_pids[cpid] = true; intrval = DisableIntrs(); mboxes[handle].opened_pids_count += 1; RestoreIntrs(intrval); } 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 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; }
//------------------------------------------------------- // // 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 i; int pid = GetCurrentPid(); if (handle >= 0 && handle < MBOX_NUM_MBOXES) { //modified (MBOX_NUM_BOXES) if (mbox_list[(int)handle].in_use > 1) { for (i = 0; i < MBOX_NUM_BUFFERS; i++) { if (mbox_list[(int)handle].users[i] == pid) { mbox_list[(int)handle].users[i] = -1; mbox_list[(int)handle].in_use--; // printf("MboxClose: handle = %d in_use = %d", handle, mbox_list[(int)handle].in_use); } } return MBOX_SUCCESS; }else if(mbox_list[(int)handle].in_use == 1) { mbox_list[(int)handle].in_use = -1; } } return MBOX_FAIL; }
//------------------------------------------------------- // // 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 i; int length; Link *l; if(!&mboxs[handle]) return MBOX_FAIL; if(!AQueueEmpty(&mboxs[handle].pids)){ length = AQueueLength(&mboxs[handle].pids); l = AQueueFirst(&mboxs[handle].pids); for(i=0; i < length; i++){ if((int)AQueueObject(l) == GetCurrentPid()){ AQueueRemove(&l); break; } l = AQueueNext(l); } } if(AQueueEmpty(&mboxs[handle].pids)){ while(!AQueueEmpty(&mboxs[handle].messages)){ l = AQueueFirst(&mboxs[handle].messages); AQueueRemove(&l); } mboxs[handle].inuse = 0; } return MBOX_SUCCESS; }
//--------------------------------------------------------------------------- // LockHandleAcquire // // This routine acquires a lock given its handle. The handle must be a // valid handle for this routine to succeed. In that case this routine // returns SYNC_FAIL. Otherwise the routine returns SYNC_SUCCESS. // // Your implementation should be such that if a process that already owns // the lock calls LockHandleAcquire for that lock, it should not block. //--------------------------------------------------------------------------- int LockAcquire(Lock *k) { Link *l; int intrval; if (!k) return SYNC_FAIL; // Locks are atomic intrval = DisableIntrs (); dbprintf ('I', "LockAcquire: Old interrupt value was 0x%x.\n", intrval); // Check to see if the current process owns the lock if (k->pid == GetCurrentPid()) { dbprintf('s', "LockAcquire: Proc %d already owns lock %d\n", GetCurrentPid(), (int)(k-locks)); RestoreIntrs(intrval); return SYNC_SUCCESS; } dbprintf ('s', "LockAcquire: Proc %d asking for lock %d.\n", GetCurrentPid(), (int)(k-locks)); if (k->pid >= 0) { // Lock is already in use by another process dbprintf('s', "LockAcquire: putting process %d to sleep\n", GetCurrentPid()); if ((l = AQueueAllocLink ((void *)currentPCB)) == NULL) { printf("FATAL ERROR: could not allocate link for lock queue in LockAcquire!\n"); exitsim(); } if (AQueueInsertLast (&k->waiting, l) != QUEUE_SUCCESS) { printf("FATAL ERROR: could not insert new link into lock waiting queue in LockAcquire!\n"); exitsim(); } ProcessSleep(); } else { dbprintf('s', "LockAcquire: lock is available, assigning to proc %d\n", GetCurrentPid()); k->pid = GetCurrentPid(); } RestoreIntrs(intrval); return SYNC_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 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 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 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; }
//---------------------------------------------------------------------- // // 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 (); }
//-------------------------------------------------------------------------- // ProcessKill destroys the current process and then calls ProcessSchedule. // Therefore, you can only call ProcessKill from inside of a trap. //-------------------------------------------------------------------------- void ProcessKill() { dbprintf('m', "ProcessKill: killing processid %d\n", GetCurrentPid()); ProcessDestroy(currentPCB); ProcessSchedule(); }
//------------------------------------------------------- // // 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; }