void _ioreq_handle_idle_request(Drive *d){ Status status; Key key; Iorequest *req; key.v = (void *) d; status = _q_remove_by_key( idle_q, (void **) &req, key ); if(status == NOT_FOUND || status == EMPTY_QUEUE){ d->state=IDLE; req = NULL; //wasn't found return; } else if (status != SUCCESS){ _kpanic("handle_idle_request", "remove status", status); } if (! (_ata_pio_read_status(d) & (BSY | DRQ)) ){ if (req->read){ //send read request and add the data queue d->state=READING; req->st = WAIT_ON_DATA; _q_insert(data_q, (void *) req, key); _ata_pio_send_read(req->fd->device_data); } else { //transfer data and send write reqest d->state=WRITING; _ata_pio_send_write(req->fd->device_data); _ata_pio_write_fd_block(req->fd); _fd_writeDone(req->fd); _ioreq_dealloc(req); } }else { //no idle request on disk, despite removing from idle queue.. this shouldn't happen _q_insert(idle_q, (void *) req, key); } }
/** * Removes the PCB from the buf_block queue. Note, the PCB of the process is * still returned even if the PCB could not be removed from the buf_block * queue, but the PCB may be 0 if the corresponding process could not be found. * * @param index The index in the requests array of the process to * remove. * returns The PCB of the process that was removed, or 0 if the * index was too large. Note, the PCB returned may be 0 * if the corresponding process could not be found. */ Pcb *_ps2_remove_from_queue( Uint8 index ){ if( index >= TOTAL_IO_REQS ) return 0; void *data; Key key; key.u = requests[ index ]->pid; Status status = _q_remove_by_key( _buf_block, &data, key ); Pcb *pcb = ( Pcb* ) data; if( status != SUCCESS ){ prt_status( "keyboard, write active: Unable to remove process" " in buf block queue!\nError: %s\n", status); } return pcb; }
/** * Performs a blocking buffered read for keyboard input. * * Keystrokes are stored in the buffer and will not stop filling the buffer * until 'size' characters has been read. If there is an error when processing * the read request, the buffer will be left untouched. Otherwise undefined * behavior is defined for errors after the read request is processed. Note, * only user programs which have focus will recieve characters. * * @param buf The buffer to fill with character input from the keyboard. * @param size The number of characters to read. */ int buf_read( char* buf, int size, Pcb* cur ){ // Create an IO-Request block int index = _ps2_get_io_req(); if( index == -1 ){ Key key; key.u = cur->pid; void *data; _q_remove_by_key( _buf_block, &data, key ); _sched( cur ); return 0; } // Initialize IO-request requests[index]->pid = cur->pid; requests[index]->pdt = (Uint32)cur->pdt; requests[index]->buf = buf; requests[index]->size = size; requests[index]->index = 0; return 1; }
void _ioreq_handle_data_request(Drive *d){ Status status; Key key; Iorequest *req; key.v = d; status = _q_remove_by_key( data_q, (void **) &req, key ); if(status == NOT_FOUND || status == EMPTY_QUEUE){ req = NULL; //wasn't found //no data request on disk. Unsolicited data int i,j; for (i =0; i< 4;i++){ for (j=0;j<4;j++){ if (&_busses[i].drives[j]==d){ c_printf("bus[%d].drive[%d] %s",i,j,d->model); } } } _kpanic("handle_data_request", "Got unsolicited data.",FAILURE); return; } if (req->st == WAIT_ON_DATA){ if (req->read){ //send read request and add the data queue req->d->state=IDLE; _ata_read_finish(req->fd); _ioreq_dealloc(req); } else { //Unsolicited data... _kpanic("handle_data_request", "Got unsolicited, but waiting to write only.",FAILURE); } }else { //no data request on disk. Unsolicited data _kpanic("handle_data_request", "Got unsolicited data.",FAILURE); } }
void _zombify( pcb_t *pcb ) { pcb_t *parent; status_t stat; pid_t pid; key_t key; info_t *info; // sanity check if( pcb == NULL ) { _kpanic( "_zombify", "null pcb", 0 ); } // Locate the parent of this process parent = _pcb_find( pcb->ppid ); if( parent == NULL ) { c_printf( "** zombify(): pid %d ppid %d\n", pcb->pid, pcb->ppid ); _kpanic( "_zombify", "no process parent", 0 ); } // // Found the parent. If it's waiting for this process, // wake it up, give it this process' status, and clean up. // if( parent->state == WAITING ) { // get the address of the info structure from the // parent, and pull out the desired PID info = (info_t *) ARG(parent->context,1); pid = info->pid; // if the parent was waiting for any of its children // or was waiting for us specifically, give it our // information and terminate this process. // // if the parent was waiting for another child, // turn this process into a zombie. if( pid == 0 || pid == _current->pid ) { // pull the parent off the waiting queue key.u = parent->pid; stat = _q_remove_by_key(&_waiting,(void **)&parent,key); if( stat != E_SUCCESS ) { _kpanic( "_zombify", "wait remove status %s", stat ); } // return our PID and our termination status // to the parent info->pid = _current->pid; info->status = ARG(_current->context,1); // clean up this process stat = _stack_free( pcb->stack ); if( stat != E_SUCCESS ) { _kpanic( "_zombify", "stack free status %s", stat ); } stat = _pcb_free( pcb ); if( stat != E_SUCCESS ) { _kpanic( "_zombify", "pcb free status %s", stat ); } // schedule the parent; give it a quick dispatch _schedule( parent, PRIO_MAXIMUM ); return; } } // // Our parent either wasn't waiting, or was waiting for someone // else. Put this process on the zombie queue until our parent // wants us. // key.u = _current->pid; _current->state = ZOMBIE; stat = _q_insert( &_zombie, (void *)_current, key ); if( stat != E_SUCCESS ) { _kpanic( "_zombify", "zombie insert status %s", stat ); } }