Exemplo n.º 1
0
Arquivo: main.c Projeto: tzuryby/pimd
int main(int argc, char *argv[])
{	
    int dummy, dummysigalrm, foreground = 0;
    struct timeval tv, difftime, curtime, lasttime, *timeout;
    fd_set rfds, readers;
    int nfds, n, i, secs, ch;
    struct sigaction sa;
    time_t boottime;
    struct option long_options[] = {
	{"config", 1, 0, 'c'},
	{"debug", 2, 0, 'd'},
	{"foreground", 0, 0, 'f'},
	{"disable-vifs", 0, 0, 'N'},
	{"help", 0, 0, 'h'},
	{"version", 0, 0, 'v'},
	{"quit-daemon", 0, 0, 'q'},
	{"reload-config", 0, 0, 'l'},
	{"show-routes", 0, 0, 'r'},
	/* {"show-cache", 0, 0, 'i'}, */
	/* {"show-debug", 0, 0, 'p'}, */
	{0, 0, 0, 0}
    };
    
    snprintf(versionstring, sizeof (versionstring), "pimd version %s", todaysversion);

    while ((ch = getopt_long (argc, argv, "c:d::fhlNP::vqr", long_options, NULL)) != EOF) {
	switch (ch) {
	    case 'c':
		configfilename = optarg;
		break;

	    case 'd':
		if (!optarg) {
		    debug = DEBUG_DEFAULT;
		} else {
		    char *p,*q;
		    size_t i, len;
		    struct debugname *d;

		    debug = 0;
		    p = optarg; q = NULL;
		    while (p) {
			q = strchr(p, ',');
			if (q)
			    *q++ = '\0';
			len = strlen(p);
			for (i = 0, d = debugnames; i < ARRAY_LEN(debugnames); i++, d++)
			    if (len >= d->nchars && strncmp(d->name, p, len) == 0)
				break;

			if (i == ARRAY_LEN(debugnames))
			    return usage();

			debug |= d->level;
			p = q;
		    }
		}
		break;

	    case 'f':
		foreground = 1;
		break;

	    case 'h':
		return usage();

	    case 'l':
		killshow(SIGHUP, NULL);
		return 0;

	    case 'N':
		disable_all_by_default = 1;
		break;

	    case 'P':
#ifdef SNMP
		if (!optarg)
		    dest_port = DEFAULT_PORT;
		else {
		    dest_port = strtonum(optarg, 1, 65535, &errstr);
		    if (errstr) {
			warnx("destination port %s", errstr);
			dest_port = DEFAULT_PORT;
		    }
		}
#else
		warnx("SNMP support missing, please feel free to submit a patch.");
#endif
		break;

	    case 'v':
		printf("%s\n", versionstring);
		return 0;

	    case 'q':
		killshow(SIGTERM, NULL);
		return 0;

	    case 'r':
		killshow(SIGUSR1, _PATH_PIMD_DUMP);
		return 0;
#if 0 /* XXX: TODO */
	    case 'i':
		killshow(SIGUSR2, _PATH_PIMD_CACHE);
		return 0;

	    case 'p':
		killshow(SIGQUIT, NULL);
		return 0;
#endif
	    default:
		return usage();
	}
    }

    argc -= optind;
    argv += optind;

    if (argc > 0) {
	return usage();
    }

    if (geteuid() != 0) {
	fprintf(stderr, "%s: must be root\n", __progname);
	exit(1);
    }
    setlinebuf(stderr);

    if (debug != 0) {
	struct debugname *d;
	char c;
	int tmpd = debug;

	fprintf(stderr, "debug level 0x%lx ", debug);
	c = '(';
	for (d = debugnames; d < debugnames + ARRAY_LEN(debugnames); d++) {
	    if ((tmpd & d->level) == d->level) {
		tmpd &= ~d->level;
		fprintf(stderr, "%c%s", c, d->name);
		c = ',';
	    }
	}
	fprintf(stderr, ")\n");
    }
    
    /*
     * Create directory for runtime files
     */
    mkdir(_PATH_PIMD_RUNDIR, 0755);

    /*
     * Setup logging
     */
#ifdef LOG_DAEMON
    (void)openlog("pimd", LOG_PID, LOG_DAEMON);
    (void)setlogmask(LOG_UPTO(LOG_NOTICE));
#else
    (void)openlog("pimd", LOG_PID);
#endif /* LOG_DAEMON */

    logit(LOG_DEBUG, 0, "%s starting", versionstring);

    do_randomize();
    time(&boottime);
    
    /* Start up the log rate-limiter */
    resetlogging(NULL);

    callout_init();
    init_igmp();
    init_pim();
#ifdef HAVE_ROUTING_SOCKETS
    init_routesock();
#endif /* HAVE_ROUTING_SOCKETS */
    init_pim_mrt();
    init_timers();
    
    /* TODO: check the kernel DVMRP/MROUTED/PIM support version */
    
#ifdef SNMP
    if (i = snmp_init())
	return i;
#endif /* SNMP */
    init_vifs();
    init_rp_and_bsr();   /* Must be after init_vifs() */
    
#ifdef RSRR
    rsrr_init();
#endif /* RSRR */
    
    sa.sa_handler = handler;
    sa.sa_flags = 0;	/* Interrupt system calls */
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);
    
    FD_ZERO(&readers);
    FD_SET(igmp_socket, &readers);
    nfds = igmp_socket + 1;
    for (i = 0; i < nhandlers; i++) {
	FD_SET(ihandlers[i].fd, &readers);
	if (ihandlers[i].fd >= nfds)
	    nfds = ihandlers[i].fd + 1;
    }
    
    IF_DEBUG(DEBUG_IF)
	dump_vifs(stderr);
    IF_DEBUG(DEBUG_PIM_MRT)
	dump_pim_mrt(stderr);
    
    /* schedule first timer interrupt */
    timer_setTimer(TIMER_INTERVAL, timer, NULL);
    
    if (!debug && !foreground) {
	/* Detach from the terminal */
	haveterminal = 0;
	if (fork())
	    exit(0);
	(void)close(0);
	(void)close(1);
	(void)close(2);
	(void)open("/", 0);
	(void)dup2(0, 1);
	(void)dup2(0, 2);
#ifdef SYSV
	(void)setpgrp();
#else 
#ifdef TIOCNOTTY
	n = open("/dev/tty", 2);
	if (n >= 0) {
	    (void)ioctl(n, TIOCNOTTY, (char *)0);
	    (void)close(n);
	}
#else
	if (setsid() < 0)
	    perror("setsid");
#endif /* TIOCNOTTY */
#endif /* SYSV */
    } /* End of child process code */
    
    if (pidfile(NULL)) {
	warn("Cannot create pidfile");
    }

    /*
     * Main receive loop.
     */
    dummy = 0;
    dummysigalrm = SIGALRM;
    difftime.tv_usec = 0;
    gettimeofday(&curtime, NULL);
    lasttime = curtime;
    while (1) {
	memcpy(&rfds, &readers, sizeof(rfds));
	secs = timer_nextTimer();
	if (secs == -1)
	    timeout = NULL;
	else {
	    timeout = &tv;
	    timeout->tv_sec = secs;
	   timeout->tv_usec = 0;
        }

        if (boottime) {
           time_t n;

           time(&n);
           if (n > boottime + 15) {
              struct rp_hold *rph = g_rp_hold;

              while(rph) {
                 add_rp_grp_entry(&cand_rp_list, &grp_mask_list,
                                  rph->address, 1, (u_int16)0xffffff, rph->group, rph->mask,
                                  curr_bsr_hash_mask, curr_bsr_fragment_tag);
                 rph = rph->next;
              }
              boottime = 0;
           }
        }
	
	if (sighandled) {
	    if (sighandled & GOT_SIGINT) {
		sighandled &= ~GOT_SIGINT;
		break;
	    }
	    if (sighandled & GOT_SIGHUP) {
		sighandled &= ~GOT_SIGHUP;
		restart(SIGHUP);
		
		/* reconstruct readers and nfds */
		FD_ZERO(&readers);
		FD_SET(igmp_socket, &readers);
		nfds = igmp_socket + 1;
		for (i = 0; i < nhandlers; i++) {
		    FD_SET(ihandlers[i].fd, &readers);
		    if (ihandlers[i].fd >= nfds)
			nfds = ihandlers[i].fd + 1;
		}
		memcpy(&rfds, &readers, sizeof(rfds));
	    }
	    if (sighandled & GOT_SIGUSR1) {
		sighandled &= ~GOT_SIGUSR1;
		fdump(SIGUSR1);
	    }
	    if (sighandled & GOT_SIGUSR2) {
		sighandled &= ~GOT_SIGUSR2;
		cdump(SIGUSR2);
	    }
	    if (sighandled & GOT_SIGALRM) {
		sighandled &= ~GOT_SIGALRM;
		timer(&dummysigalrm);
	    }
	}
	if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
	    if (errno != EINTR) /* SIGALRM is expected */
		logit(LOG_WARNING, errno, "select failed");
	    continue;
	}
	if (n > 0) {
	    /* TODO: shall check first igmp_socket for better performance? */
	    for (i = 0; i < nhandlers; i++) {
		if (FD_ISSET(ihandlers[i].fd, &rfds)) {
		    (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
		}
	    }
	}
    
	/*
	 * Handle timeout queue.
	 *
	 * If select + packet processing took more than 1 second,
	 * or if there is a timeout pending, age the timeout queue.
	 *
	 * If not, collect usec in difftime to make sure that the
	 * time doesn't drift too badly.
	 *
	 * If the timeout handlers took more than 1 second,
	 * age the timeout queue again.  XXX This introduces the
	 * potential for infinite loops!
	 */
	do {
	    /*
	     * If the select timed out, then there's no other
	     * activity to account for and we don't need to
	     * call gettimeofday.
	     */
	    if (n == 0) {
		curtime.tv_sec = lasttime.tv_sec + secs;
		curtime.tv_usec = lasttime.tv_usec;
		n = -1;	/* don't do this next time through the loop */
	    } else
		gettimeofday(&curtime, NULL);
	    difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
	    difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
	    while (difftime.tv_usec >= 1000000) {
		difftime.tv_sec++;
		difftime.tv_usec -= 1000000;
	    }
	    if (difftime.tv_usec < 0) {
		difftime.tv_sec--;
		difftime.tv_usec += 1000000;
	    }
	    lasttime = curtime;
	    if (secs == 0 || difftime.tv_sec > 0)
		age_callout_queue(difftime.tv_sec);
	    secs = -1;
	} while (difftime.tv_sec > 0);
    } /* Main loop */

    logit(LOG_NOTICE, 0, "%s exiting", versionstring);
    cleanup();
    exit(0);
}
Exemplo n.º 2
0
int main(int argc, char *argv[]) {
    struct cache **cache;
    struct list_entry **access_list;
    char *filename;
    FILE *program;
    char buffer[33];
    char operation;
    unsigned int address;

    int i, j;
    int opt;
    int tmp;

    int capacity;
    int way;
    int blocksize;
    int set;
    int words;
    int index_size;

    int cache_config_set = 0;
    int cache_dump_set = 0;

    int total_reads = 0;
    int total_writes = 0;
    int write_backs = 0;
    int reads_hits = 0;
    int write_hits = 0;
    int reads_misses = 0;
    int write_misses = 0;

    // Argument check
    if (argc < 2) {
        usage(argv[0]);
    }

    while ((opt = getopt(argc, argv, "c:x")) != -1) {
        switch (opt) {
            case 'c':
                cache_config_set = 1;
                if (sscanf(optarg, "%d:%d:%d",
                            &capacity, &way, &blocksize) != 3) {
                    usage(argv[0]);
                }
                if (capacity < 4 || capacity > 8192) {
                    printf("Capacity should be between 4B and 8KB.\n");
                    exit(1);
                }
                if (way < 1 || way > 16) {
                    printf("Associativity should be between 1 and 16.\n");
                    exit(1);
                }
                if (blocksize < 4 || blocksize > 32) {
                    printf("Block size should be between 4B and 32B.\n");
                    exit(1);
                }
                set = capacity / way / blocksize;
                words = blocksize / BYTES_PER_WORD;

                tmp = set / 2;
                index_size = 0;
                while (tmp > 0) {
                    index_size++;
                    tmp >>= 1;
                }
                break;
            case 'x':
                cache_dump_set = 1;
                break;
            case '?':
                usage(argv[0]);
        }
    }
    if (!cache_config_set) {
        printf("The cache parameters are specified with \"-c\" option.\n");
        exit(1);
    }
    if (argc == optind) {
        usage(argv[0]);
    }
    filename = argv[optind];

    // allocate
    cache = (struct cache **) malloc(sizeof(struct cache *) * set);
    access_list = (struct list_entry **)
        malloc(sizeof(struct list_entry *) * set);
    for (i = 0; i < set; i++) {
        struct list_entry *entry;
        struct list_entry *prev_entry = NULL;

        cache[i] = (struct cache *) malloc(sizeof(struct cache) * way);
        for (j = 0; j < way; j++) {
            cache[i][j].valid = 0;
            cache[i][j].dirty = 0;
            cache[i][j].content = 0x0;
        }

        entry = (struct list_entry *) malloc(sizeof(struct list_entry));
        entry->way = 0;
        entry->prev = prev_entry;
        access_list[i] = entry;
        for (j = 1; j < way; j++) {
            entry->next =
                (struct list_entry *) malloc(sizeof(struct list_entry));
            prev_entry = entry;
            entry = entry->next;
            entry->way = j;
            entry->prev = prev_entry;
        }
        entry->next = NULL;
    }

    // Open program file.
    program = fopen(filename, "r");
    if (program == NULL) {
        printf("Error: Can't open program file \"%s\"\n", filename);
        exit(-1);
    }

    while (fgets(buffer, 33, program) != NULL) {
        unsigned int entry;
        unsigned int index;
        int _way;
        struct cache *result_cache;
        struct list_entry *list_item;
        int hit;
        int invalid_exist;

        sscanf(buffer, "%c %x", &operation, &address);

        entry = address & ~(blocksize - 1);
        index = (address / blocksize) & ((1 << index_size) - 1);
        hit = 0;
        for (i = 0; i < way; i++) {
            if (cache[index][i].valid && cache[index][i].content == entry) {
                hit = 1;
                _way = i;
                result_cache = &cache[index][i];

                list_item = access_list[index];
                while (list_item->way != i) {
                    list_item = list_item->next;
                }
                if (list_item->prev != NULL) {
                    list_item->prev->next = list_item->next;
                    if (list_item->next != NULL) {
                        list_item->next->prev = list_item->prev;
                    }
                    access_list[index]->prev = list_item;
                    list_item->prev = NULL;
                    list_item->next = access_list[index];
                    access_list[index] = list_item;
                }
                break;
            }
        }
        if (!hit) {
            struct cache *evict_cache;

            list_item = access_list[index];
            invalid_exist = 0;
            for (i = 0; i < way; i++) {
                if (!cache[index][i].valid) {
                    invalid_exist = 1;
                    evict_cache = &cache[index][i];
                    _way = i;
                    while (list_item->way != i) {
                        list_item = list_item->next;
                    }
                    break;
                }
            }
            if (!invalid_exist) {
                for (i = 1; i < way; i++) {
                    list_item = list_item->next;
                }
                evict_cache = &cache[index][list_item->way];
                _way = list_item->way;
            }
            if (evict_cache->dirty) {
                write_backs++;
            }
            evict_cache->valid = 1;
            evict_cache->dirty = 0;
            evict_cache->content = entry;
            result_cache = evict_cache;

            if (list_item->prev != NULL) {
                list_item->prev->next = list_item->next;
                if (list_item->next != NULL) {
                    list_item->next->prev = list_item->prev;
                }
                access_list[index]->prev = list_item;
                list_item->prev = NULL;
                list_item->next = access_list[index];
                access_list[index] = list_item;
            }
        }

        switch (operation) {
            case 'R':
                total_reads++;
                hit ? reads_hits++ : reads_misses++;
                break;
            case 'W':
                result_cache->dirty = 1;
                total_writes++;
                hit ? write_hits++ : write_misses++;
                break;
        }
    }

    cdump(capacity, way, blocksize);
    sdump(total_reads, total_writes, write_backs,
            reads_hits, write_hits, reads_misses, write_misses);
    if (cache_dump_set) {
        xdump(set, way, cache);
    }

    for (i = 0; i < set; i++) {
        free(cache[i]);
    }
    free(cache);

    return 0;
}
Exemplo n.º 3
0
void SplitTree::printTechnique( const SplitTechniqueDesc& inTechniqueDesc, std::ostream& inStream )
{
  // TIM: sanity check:
  for( size_t i = 0; i < _dagOrderNodeList.size(); i++ )
    assert( _dagOrderNodeList[i]->getDagOrderIndex() == i );

//  dumpFile.open( "dump.txt" );

//  preRdsMagic();

  timeSplitCounter = 0;
  timePrintingCounter = 0;
  timeCompilingCounter = 0;

  unsigned long splitStart = getTime();

  {for( NodeList::iterator i = _outputList.begin(); i != _outputList.end(); ++i ) {
    (*i)->_isFinalOutput = true;
  }}

#ifdef SPLIT_SEARCH_EXHAUSTIVE
  exhaustiveSearch();
#else
  rdsSearch();
#endif

  unsigned long splitStop = getTime();
  timeSplitCounter += splitStop - splitStart;

  // TIM: we need to split somewhere
  for( size_t i = 0; i < _outputList.size(); i++ )
  {
    assert( _outputList[i]->_splitHere );
  }

  // assign "registers" to all split nodes
  {for( NodeList::iterator i = _dagOrderNodeList.begin(); i != _dagOrderNodeList.end(); ++i ) {
    (*i)->setTemporaryID( 0 );
  }}
  int outputID = 0;
  {for( NodeList::iterator i = _outputList.begin(); i != _outputList.end(); ++i ) {
    (*i)->setTemporaryID( _outputArgumentIndices[outputID++] );
  }}
  int temporaryID = 1;
  {for( NodeList::iterator i = _dagOrderNodeList.begin(); i != _dagOrderNodeList.end(); ++i )
  {
    if( (*i)->isMarkedAsSplit() && ((*i)->getTemporaryID() == 0) )
      (*i)->setTemporaryID( -(temporaryID++) );
  }}
  int temporaryCount = temporaryID-1;

  // now we go through the passes and print them?
  inStream << "\t.technique( gpu_technique_desc()" << std::endl;
  if( temporaryCount )
  {
    inStream << "\t\t.temporaries(" << temporaryCount << ")" << std::endl;
  }

  unmark( SplitNode::kMarkBit_Printed );

  std::cout << "time split " << timeSplitCounter << std::endl;
  std::cout << "time compile " << timeCompilingCounter << std::endl;
  std::cout << "time print " << timePrintingCounter << std::endl;
  std::ofstream cdump("configuration.dump");
  dumpPassConfiguration(cdump  );

  for( PassSet::iterator p = _passes.begin(); p != _passes.end(); ++p )
    rdsPrintPass( *p, inStream );

  inStream << "\t)";

//  dumpFile.close();
}