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); } }
int _ioreq_enqueue(Drive *d, Fd *fd, Uint8 rd, Iostate state){ Status status; Key key; Iorequest *req; if( (status = _q_remove( free_req_q, (void **) &req ))!= SUCCESS ) { _kpanic( "_ioreq_enqueue", "No free requests. Status: %s", status ); } key.v =(void *) d; req->d=d; req->fd=fd; req->read=rd; req->st=state; if (state == WAIT_ON_IDLE){ status = _q_insert( idle_q,(void *) req, key); }else if (state == WAIT_ON_DATA){ status = _q_insert( data_q,(void *) req, key); }else{ //drop invalid request status=FAILURE; } if( status != SUCCESS ) { _kpanic( "_ioreq_enqueue", "IO queue insertion status %s", status ); } return 1; }
void _ioreq_dealloc(Iorequest *req){ Key key; Status status; key.v = req->d; status = _q_insert(free_req_q, (void *) req,key); if( status != SUCCESS ) { _kpanic( "_ioreq_init", "IO free queue insertion status %s", status ); } }
Status _sched( Pcb *pcb ) { Prio p; Key key; if( pcb == NULL ) { return( BAD_PARAM ); } // Insert into one of the N ready queues // according to the priority of the process p = pcb->priority; if( p >= N_READYQ ) { return( BAD_PRIO ); } key.u = pcb->pid; pcb->state = READY; return( _q_insert( _ready[p], (void *) pcb, key ) ); }
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 ); } }
void _zombify( pcb_t *pcb ) { estatus_t *esptr; pid_t *pidptr; pid_t ppid; pcb_t *parent, *p2; int i; key_t key; status_t stat; // mark the process as no longer runnable pcb->state = ZOMBIE; // find the parent ppid = pcb->ppid; for( i = 0; i < N_PCBS; ++i ) { if( _pcbs[i].pid == ppid && _pcbs[i].state != FREE ) { parent = &_pcbs[i]; break; } } /* ** If we didn't find a parent, or if the parent was ** already unrunnable (zombied, killed), reparent this ** process to the init process */ if( i >= N_PCBS || _pcbs[i].state >= FIRST_DEAD_STATE ) { ppid = pcb->ppid = PID_INIT; parent = _init_pcb; } /* ** At this point, parent points to the parent's PCB, and ppid ** contains the parent's PID. ** ** If the parent is on the wait() queue, we'll awaken it and give ** it this child's information. ** ** Otherwise, we need to put this child on the zombie queue. */ if( parent->state == WAITING ) { // look for the parent on the wait queue key.u = ppid; stat = _q_remove_specific( &_waiting, (void **) &p2, key ); if( stat != SUCCESS ) { _kpanic( "_zombify", "parent wait remove status %s", stat ); } // verify that we found the same process if( p2 != parent ) { _pcb_dump( "*** p2: ", p2 ); _pcb_dump( "*** parent: ", parent ); _kpanic( "_zombify", "parent wait deque wrong", FAILURE ); } // OK, we have the right one. // Start by decrementing its "remaining children" // counter if it isn't the init process if( ppid != PID_INIT ) { parent->children -= 1; } // return the child's information to it. RET(parent) = U_SUCCESS; pidptr = (pid_t *) ARG(parent)[1]; *pidptr = pcb->pid; esptr = (estatus_t *) ARG(parent)[2]; *esptr = ARG(pcb)[1]; // schedule the parent (who returns from wait()) _schedule( parent ); // clean up the child process _pcb_cleanup( pcb ); } else { // place this child on the zombie queue, ordered by PID key.u = pcb->pid; pcb->status = ARG(pcb)[1]; stat = _q_insert( &_zombie, (void *)pcb, key ); if( stat != SUCCESS ) { _kpanic( "_zombify", "zombie insert status %s", stat ); } } }