Ejemplo n.º 1
0
thread_safe_page *original_io_request::complete_req(thread_safe_page *p,
		bool lock)
{
	if (get_req_type() == io_request::BASIC_REQ) {
		int page_off;
		thread_safe_page *ret = NULL;
		char *req_buf;
		int req_size;

		if (within_1page()) {
			page_off = get_offset() - ROUND_PAGE(get_offset());
			req_buf = get_buf();
			req_size = get_size();
		}
		else {
			io_request extracted;
			extract(p->get_offset(), PAGE_SIZE, extracted);
			page_off = extracted.get_offset() - ROUND_PAGE(extracted.get_offset());
			req_buf = extracted.get_buf();
			req_size = extracted.get_size();
		}

		if (lock)
			p->lock();
		if (get_access_method() == WRITE) {
			memcpy((char *) p->get_data() + page_off, req_buf, req_size);
			if (!p->set_dirty(true))
				ret = p;
		}
		else 
			/* I assume the data I read never crosses the page boundary */
			memcpy(req_buf, (char *) p->get_data() + page_off, req_size);
		if (lock)
			p->unlock();
		return ret;
	}
	else {
		p->inc_ref();
		get_page_status(p).pg = p;
		return NULL;
	}
}
Ejemplo n.º 2
0
static int
give_write_copy (int requester_id, int request_id, int page_number) {
    int result;
    printf("%d: pre-lock\n", thisid);
    pthread_mutex_lock(&locks[page_number]);
    printf("%d: post-lock\n", thisid);
    int owner_id = get_owner(page_number);
    if (owner_id != thisid) {
        printf("%d: wtf\n", thisid);
        pthread_mutex_unlock(&locks[page_number]);
        return -E_INCORRECT_OWNER;
    }
    struct PageStatus *page_status = get_page_status(page_number);
    printf("%d: page_status->status: %d\n", thisid, page_status->status);
    switch (page_status->status) {
        case READABLE: {
            int i;
            int had_read_only;
            for (i = 0; i < nowners; i++) {
                if (i == requester_id) {
                    had_read_only = (page_status->status_by_owner[i] == READING);
                    continue;
                }
                if (i == thisid) {
                    if (page_status->status_by_owner[i] == READING) {
                        // Set local page to PROT_NONE at end of function
                        continue;
                    } else {
                        // This shouldn't happen - the local copy should become
                        //   readable as soon the page status becomes READABLE
                        result = -E_INCONSISTENT_STATE;
                        break;
                    }
                }
                if (page_status->status_by_owner[i] == READING) {
                    // Tell i that it is INVALIDATED
                    printf("%d: Telling %d that it is INVALIDATED\n", thisid, i);
                    struct Message m = create_message(SET_PERMISSION,
                            INVALIDATED, page_number);
                    printf("%d: sending message of type %c\n", thisid, m.msg_type);
                    result = send_to(i, &m);
                    if (result < 0) break;
                    page_status->status_by_owner[i] = INVALIDATED;
                }
            }
            page_status->status_by_owner[requester_id] = MODIFYING;
            page_status->modifying_owner = requester_id;
            page_status->status = MODIFIED;
            if (requester_id == thisid) {
                // Set local page to PROT_READ_WRITE
                printf("%d: Setting local page %d to PROT_READ_WRITE\n", thisid,
                        page_number);
                result = set_permissions((void *) get_pageaddr(page_number),
                        PGSIZE, PROT_READ_WRITE);
                if (result < 0) break;
            } else {
                if (had_read_only) {
                    // Tell requester_id that it has PROT_READ_WRITE access
                    struct Message m = create_message(SET_PERMISSION,
                            MODIFYING, page_number);
                    m.is_response = 1;
                    if (request_id == NO_RESPONSE) {
                        result = E_INCONSISTENT_STATE;
                        break;
                    }
                    m.index = request_id;
                    result = send_to(requester_id, &m);
                    if (result < 0) break;
                } else {
                    // Transfer page over network to requester_id and tell it
                    //   it has PROT_READ_WRITE access
                    struct Message m = create_message(SEND_PAGE, MODIFYING,
                            page_number);
                    memcpy((void *) m.page, (void *) get_pageaddr(page_number),
                            PGSIZE);
                    m.is_response = 1;
                    if (request_id == NO_RESPONSE) {
                        result = E_INCONSISTENT_STATE;
                        break;
                    }
                    m.index = request_id;
                    result = send_to(requester_id, &m);
                    if (result < 0) break;
                }
            }
            // Set local page to PROT_NONE
            result = set_permissions((void *) get_pageaddr(page_number),
                    PGSIZE, PROT_NONE);
            if (result < 0) break;
            page_status->status_by_owner[thisid] = INVALIDATED;
            result = 0;
            break;
        }
        case MODIFIED: {
            int modifier = page_status->modifying_owner;
            if (modifier == requester_id) {
                // The modifier should have read-write permissions, in which
                //   case a page not fault should not be thrown and this
                //   should never be called.
                result = -E_INCONSISTENT_STATE;
                break;
            }
            if (modifier == thisid) {
                // Set local page to PROT_NONE at end of method
            } else {
                // Tell modifier that it is INVALIDATED
                // Get modified page from modifier
                struct Message m = create_message(REQUEST_PAGE, INVALIDATED,
                        page_number);
                // Upon receiving the message we should map the page locally
                result = send_and_wait_for_response(modifier, &m);
                if (result < 0) break;
                // Local page should already be set PROT_READ
            }
            page_status->status_by_owner[modifier] = INVALIDATED;
            page_status->status_by_owner[requester_id] = MODIFYING;
            page_status->modifying_owner = requester_id;
            if (requester_id == thisid) {
                // Set local page to PROT_READ_WRITE
                result = set_permissions((void *) get_pageaddr(page_number),
                        PGSIZE, PROT_READ_WRITE);
                if (result < 0) break;
            } else {
                // Transfer page over network to requester_id and tell it it has
                //   PROT_READ_WRITE access
                struct Message m = create_message(SEND_PAGE, MODIFYING,
                        page_number);
                memcpy((void *) m.page, (void *) get_pageaddr(page_number),
                        PGSIZE);
                m.is_response = 1;
                if (request_id == NO_RESPONSE) {
                    result = E_INCONSISTENT_STATE;
                    break;
                }
                m.index = request_id;
                result = send_to(requester_id, &m);
                if (result < 0) break;
                // Set local page to PROT_NONE
                result = set_permissions((void *) get_pageaddr(page_number),
                        PGSIZE, PROT_NONE);
                if (result < 0) break;
            }
            result = 0;
            break;
        }
        default: {
            printf("Unhandled page status in give_write_copy.\n");
            exit(-E_UNHANDLED_PAGE_STATUS);
        }
    }
    pthread_mutex_unlock(&locks[page_number]);
    return result;
}
Ejemplo n.º 3
0
static int
give_read_copy (int requester_id, int request_id, int page_number) {
    int result;
    pthread_mutex_lock(&locks[page_number]);
    int owner_id = get_owner(page_number);
    if (owner_id != thisid) {
        pthread_mutex_unlock(&locks[page_number]);
        return -E_INCORRECT_OWNER;
    }
    struct PageStatus *page_status = get_page_status(page_number);
    switch (page_status->status) {
        case READABLE: {
            if (requester_id == thisid) {
                // Status should not be readable without local copy having
                //   read permissions; with these permissions, a page fault
                //   should not be thrown and this should never be called
                result = -E_INCONSISTENT_STATE;
                break;
            }
            // Transfer page over network to owner_id and tell it it
            //   has PROT_READ access
            struct Message m = create_message(SEND_PAGE, READING, page_number);
            memcpy((void *) m.page, (void *) get_pageaddr(page_number), PGSIZE);
            m.is_response = 1;
            if (request_id == NO_RESPONSE) {
                result = E_INCONSISTENT_STATE;
                break;
            }
            m.index = request_id;
            if ((result = send_to(owner_id, &m)) < 0) break;
            page_status->status_by_owner[requester_id] = READABLE;
            result = 0;
            break;
        }
        case MODIFIED: {
            int modifier = page_status->modifying_owner;
            if (modifier == requester_id) {
                // The modifier should have read-write permissions, in which
                //   case a page not fault should not be thrown and this
                //   should never be called.
                result = -E_INCONSISTENT_STATE;
                break;
            }
            if (modifier != thisid) {
                // Request page from modifier and tell it to set its
                //   permissions to PROT_READ
                struct Message m =
                    create_message(REQUEST_PAGE, READING, page_number);
                // Upon receiving the message we should map the page locally
                if ((result = send_and_wait_for_response(modifier, &m)) < 0) {
                    break;
                }
                // Local page should already be set PROT_READ
                page_status->status_by_owner[thisid] = READING;
            }
            page_status->status_by_owner[modifier] = READING;
            page_status->modifying_owner = NO_OWNER;
            page_status->status = READABLE;
            if (requester_id != thisid) {
                // Transfer page over network to requester_id and tell it it
                //   has PROT_READ access
                struct Message m =
                        create_message(SEND_PAGE, READING, page_number);
                memcpy((void *) m.page, (void *) get_pageaddr(page_number),
                        PGSIZE);
                m.is_response = 1;
                if (request_id == NO_RESPONSE) {
                    result = E_INCONSISTENT_STATE;
                    break;
                }
                m.index = request_id;
                result = send_to(requester_id, &m);
                if (result < 0) break;
                page_status->status_by_owner[requester_id] = READING;
            }
            result = 0;
            break;
        }
        default:
            printf("Unhandled page status in give_read_copy.\n");
            exit(-E_UNHANDLED_PAGE_STATUS);
    }
    pthread_mutex_unlock(&locks[page_number]);
    return result;
}