/* ------ WRITER ------ */ void writer_lock(rw_lock* rw) { int success = 0; // local var int mytid = nf_tid(); while(!success) { while((rw->writer_pending && (mytid != rw->writer_id)) || (rw->reader_cnt || rw->writing)){ nf_lock(LOCK_FOR_HW_TM); //Rizwan nf_unlock(LOCK_FOR_HW_TM); //Rizwan } nf_lock(rw->lock); if(!(rw->writer_pending)) { rw->writer_pending = 1; rw->writer_id = mytid; } if(!(rw->reader_cnt || rw->writing)) { rw->writing = 1; success = 1; nf_lock(LOCK_FOR_HW_TM); //Rizwan } nf_unlock(rw->lock); } }
void writer_unlock(rw_lock* rw) { nf_unlock(LOCK_FOR_HW_TM); //Rizwan nf_lock(rw->lock); rw->writer_pending = 0; rw->writer_id = -1; rw->writing = 0; nf_unlock(rw->lock); }
// all threads start here, NetThreads 1.0 has 8 threads (4 per CPU) // instructions from the 4 thread on a CPU are interleaved in a // round-robin fashion. use compiler/bin/mips-mips-elf-objdump -h to // see the memory layout of your compiled application and support.h to // see where some controls are memory-mapped. int main(void) { int mytid = nf_tid(); if(mytid != 0) { nf_stall_a_bit(); nf_lock(LOCK_INIT); // should not get it } else { #ifndef DEBUG nf_lock(LOCK_INIT); // should get it on the first attempt nf_pktout_init(); nf_pktin_init(); #endif sp_init_mem_single(); // initialize the multithreaded memory allocator // perform memory allocation for initialization purposes // only use sp_free() and sp_malloc() // two implementations of these functions exists. If you prefer the STANDARD_MALLOC // from ../common/memory.c, you should not perform sp_init_mem_single() nor sp_init_mem_pool(). // finalize the initialization of the multithreaded memory allocator // since each thread allocates from its private head and adds to its heap // upon memory free, the heaps can get unbalanced if care is not taken sp_init_mem_pool(); } nf_unlock(LOCK_INIT); while(1) { // get the time if you need it uint t = nf_time(); // 32-bit unsigned wrap-around time nf_lock(LOCK_DS0); // valid lock identifiers are integers from 0 to 15 inclusively // do some synchronized action here nf_unlock(LOCK_DS0); t_addr* next_packet = nf_pktin_pop(); // get the next available packet, this is non-blocking call if (nf_pktin_is_valid(next_packet)) { // test if we have a packet // process the packet nf_pktin_free(next_packet); // free this packet from the input memory } } // rever reached return 0; }
/* ------ WRITER ------ */ void writer_lock(rw_lock* rw) { int success = 0; // local var int mytid = nf_tid(); while(!success) { while(rw->writer_pending && (mytid != rw->writer_id)) relax(); while(rw->reader_cnt || rw->writing) relax(); nf_lock(rw->lock); if(!(rw->writer_pending)) { rw->writer_pending = 1; rw->writer_id = mytid; } if(!(rw->reader_cnt || rw->writing)) { rw->writing = 1; success = 1; } nf_unlock(rw->lock); } }
void dispatch_put_lock(int lock_id) { if(lock_id == -1) return; else nf_unlock(lock_id); }
void writer_unlock(rw_lock* rw) { nf_lock(rw->lock); rw->writer_pending = 0; rw->writer_id = -1; rw->writing = 0; nf_unlock(rw->lock); }
void *sp_malloc(size_t size) { void* ret; nf_lock(MALLOCFREE_LOCK); sp_allocated += size; if(sp_allocated >= HEAP_AVAILABLE) { log("ALLOCATION FAILED, MEMORY FILLED\n"); sp_allocated -= size; nf_unlock(MALLOCFREE_LOCK); return NULL; } ret = malloc(size); log("total allocated size is %d, last increment %d addr %#x\n", sp_allocated, size, (int)ret); //log("%#x\n", (int)ret); nf_unlock(MALLOCFREE_LOCK); return ret; }
void reader_lock(rw_lock* rw) { int success = 0; // local var while(!success) { while(rw->writing || rw->writer_pending){ nf_lock(LOCK_FOR_HW_TM); //Rizwan nf_unlock(LOCK_FOR_HW_TM); //Rizwan } //relax(); nf_lock(rw->lock); if(!(rw->writing || rw->writer_pending)) { rw->reader_cnt++; success = 1; } nf_unlock(rw->lock); } }
void* sp_realloc(void *ptr, int new_size) { void* ret; nf_lock(MALLOCFREE_LOCK); struct mem_struct* p; p = (struct mem_struct*)((char*)(ptr)-8); int size = p->size & ~PREV_INUSE; size -= 4; sp_allocated = sp_allocated - size + new_size; if(sp_allocated >= HEAP_AVAILABLE) { log("ALLOCATION FAILED, MEMORY FILLED\n"); sp_allocated -= size; nf_unlock(MALLOCFREE_LOCK); return NULL; } ret = realloc(ptr,new_size); nf_unlock(MALLOCFREE_LOCK); return ret; }
void sp_free(void *ptr) { nf_lock(MALLOCFREE_LOCK); struct mem_struct* p; p = (struct mem_struct*)((char*)(ptr)-8); int size = p->size & ~PREV_INUSE; size -= 4; sp_allocated -= size; log("total allocated size is %d, last decrement %d addr %#x\n", sp_allocated, size, (int)ptr); free(ptr); nf_unlock(MALLOCFREE_LOCK); }
struct ioq_header* get_dispatch_pkt(int myid) { int qid = get_dispatch_id(myid); struct ioq_header* ret = NULL; // first, check in private waiting list nf_lock(DISPAT_LOCK); if(num_dispatched[qid] > 0) { ret = dispatched_msg[qid][num_dispatched[qid]-1]; num_dispatched[qid] -= 1; log("DISPATCH got packet from queue %d\n", qid); } nf_unlock(DISPAT_LOCK); return ret; }
void reader_lock(rw_lock* rw) { int success = 0; // local var while(!success) { while(rw->writing || rw->writer_pending) relax(); nf_lock(rw->lock); if(!(rw->writing || rw->writer_pending)) { rw->reader_cnt++; success = 1; } nf_unlock(rw->lock); } }
int main(void) { if (nf_tid() != 0) { while (1) {} } nf_lock(LOCK_INIT); nf_pktout_init(); nf_pktin_init(); nf_unlock(LOCK_INIT); t_addr *pkt = nf_pktout_alloc(SIZE); fill_ioq((struct ioq_header *)pkt, 0, SIZE-sizeof(struct ioq_header)); nf_pktout_send(pkt, pkt + SIZE); nf_pktout_send(pkt, pkt + SIZE); nf_pktout_send(pkt, pkt + SIZE); nf_pktout_send(pkt, pkt + SIZE); while (1) {} return 0; }
int main(void) { t_addr* next_packet; int i = 0; int mytid = nf_tid(); if(mytid != 0) { nf_stall_a_bit(); nf_lock(LOCK_INIT); // should not get it } else { nf_lock(LOCK_INIT); // should get it immediately nf_pktout_init(); nf_pktin_init(); } nf_unlock(LOCK_INIT); while(1) { next_packet = nf_pktin_pop(); if (nf_pktin_is_valid(next_packet)) { i++; iddle_time(NUMBER_OF_LOOPS); log("thread %d sending packet %d from %p\n", nf_tid(), i, next_packet); process_pkt(next_packet); } } while(1); return 0; }
struct ioq_header* do_dispatch_core(int flowid, int myid, struct ioq_header* ioq) { int dest = (flowid % DISPATCH_NUM); if((dest < 0) || (dest > DISPATCH_NUM)) { log("DISPATCH error in dest, val %d\n", dest); while(1); } if(dest != myid) { int success = 0; while(!success) { nf_lock(DISPAT_LOCK); if(num_dispatched[dest] < DISPATCH_Q) { dispatched_msg[dest][num_dispatched[dest]] = ioq; num_dispatched[dest]++; success = 1; log("DISPATCH added packet to queue %d\n", dest); } nf_unlock(DISPAT_LOCK); if(!success) { relax(); log("DISPATCH waited before retrying to add packet to queue %d\n", dest); } } return NULL; } else return ioq; }
int main() { int mytid = nf_tid(); if(mytid != 0) { nf_stall_a_bit(); nf_lock(LOCK_INIT); // should not get it } else { nf_lock(LOCK_INIT); // should get it on the first attempt nf_pktout_init(); nf_pktin_init(); } nf_unlock(LOCK_INIT); //only run this program on thread 0 //if (nf_tid() != 0) //{ // while (1) {} //} //// initialize //nf_pktout_init(); //nf_pktin_init(); // allocate an output buffer t_addr *pkt = nf_pktout_alloc(PKT_SIZE); // setup the ioq_header fill_ioq((struct ioq_header*)pkt, 2, sizeof(struct netfpga_to_driver)); // get a pointer to the payload struct struct netfpga_to_driver* n2d = (struct netfpga_to_driver*) (pkt + sizeof(struct ioq_header)); // initialize the message memset(n2d->str, 0, STR_SIZE); memcpy(n2d->str, mystr, strlen(mystr)); //n2d->str[strlen(mystr)+1] = nf_tid() + 0x30; //thread id in ascii n2d->str[strlen(mystr)+1] = mytid + 0x30; //thread id in ascii // send it nf_pktout_send(pkt, pkt + PKT_SIZE); //int i = 0; //int mytid; //struct netfpga_to_driver* n2d; //t_addr *pkt; //while(i <= 1) //{ // mytid = nf_tid(); // // if(mytid != 0) // { // nf_stall_a_bit(); // nf_lock(LOCK_INIT); // should not get it // } // else // { // nf_lock(LOCK_INIT); // should get it on the first attempt // nf_pktout_init(); // nf_pktin_init(); // } // nf_unlock(LOCK_INIT); // // allocate an output buffer // pkt = nf_pktout_alloc(PKT_SIZE); // // setup the ioq_header // fill_ioq((struct ioq_header*)pkt, 2, sizeof(struct netfpga_to_driver)); // // get a pointer to the payload struct // n2d = // (struct netfpga_to_driver*) (pkt + sizeof(struct ioq_header)); // // initialize the message // memset(n2d->str, 0, STR_SIZE); // memcpy(n2d->str, mystr, strlen(mystr)); // //n2d->str[strlen(mystr)+1] = nf_tid() + 0x30; //thread id in ascii // n2d->str[strlen(mystr)+1] = mytid + 0x30; //thread id in ascii // // send it // nf_pktout_send(pkt, pkt + PKT_SIZE); // i = i + 1; //} //#else // int mytid = nf_tid(); // // if(mytid != 0) // { // nf_stall_a_bit(); // nf_lock(LOCK_INIT); // should not get it // } // else // { // nf_lock(LOCK_INIT); // should get it on the first attempt // nf_pktout_init(); // nf_pktin_init(); // } // nf_unlock(LOCK_INIT); // t_addr *pkt = nf_pktout_alloc(PKT_SIZE); // // // setup the ioq_header // fill_ioq((struct ioq_header*)pkt, 2, sizeof(struct netfpga_to_driver)); // // // get a pointer to the payload struct // struct netfpga_to_driver* n2d = // (struct netfpga_to_driver*) (pkt + sizeof(struct ioq_header)); // // // initialize the message // memset(n2d->str, 0, STR_SIZE); // memcpy(n2d->str, mystr, strlen(mystr)); // //n2d->str[strlen(mystr)+1] = nf_tid() + 0x30; //thread id in ascii // n2d->str[strlen(mystr)+1] = mytid + 0x30; //thread id in ascii // nf_pktout_send(pkt, pkt + PKT_SIZE); //#endif return 0; }
void reader_unlock(rw_lock* rw) { nf_lock(rw->lock); rw->reader_cnt--; nf_unlock(rw->lock); }