Exemplo n.º 1
0
static int shared_page_setup(int thd_id) 
{
	// thd_id is the upcall thread on the server side.

	struct srv_thd_info *thd;
	int cspd, sspd;
	vaddr_t ring_mgr, ring_cli, ring_srv;

	assert(thd_id);

	thd = &srv_thd_info[thd_id];
	cspd = thd->cli_spd_id;
	sspd = thd->srv_spd_id;
	
	if (!cspd || !sspd) goto err;

	ring_mgr = (vaddr_t)alloc_page();
	if (!ring_mgr) {
		printc("par_mgr: alloc ring buffer failed in mgr %ld.\n", cos_spd_id());
		goto err;
	}

	srv_thd_info[thd_id].mgr_ring = ring_mgr;

	ring_cli = (vaddr_t)valloc_alloc(cos_spd_id(), cspd, 1);
	if (unlikely(!ring_cli)) {
		printc("par_mgr: vaddr alloc failed in client comp %d.\n", cspd);
		goto err_cli;
	}
	if (unlikely(ring_cli != mman_alias_page(cos_spd_id(), ring_mgr, cspd, ring_cli, MAPPING_RW))) {
		printc("par_mgr: alias to client %d failed.\n", cspd);
		goto err_cli_alias;
	}
	comp_info[cspd].cli_thd_info[cos_get_thd_id()]->cap_info[thd->cli_cap_id].cap_ring = ring_cli;
	
	ring_srv = (vaddr_t)valloc_alloc(cos_spd_id(), sspd, 1);
	if (unlikely(!ring_srv)) {
		goto err_srv;
		printc("par_mgr: vaddr alloc failed in server comp  %d.\n", sspd);
	}
	if (unlikely(ring_srv != mman_alias_page(cos_spd_id(), ring_mgr, sspd, ring_srv, MAPPING_RW))) {
		printc("par_mgr: alias to server %d failed.\n", sspd);
		goto err_srv_alias;
	}
	srv_thd_info[thd_id].srv_ring = ring_srv;

	/* Initialize the ring buffer. Passing NULL because we use
	 * continuous ring (struct + data region). The ring starts
	 * from the second cache line of the page. (First cache line
	 * is used for the server thread active flag) */
	CK_RING_INIT(inv_ring, (CK_RING_INSTANCE(inv_ring) *)((void *)ring_mgr + CACHE_LINE), NULL, 
		     leqpow2((PAGE_SIZE - CACHE_LINE - sizeof(CK_RING_INSTANCE(inv_ring))) / 2 / sizeof(struct inv_data)));
	
	return 0;

err_srv_alias:
	valloc_free(cos_spd_id(), sspd, (void *)ring_srv, 1);
err_srv:
	mman_revoke_page(cos_spd_id(), ring_mgr, 0); 
err_cli_alias:
	valloc_free(cos_spd_id(), cspd, (void *)ring_cli, 1);
err_cli:
	free_page((void *)ring_mgr);
err:	
	return -1;
}
Exemplo n.º 2
0
/////////////////// move to lib later
int cos_ainv_handling(void) {
    struct __cos_ainv_srv_thd curr_data = { .stop = 0 };
    struct __cos_ainv_srv_thd *curr = &curr_data;
    int acap, i;
    int curr_thd_id = cos_get_thd_id();

    assert(curr);

    printc("upcall thread %d (core %ld) waiting in pong...\n", cos_get_thd_id(), cos_cpuid());
    sched_block(cos_spd_id(), 0);
    printc("upcall thread %d (core %ld) up!\n", cos_get_thd_id(), cos_cpuid());

    curr->acap = acap_srv_lookup(cos_spd_id());
    curr->cli_ncaps = acap_srv_ncaps(cos_spd_id());
    curr->shared_page = acap_srv_lookup_ring(cos_spd_id());
    assert(curr->acap && curr->cli_ncaps && curr->shared_page);

    init_shared_page(&curr->shared_struct, curr->shared_page);

    curr->fn_mapping = malloc(sizeof(vaddr_t) * curr->cli_ncaps);
    if (unlikely(curr->fn_mapping == NULL)) goto err_nomem;
    for (i = 0; i < curr->cli_ncaps; i++) {
        curr->fn_mapping[i] = (vaddr_t)acap_srv_fn_mapping(cos_spd_id(), i);
    }

    assert(curr);
    acap = curr->acap;

    printc("server %ld, upcall thd %d has acap %d.\n",
           cos_spd_id(), curr_thd_id, acap);

    struct shared_struct *shared_struct = &curr->shared_struct;
    CK_RING_INSTANCE(inv_ring) *ring = shared_struct->ring;
    assert(ring);

    struct inv_data inv;
    while (curr->stop == 0) {
        CLEAR_SERVER_ACTIVE(shared_struct); // clear active early to avoid race (and atomic instruction)
        if (CK_RING_DEQUEUE_SPSC(inv_ring, ring, &inv) == false) {
            printc("thread %d waiting on acap %d\n", cos_get_thd_id(), acap);
            cos_areceive(acap);
            printc("thread %d up from areceive\n", cos_get_thd_id());
        } else {
            SET_SERVER_ACTIVE(shared_struct); /* setting us active */
            printc("core %ld: got inv for cap %d, param %d, %d, %d, %d\n",
                   cos_cpuid(), inv.cap, inv.params[0], inv.params[1], inv.params[2], inv.params[3]);
            if (unlikely(inv.cap > curr->cli_ncaps || !curr->fn_mapping[inv.cap])) {
                printc("Server thread %d in comp %ld: receiving invalid cap %d\n",
                       cos_get_thd_id(), cos_spd_id(), inv.cap);
            } else {
                assert(curr->fn_mapping[inv.cap]);
                //execute!
                exec_fn((void *)curr->fn_mapping[inv.cap], 4, inv.params);
                // and write to the return value.
            }
        }
    }

    return 0;
err_nomem:
    printc("couldn't allocate memory in spd %ld\n", cos_spd_id());
    return -1;
}

void cos_upcall_fn(upcall_type_t t, void *arg1, void *arg2, void *arg3)
{
    switch (t) {
    case COS_UPCALL_THD_CREATE:
    {
        cos_ainv_handling();
        break;
    }
    default:
        /* fault! */
        //*(int*)NULL = 0;
        printc("\n upcall type t %d\n", t);
        return;
    }
    return;
}