static errno_t startSync( phantom_disk_partition_t *p, void *to, long blockNo, int nBlocks, int isWrite ) { assert( p->block_size < PAGE_SIZE ); SHOW_FLOW( 3, "blk %d", blockNo ); pager_io_request rq; pager_io_request_init( &rq ); rq.phys_page = (physaddr_t)phystokv(to); // why? redundant? rq.disk_page = blockNo; rq.blockNo = blockNo; rq.nSect = nBlocks; rq.rc = 0; if(isWrite) rq.flag_pageout = 1; else rq.flag_pagein = 1; STAT_INC_CNT(STAT_CNT_BLOCK_SYNC_IO); STAT_INC_CNT( STAT_CNT_DISK_Q_SIZE ); // Will decrement on io done void *va; hal_pv_alloc( &rq.phys_page, &va, nBlocks * p->block_size ); errno_t ret = EINVAL; if(isWrite) memcpy( va, to, nBlocks * p->block_size ); int ei = hal_save_cli(); hal_spin_lock(&(rq.lock)); rq.flag_sleep = 1; // Don't return until done rq.sleep_tid = GET_CURRENT_THREAD()->tid; SHOW_FLOW0( 3, "start io" ); if( (ret = p->asyncIo( p, &rq )) ) { rq.flag_sleep = 0; hal_spin_unlock(&(rq.lock)); if( ei ) hal_sti(); //return ret; goto ret; } thread_block( THREAD_SLEEP_IO, &(rq.lock) ); SHOW_FLOW0( 3, "unblock" ); if( ei ) hal_sti(); if(!isWrite) memcpy( to, va, nBlocks * p->block_size ); ret = rq.rc; //return partAsyncIo( p, &rq ); //return p->asyncIo( p, rq ); ret: hal_pv_free( rq.phys_page, va, nBlocks * p->block_size ); return ret; }
void deferred_refdec(pvm_object_storage_t *os) { assert(inited); #if 0 if( os->_ah.refCount > 1 ) { os->_ah.refCount--; if( os->_ah.refCount <= 0 ) { os->_ah.refCount++; goto long_way; } return; } #endif STAT_INC_CNT(DEFERRED_REFDEC_REQS); if( ( (refdec_put_ptr <= REFDEC_BUFFER_HALF) && (refdec_put_ptr > REFDEC_BUFFER_RED_ZONE ) ) || ( refdec_put_ptr > REFDEC_BUFFER_RED_ZONE+REFDEC_BUFFER_HALF ) ) { //hal_mutex_lock( &deferred_refdec_mutex ); hal_cond_signal( &start_refdec_cond ); //hal_cond_wait( &end_refdec_cond, &deferred_refdec_mutex ); //hal_mutex_unlock( &deferred_refdec_mutex ); } //long_way: // TODO ERROR atomic_add returns not what we assume! //int pos = atomic_add( (int *)&refdec_put_ptr, 1 ); int pos = ATOMIC_ADD_AND_FETCH( (int *)&refdec_put_ptr, 1 ); // Overflow if( (pos >= REFDEC_BUFFER_SIZE) || (pos == REFDEC_BUFFER_HALF) ) { STAT_INC_CNT(DEFERRED_REFDEC_LOST); // We just loose refdec - big GC will pick it up return; } refdec_buffer[pos] = os; }
//! Convert usual pager request to partition code style request and start it void disk_enqueue( phantom_disk_partition_t *p, pager_io_request *rq ) { int m = PAGE_SIZE/p->block_size; rq->blockNo = rq->disk_page*m; rq->nSect = m; assert( rq->flag_ioerror == 0 ); assert( rq->flag_pagein != rq->flag_pageout ); STAT_INC_CNT(STAT_CNT_BLOCK_IO); STAT_INC_CNT( STAT_CNT_DISK_Q_SIZE ); // Will decrement on io done p->asyncIo( p, rq ); }
static void deferred_refdec_thread(void *a) { t_current_set_name("RefDec"); t_current_set_priority( THREAD_PRIO_HIGH ); while(!stop) { hal_mutex_lock( &deferred_refdec_mutex ); // TODO timed wait hal_cond_wait( &start_refdec_cond, &deferred_refdec_mutex ); STAT_INC_CNT(DEFERRED_REFDEC_RUNS); // Decide where to switch put pointer int new_put_ptr = REFDEC_BUFFER_HALF + 1; // first one used to check low half overflow // Was in upper page? if( refdec_put_ptr >= REFDEC_BUFFER_HALF ) new_put_ptr = 0; //int last_pos = atomic_set( &refdec_put_ptr, new_put_ptr); int last_pos = ATOMIC_FETCH_AND_SET( &refdec_put_ptr, new_put_ptr); int start_pos = (last_pos >= REFDEC_BUFFER_HALF) ? REFDEC_BUFFER_HALF+1 : 0; // Check that all VM threads are either sleep or passed an bytecode instr boundary phantom_check_threads_pass_bytecode_instr_boundary(); int pos; for( pos = start_pos; pos < last_pos; pos++ ) { pvm_object_storage_t volatile *os; os = refdec_buffer[pos]; assert( os->_ah.refCount > 0); do_ref_dec_p((pvm_object_storage_t *)os); } hal_cond_broadcast( &end_refdec_cond ); hal_mutex_unlock( &deferred_refdec_mutex ); } }
ssize_t udp_sendto(void *prot_data, const void *inbuf, ssize_t len, i4sockaddr *toaddr) { udp_endpoint *e = prot_data; udp_header *header; int total_len; cbuf *buf; udp_pseudo_header pheader; ipv4_addr srcaddr; int err; // make sure the args make sense if(len < 0 || len + sizeof(udp_header) > 0xffff) return ERR_INVALID_ARGS; if(toaddr->port < 0 || toaddr->port > 0xffff) return ERR_INVALID_ARGS; // allocate a buffer to hold the data + header total_len = len + sizeof(udp_header); buf = cbuf_get_chain(total_len); if(!buf) return ERR_NO_MEMORY; // copy the data to this new buffer //err = cbuf_user_memcpy_to_chain(buf, sizeof(udp_header), inbuf, len); err = cbuf_memcpy_to_chain(buf, sizeof(udp_header), inbuf, len); if(err < 0) { cbuf_free_chain(buf); return ERR_VM_BAD_USER_MEMORY; } // set up the udp pseudo header if(ipv4_lookup_srcaddr_for_dest(NETADDR_TO_IPV4(toaddr->addr), &srcaddr) < 0) { cbuf_free_chain(buf); return ERR_NET_NO_ROUTE; } pheader.source_addr = htonl(srcaddr); pheader.dest_addr = htonl(NETADDR_TO_IPV4(toaddr->addr)); pheader.zero = 0; pheader.protocol = IP_PROT_UDP; pheader.udp_length = htons(total_len); // start setting up the header header = cbuf_get_ptr(buf, 0); header->source_port = htons(e->port); header->dest_port = htons(toaddr->port); header->length = htons(total_len); header->checksum = 0; header->checksum = cbuf_ones_cksum16_2(buf, 0, total_len, &pheader, sizeof(pheader)); if(header->checksum == 0) header->checksum = 0xffff; #if NET_CHATTY printf("UDP SEND port %d to %d, len %d (%d)\n", e->port, toaddr->port, total_len, len ); #endif // send it away err = ipv4_output(buf, NETADDR_TO_IPV4(toaddr->addr), IP_PROT_UDP); STAT_INC_CNT(STAT_CNT_UDP_TX); // if it returns ARP_QUEUED, then it's actually okay if(err == ERR_NET_ARP_QUEUED) { err = 0; } return err; }
int udp_input(cbuf *buf, ifnet *i, ipv4_addr source_address, ipv4_addr target_address) { (void) i; udp_header *header; udp_endpoint *e; udp_queue_elem *qe; uint16 port; int err; STAT_INC_CNT(STAT_CNT_UDP_RX); header = cbuf_get_ptr(buf, 0); #if NET_CHATTY dprintf("udp_input: src port %d, dest port %d, len %d, buf len %d, checksum 0x%x\n", ntohs(header->source_port), ntohs(header->dest_port), ntohs(header->length), (int)cbuf_get_len(buf), ntohs(header->checksum)); #endif if(ntohs(header->length) > (uint16)cbuf_get_len(buf)) { err = ERR_NET_BAD_PACKET; goto ditch_packet; } // deal with the checksum check if(header->checksum) { udp_pseudo_header pheader; uint16 checksum; // set up the pseudo header for checksum purposes pheader.source_addr = htonl(source_address); pheader.dest_addr = htonl(target_address); pheader.zero = 0; pheader.protocol = IP_PROT_UDP; pheader.udp_length = header->length; checksum = cbuf_ones_cksum16_2(buf, 0, ntohs(header->length), &pheader, sizeof(pheader)); if(checksum != 0) { #if NET_CHATTY dprintf("udp_receive: packet failed checksum\n"); #endif err = ERR_NET_BAD_PACKET; goto ditch_packet; } } // see if we have an endpoint port = ntohs(header->dest_port); mutex_lock(&endpoints_lock); e = hash_lookup(endpoints, &port); if(e) udp_endpoint_acquire_ref(e); mutex_unlock(&endpoints_lock); if(!e) { err = NO_ERROR; #if NET_CHATTY dprintf("udp_receive: no endpoint found\n"); #endif goto ditch_packet; } // okay, we have an endpoint, lets queue our stuff up and move on qe = kmalloc(sizeof(udp_queue_elem)); if(!qe) { udp_endpoint_release_ref(e); err = ERR_NO_MEMORY; goto ditch_packet; } qe->src_port = ntohs(header->source_port); qe->target_port = port; qe->src_address = source_address; qe->target_address = target_address; qe->len = ntohs(header->length) - sizeof(udp_header); // trim off the udp header buf = cbuf_truncate_head(buf, sizeof(udp_header), true); qe->buf = buf; mutex_lock(&e->lock); udp_queue_push(&e->q, qe); mutex_unlock(&e->lock); sem_release(e->blocking_sem); udp_endpoint_release_ref(e); err = NO_ERROR; return err; ditch_packet: #if NET_CHATTY dprintf("udp_receive: packet thrown away\n"); #endif cbuf_free_chain(buf); return err; }
errno_t dns_request(const unsigned char *host, ipv4_addr server, ipv4_addr *result) { // TODO 64 k on stack? unsigned char buf[32000]; //unsigned char buf[65536]; unsigned char *qname, *reader; int i, j, stop; struct RES_RECORD answers[20], auth[20], addit[20]; //the replies from the DNS server struct DNS_HEADER *dns = NULL; struct QUESTION *qinfo = NULL; #ifdef KERNEL void *s; int res = udp_open(&s); if( res ) { SHOW_ERROR0( 0, "Can't get socket"); return ENOTSOCK; } #else int s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries #endif //SHOW_FLOW0( 2, "got sock"); #ifdef KERNEL i4sockaddr addr; addr.port = 53; addr.addr.len = 4; addr.addr.type = ADDR_TYPE_IP; NETADDR_TO_IPV4(addr.addr) = server; #else struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_port = htons(53); dest.sin_addr.s_addr = inet_addr(dns_servers[0]); //dns servers #endif memset(buf, 0, sizeof(buf)); //Set the DNS structure to standard queries dns = (struct DNS_HEADER *)&buf; #ifdef KERNEL dns->id = (unsigned short) random(); #else dns->id = (unsigned short) htons(getpid()); #endif dns->qr = 0; //This is a query dns->opcode = 0; //This is a standard query dns->aa = 0; //Not Authoritative dns->tc = 0; //This message is not truncated dns->rd = 1; //Recursion Desired dns->ra = 0; //Recursion not available! hey we dont have it (lol) dns->z = 0; dns->ad = 0; dns->cd = 0; dns->rcode = 0; dns->q_count = htons(1); //we have only 1 question dns->ans_count = 0; dns->auth_count = 0; dns->add_count = 0; //point to the query portion qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)]; ChangetoDnsNameFormat(qname , host); int qname_len = (strlen((const char*)qname) + 1); qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + qname_len]; //fill it qinfo->qtype = htons(1); //we are requesting the ipv4 address qinfo->qclass = htons(1); //its internet (lol) STAT_INC_CNT(STAT_CNT_DNS_REQ); SHOW_FLOW0( 3, "Sending Packet"); int sendLen = sizeof(struct DNS_HEADER) + qname_len + sizeof(struct QUESTION); #ifdef KERNEL int ret = udp_sendto( s, buf, sendLen, &addr); if( ret ) #else if(sendto(s,(char*)buf, sendLen, 0, (struct sockaddr*)&dest, sizeof(dest)) != sendLen) #endif { SHOW_ERROR( 0, "Error sending req, %d", ret); goto reterr; } SHOW_FLOW0( 3, "Sent"); #ifdef KERNEL long tmo = 1000L*1000L*2; // 2 sec //long tmo = 1000L*10; if( udp_recvfrom( s, buf, sizeof(buf), &addr, SOCK_FLAG_TIMEOUT, tmo) <= 0 ) #else i = sizeof dest; ret = recvfrom (s,(char*)buf,65536,0,(struct sockaddr*)&dest,&i); if(ret == 0) #endif { SHOW_ERROR0( 1, "Failed"); goto reterr; } SHOW_FLOW0( 3, "Received"); STAT_INC_CNT(STAT_CNT_DNS_ANS); dns = (struct DNS_HEADER*) buf; //move ahead of the dns header and the query field reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)]; if(debug_level_flow > 6) { printf("The response contains : \n"); printf("%d Questions.\n",ntohs(dns->q_count)); printf("%d Answers.\n",ntohs(dns->ans_count)); printf("%d Authoritative Servers.\n",ntohs(dns->auth_count)); printf("%d Additional records.\n\n",ntohs(dns->add_count)); } //reading answers stop=0; for(i=0;i<ntohs(dns->ans_count);i++) { answers[i].name=ReadName(reader,buf,&stop); reader = reader + stop; answers[i].resource = (struct R_DATA*)(reader); reader = reader + sizeof(struct R_DATA); if(ntohs(answers[i].resource->type) == 1) //if its an ipv4 address { answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len)); for(j=0 ; j<ntohs(answers[i].resource->data_len) ; j++) answers[i].rdata[j]=reader[j]; answers[i].rdata[ntohs(answers[i].resource->data_len)] = FIN; reader = reader + ntohs(answers[i].resource->data_len); } else { answers[i].rdata = ReadName(reader,buf,&stop); reader = reader + stop; } } //read authorities for(i=0;i<ntohs(dns->auth_count);i++) { auth[i].name=ReadName(reader,buf,&stop); reader+=stop; auth[i].resource=(struct R_DATA*)(reader); reader+=sizeof(struct R_DATA); auth[i].rdata=ReadName(reader,buf,&stop); reader+=stop; } //read additional for(i=0;i<ntohs(dns->add_count);i++) { addit[i].name=ReadName(reader,buf,&stop); reader+=stop; addit[i].resource=(struct R_DATA*)(reader); reader+=sizeof(struct R_DATA); if(ntohs(addit[i].resource->type)==1) { addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len)); for(j=0;j<ntohs(addit[i].resource->data_len);j++) addit[i].rdata[j]=reader[j]; addit[i].rdata[ntohs(addit[i].resource->data_len)]= FIN; reader+=ntohs(addit[i].resource->data_len); } else { addit[i].rdata=ReadName(reader,buf,&stop); reader+=stop; } } if(debug_level_flow > 6) { //print answers for(i=0;i<ntohs(dns->ans_count);i++) { printf("Name : %s ",answers[i].name); if(ntohs(answers[i].resource->type)==1) //IPv4 address { long *p; p=(long*)answers[i].rdata; struct sockaddr_in a; a.sin_addr.s_addr=(*p); //working without ntohl printf("has IPv4 address : %s",inet_ntoa(a.sin_addr)); } if(ntohs(answers[i].resource->type)==5) //Canonical name for an alias printf("has alias name : %s",answers[i].rdata); printf("\n"); } //print authorities for(i=0;i<ntohs(dns->auth_count);i++) { printf("Name : %s ",auth[i].name); if(ntohs(auth[i].resource->type)==2) printf("has authoritative nameserver : %s",auth[i].rdata); printf("\n"); } //print additional resource records for(i=0;i<ntohs(dns->add_count);i++) { printf("Name : %s ",addit[i].name); if(ntohs(addit[i].resource->type)==1) { long *p; p=(long*)addit[i].rdata; struct sockaddr_in a; a.sin_addr.s_addr=(*p); //working without ntohl printf("has IPv4 address : %s",inet_ntoa(a.sin_addr)); } printf("\n"); } } // return answer for( i=0; i < ntohs(dns->ans_count); i++ ) { if( ntohs(answers[i].resource->type) == 1 ) //IPv4 address { *result = *( (long*)answers[i].rdata); udp_close(s); return 0; } } reterr: // No direct answer *result = 0; udp_close(s); return ENOENT; }