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; }
/////////////////// 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; }