Beispiel #1
0
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;
}
Beispiel #2
0
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;


}
Beispiel #3
0
//! 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 );
}
Beispiel #4
0
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 );
    }
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}