示例#1
0
std::queue<node*> Map::add_all_possible_paths(node *N, Map &copy){
    std::queue<node*> neighbohrs;
    std::vector<pos_t> J = N->diamonds;
    node *par = N;
    pos_t new_man = N->man;
    //Don't get children if there is a deadlock
    bool dead_end = false;
    for(size_t n=0; n < J.size(); ++n){
        if(dead_lock(J.at(n))){
            dead_end = true;
            for(auto g : goals){
                if(g == J.at(n)){
                    dead_end = false;
                    //if a diamond is locked in a goal then it is not a deadlock.
                }
            }
            if(dead_end){
                return neighbohrs; //deadlock, no need to see what children might come of this.
            }
        }
    }
    wave(copy,new_man,J);
    Map wave_map; /******** If we want to optimize for robot moves ********/
    std::vector<std::vector<float>> cost_map;
    if(optimize_for_robot_moves){
        cost_map = find_robot_moves(wave_map, N);
    }
    char ans;
    for(size_t n=0; n < J.size(); ++n){
        ans = copy.valid_push(J.at(n)); //gets all the directions a diamond can be pushed
        if(ans){
            new_man = J.at(n); //New position where the man is where the diamond was
            if(ans & east){
                J.at(n) = N->diamonds.at(n) + right; //move diamond
                node *next = new node(new_man,J,par);      //create node
                if(optimize_for_robot_moves){
                    next->path_length = N->path_length + wave_map.get(new_man) -3;//based on robot moves in seconds
                } else {
                    next->path_length = N->path_length + copy.get(new_man-right) - 2; //wavefront approach
                }
                J.at(n) = N->diamonds.at(n);         //reset diamond
                neighbohrs.push(next);
            }
            if(ans & west){
                J.at(n) = N->diamonds.at(n) + left;
                node *next = new node(new_man,J,par);
                if(optimize_for_robot_moves){
                    next->path_length = N->path_length + wave_map.get(new_man) -3;
                } else {
                    next->path_length = N->path_length + copy.get(new_man-left) - 2; //wavefront approach
                }
                J.at(n) = N->diamonds.at(n);
                neighbohrs.push(next);
            }
            if(ans & north){
                J.at(n) = N->diamonds.at(n) + above;
                node *next = new node(new_man,J,par);
                if(optimize_for_robot_moves){
                    next->path_length = N->path_length + wave_map.get(new_man) -3;
                } else {
                    next->path_length = N->path_length + copy.get(new_man-above) - 2; //wavefront approach
                }
                J.at(n) = N->diamonds.at(n);
                neighbohrs.push(next);
            }
            if(ans & south){
                J.at(n) = N->diamonds.at(n) + below;
                node *next = new node(new_man,J,par);
                if(optimize_for_robot_moves){
                    next->path_length = N->path_length + wave_map.get(new_man) -3;
                } else {
                    next->path_length = N->path_length + copy.get(new_man-below) - 2; //wavefront approach
                }
                J.at(n) = N->diamonds.at(n);
                neighbohrs.push(next);
            }
        }
    }
    return neighbohrs;
}
示例#2
0
/*
 * osprd_ioctl(inode, filp, cmd, arg)
 *   Called to perform an ioctl on the named file.
 */
int osprd_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
	osprd_info_t *d = file2osprd(filp);	// device info
	int r = 0;			// return value: initially 0

	// is file open for writing?
	int filp_writable = (filp->f_mode & FMODE_WRITE) != 0;

	// This line avoids compiler warnings; you may remove it.
	(void) filp_writable, (void) d;

	// Set 'r' to the ioctl's return value: 0 on success, negative on error
    unsigned local_ticket;

	if (cmd == OSPRDIOCACQUIRE) {

		// EXERCISE: Lock the ramdisk.
		//
		// If *filp is open for writing (filp_writable), then attempt
		// to write-lock the ramdisk; otherwise attempt to read-lock
		// the ramdisk.
		//
                // This lock request must block using 'd->blockq' until:
		// 1) no other process holds a write lock;
		// 2) either the request is for a read lock, or no other process
		//    holds a read lock; and
		// 3) lock requests should be serviced in order, so no process
		//    that blocked earlier is still blocked waiting for the
		//    lock.
		//
		// If a process acquires a lock, mark this fact by setting
		// 'filp->f_flags |= F_OSPRD_LOCKED'.  You also need to
		// keep track of how many read and write locks are held:
		// change the 'osprd_info_t' structure to do this.
		//
		// Also wake up processes waiting on 'd->blockq' as needed.
		//
		// If the lock request would cause a deadlock, return -EDEADLK.
		// If the lock request blocks and is awoken by a signal, then
		// return -ERESTARTSYS.
		// Otherwise, if we can grant the lock request, return 0.

		// 'd->ticket_head' and 'd->ticket_tail' should help you
		// service lock requests in order.  These implement a ticket
		// order: 'ticket_tail' is the next ticket, and 'ticket_head'
		// is the ticket currently being served.  You should set a local
		// variable to 'd->ticket_head' and increment 'd->ticket_head'.
		// Then, block at least until 'd->ticket_tail == local_ticket'.
		// (Some of these operations are in a critical section and must
		// be protected by a spinlock; which ones?)

		// Your code here (instead of the next two lines).
		osp_spin_lock(&(d->mutex));
        // lock while updating device
        local_ticket = d->ticket_head;
        d->ticket_head = d->ticket_head + 1;
        osp_spin_unlock(&(d->mutex));
        
        for_each_open_file(current, dead_lock(filp, d), d);
        
        // lock requests block and is awoken by signal
        if (wait_event_interruptible( (d->blockq, d->writeLocks == 0) && (local_ticket == d->ticketTail) && (!filp_writable || d->readLocks == 0) ) ) {
            // sleep until any of the conditions are true
            if (local_ticket != d->ticket_tail) d->numInterrupt++;
            else d->ticket_tail++;
            return -ERESTARTSYS;
        }
        
        // deadlock exists
        bool deadlock_exists = d->deadlock > 1;
        bool locked = filp->f_flags & F_OSPRD_LOCKED;
        if (deadlock_exists && locked) return -EDEADLK;
        
        // lock device
        osp_spin_lock(&(d->mutex));
        d->deadlock = 0;
        filp->f_flags = filp->f_flags | F_OSPRD_LOCKED;
        if (d->mutex.lock >= 1) r = 0;
        
        if (!filp_writable) d->readLocks++;
        else {
            d->ticket_tail++;
            d->writeLocks++;
        }
        
        osp_spin_unlock(&(d->mutex));
        // finish using device
        
        r = 0;
        
        // if (!filp_writable) d->ticket_tail++;

	} else if (cmd == OSPRDIOCTRYACQUIRE) {

		// EXERCISE: ATTEMPT to lock the ramdisk.
		//
		// This is just like OSPRDIOCACQUIRE, except it should never
		// block.  If OSPRDIOCACQUIRE would block or return deadlock,
		// OSPRDIOCTRYACQUIRE should return -EBUSY.
		// Otherwise, if we can grant the lock request, return 0.

		// Your code here (instead of the next two lines).
        local_ticket = d->ticket_head;
		bool lockCheck1 = local_ticket != d->ticket_tail;
        bool lockCheck2 = (filp_writable && d->readLocks != 0);
        bool lockCheck3 = d->writeLocks != 0;
        if (filp->f_flags & F_OSPRD_LOCKED || lockCheck1 || lockCheck2 || lockCheck3) r = -EBUSY;
        // device is busy, is not open for writing
        else {
            osp_spin_lock(&(d->mutex));
            // lock device to try reading device
            filp->f_flags = filp->f_flags | F_OSPRD_LOCKED;
            d->ticket_head++;
            if (!filp_writable) d->readLocks++;
            // if not readable, then try to write to device
            else d->writeLocks++;
            if (d->ticket_head > d->ticket_tail) d->ticket_tail++;
            // get next ticket
            osp_spin_unlock(&(d->mutex));
            wake_up_all(&d->blockq);
            // wake up all blocked tasks
            r = 0;
        }

	} else if (cmd == OSPRDIOCRELEASE) {

		// EXERCISE: Unlock the ramdisk.
		//
		// If the file hasn't locked the ramdisk, return -EINVAL.
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.

		// Your code here (instead of the next line).
        
		if (!(filp->f_flags & F_OSPRD_LOCKED)) r = -EINVAL;
        // file hasn't locked ramdisk
        else {
            osp_spin_lock(&(d->mutex));
            d->readLocks = 0;
            d->writeLocks = 0;
            r = 0;
            filp->f_flags = filp->f_flags & ~F_OSPRD_LOCKED;
            osp_spin_unlock(&(d->mutex));
            wake_up_all(&d->blockq);
            // wake up all blocked tasks
        }

	} else
		r = -ENOTTY; /* unknown command */
	return r;
}