Пример #1
0
/*
 * queue add class_name qdisc_name [-size num_slots] [-weight value] [-delay delay_microsec]
 * queue show
 * queue del queue_number
 * queue mod queue_number [-weight value] [-delay delay_microsec]
 * queue stats [queue_number]
 */
void queueCmd()
{
	char *next_tok;
	char cname[MAX_DNAME_LEN], qdisc[MAX_DNAME_LEN];
	// the following parameters are set to default values which are sometimes overwritten
	int num_slots = 0;   // means, set to default
	double weight = 1.0, delay = 2.0;


	if ((next_tok = strtok(NULL, " \n")) != NULL)
	{
		if (!strcmp(next_tok, "add"))
		{
			next_tok = strtok(NULL, " \n");
			strcpy(cname, next_tok);
			if (getClassDef(classifier, cname) == NULL)
			{
				verbose(1, "[queue]:: class name %s not defined ..", cname);
				return;
			}
			next_tok = strtok(NULL, " \n");
			strcpy(qdisc, next_tok);
			if (lookupQDisc(pcore->qdiscs, qdisc) < 0)
			{
				verbose(1, "[queue]:: qdisc %s not defined .. ", qdisc);
				return;
			}

			while ((next_tok = strtok(NULL, " \n")) != NULL)
			{
				if (!strcmp(next_tok, "-size"))
				{
					next_tok = strtok(NULL, " \n");
					num_slots = atoi(next_tok);
				}
				else if (!strcmp(next_tok, "-weight"))
				{
					next_tok = strtok(NULL, " \n");
					weight = atof(next_tok);
				}
				else if (!strcmp(next_tok, "-delay"))
				{
					next_tok = strtok(NULL, " \n");
					delay = atof(next_tok);
				}
			}
			addPktCoreQueue(pcore, cname, qdisc, weight, delay, num_slots);
		}
		else if (!strcmp(next_tok, "show"))
			printAllQueues(pcore);
		else if (!strcmp(next_tok, "del"))
		{
			if ((next_tok = strtok(NULL, " \n")) != NULL)
				delPktCoreQueue(pcore, next_tok);
		}
		else if (!strcmp(next_tok, "mod"))
		{
			if ((next_tok = strtok(NULL, " \n")) != NULL)
			{
				strcpy(cname, next_tok);
				if ((next_tok = strtok(NULL, " \n")) != NULL)
				{
					if (!strcmp(next_tok, "-weight"))
					{
						next_tok = strtok(NULL, " \n");
						weight = atof(next_tok);
						modifyQueueWeight(pcore, cname, weight);
					}
					else if (!strcmp(next_tok, "-qdisc"))
					{
						next_tok = strtok(NULL, " \n");
						modifyQueueDiscipline(pcore, cname, next_tok);
					}
				}
			}
		}
		else if (!strcmp(next_tok, "stats"))
			printQueueStats(pcore);
	}
}
Пример #2
0
void* __ctBackgroundThreadWriter(void* d)
{
    FILE* serialFile;
    char* fname = getenv("CONTECH_FE_FILE");
    unsigned int wpos = 0;
    unsigned int maxBuffersAlloc = 0, memLimitBufCount = 0;
    size_t totalWritten = 0;
    pct_serial_buffer memLimitQueue = NULL;
    pct_serial_buffer memLimitQueueTail = NULL;
    unsigned long long totalLimitTime = 0, startLimitTime, endLimitTime;
    int mpiRank = __ctGetMPIRank();
    int mpiPresent = __ctIsMPIPresent();
    // TODO: Create MPI event
    // TODO: Modify filename with MPI rank
    // TODO: Only do the above when MPI is present
    
    if (fname == NULL)
    {
        if (mpiPresent != 0)
        {
            char* fnameMPI = strdup("/tmp/contech_fe      ");
            fnameMPI[15] = '.';
            snprintf(fnameMPI + 16, 5, "%d", mpiRank);
            serialFile = fopen(fnameMPI, "wb");
            free(fnameMPI);
        }
        else
        {
            serialFile = fopen("/tmp/contech_fe", "wb");
        }
    }
    else
    {
        serialFile = fopen(fname, "wb");
    }

    if (serialFile == NULL)
    {
        fprintf(stderr, "Failure to open front-end stream for writing.\n");
        if (fname == NULL) { fprintf(stderr, "\tCONTECH_FE_FILE unspecified\n");}
        else {fprintf(stderr, "\tAttempted on %s\n", fname);}
        exit(-1);
    }
    
    {
        unsigned int id = 0;
        ct_event_id ty = ct_event_version;
        unsigned int version = CONTECH_EVENT_VERSION;
        uint8_t* bb_info = _binary_contech_bin_start;
        
        fwrite(&id, sizeof(unsigned int), 1, serialFile); 
        fwrite(&ty, sizeof(unsigned int), 1, serialFile);
        fwrite(&version, sizeof(unsigned int), 1, serialFile);
        fwrite(bb_info, sizeof(unsigned int), 1, serialFile);
        totalWritten += 4 * sizeof(unsigned int);
        
        {
            size_t tl, wl;
            unsigned int buf[2];
            buf[0] = ct_event_rank;
            buf[1] = mpiRank;
            
            tl = 0;
            do
            {
                wl = fwrite(&buf + tl, sizeof(unsigned int), 2 - tl, serialFile);
                //if (wl > 0)
                // wl is 0 on error, so it is safe to still add
                tl += wl;
            } while  (tl < 2);
            
            totalWritten += 2 * sizeof(unsigned int);
        }
        
        bb_info += 4; // skip the basic block count
        while (bb_info != _binary_contech_bin_end)
        {
            // id, len, memop_0, ... memop_len-1
            // Contech pass lays out the events in appropriate format
            size_t tl = fwrite(bb_info, sizeof(char), _binary_contech_bin_end - bb_info, serialFile);
            bb_info += tl;
            totalWritten += tl;
        }
    }
    
    // Main loop
    //   Write queued buffer to disk until program terminates
    pthread_mutex_lock(&__ctQueueBufferLock);
    do {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        ts.tv_sec += 30;
        int condRetVal = 0;
        
        // Check for queued buffer, i.e. is the program generating events
        while (__ctQueuedBuffers == NULL && condRetVal == 0)
        {
            condRetVal = pthread_cond_timedwait(&__ctQueueSignal, &__ctQueueBufferLock, &ts);
        }
        if (condRetVal == 0)
        {
            pthread_mutex_unlock(&__ctQueueBufferLock);
        }
    
        // The thread writer will likely sit in this loop except when the memory limit is triggered
        while (__ctQueuedBuffers != NULL)
        {
            // Write buffer to file
            size_t tl = 0;
            size_t wl = 0;
            pct_serial_buffer qb = __ctQueuedBuffers;
            
            // First craft the marker event that indicates a new buffer in the event list
            //   This event tells eventLib which contech created the next set of bytes
            {
                unsigned int buf[3];
                buf[0] = ct_event_buffer;
                buf[1] = __ctQueuedBuffers->id;
                buf[2] = __ctQueuedBuffers->basePos;
                //fprintf(stderr, "%d, %llx, %d\n", __ctQueuedBuffers->id, totalWritten, __ctQueuedBuffers->pos);
                do
                {
                    wl = fwrite(&buf + tl, sizeof(unsigned int), 3 - tl, serialFile);
                    //if (wl > 0)
                    // wl is 0 on error, so it is safe to still add
                    tl += wl;
                } while  (tl < 3);

                totalWritten += 3 * sizeof(unsigned int);
                
            }
            
            // TODO: fully integrate into debug framework
            #if DEBUG
            if (totalWritten < 256)
            {
                int i;
                for (i = 0; i < 256; i ++)
                {
                    fprintf(stderr, "%x ", __ctQueuedBuffers->data[i]);
                }
            }
            #endif
            
            // Now write the bytes out of the buffer, until all have been written
            tl = 0;
            wl = 0;
            if (qb->pos > SERIAL_BUFFER_SIZE)
            {
                fprintf(stderr, "Illegal buffer size - %d\n", qb->pos);
            }
            while (tl < __ctQueuedBuffers->pos)
            {
                wl = fwrite(__ctQueuedBuffers->data + tl, 
                            sizeof(char), 
                            (__ctQueuedBuffers->pos) - tl, 
                            serialFile);
                // if (wl < 0)
                // {
                //     continue;
                // }
                tl += wl;
                if (qb != __ctQueuedBuffers)
                {
                    fprintf(stderr, "Tampering with __ctQueuedBuffers!\n");
                }
            }
            if (tl != __ctQueuedBuffers->pos)
            {
                fprintf(stderr, "Write quantity(%lu) is not bytes in buffer(%d)\n", tl, __ctQueuedBuffers->pos);
            }
            totalWritten += tl;
            
            // "Free" buffer
            // First move the queue pointer, as we implicitly held the first element
            // Then switch locks and put this processed buffer onto the free list
            pthread_mutex_lock(&__ctQueueBufferLock);
            {
                pct_serial_buffer t = __ctQueuedBuffers;
                __ctQueuedBuffers = __ctQueuedBuffers->next;
                if (__ctQueuedBuffers == NULL) __ctQueuedBufferTail = NULL;
                pthread_mutex_unlock(&__ctQueueBufferLock);
                
                if (t->length < SERIAL_BUFFER_SIZE)
                {
                    free(t);
                    // After the unlock is end of while loop, 
                    //  so as the buffer was free() rather than put on the list
                    //  we continue
                    continue;
                }
                //continue; // HACK: LEAK!
                
                // Switching locks, "t" is now only held locally
                pthread_mutex_lock(&__ctFreeBufferLock);
#ifdef DEBUG
                pthread_mutex_lock(&__ctPrintLock);
                fprintf(stderr, "f,%p,%d\n", t, t->id);
                fflush(stderr);
                pthread_mutex_unlock(&__ctPrintLock);
#endif
                
                if (__ctCurrentBuffers == __ctMaxBuffers)
                {
                    if (__ctQueuedBuffers == NULL)
                    {
                        // memlimit end
                        struct timeb tp;
                        ftime(&tp);
                        endLimitTime = tp.time*1000 + tp.millitm;
                        totalLimitTime += (endLimitTime - startLimitTime);
                        memLimitQueueTail->next = t;
                        t->next = __ctFreeBuffers;
                        __ctFreeBuffers = memLimitQueue;
                        maxBuffersAlloc = __ctCurrentBuffers;
                        
                        // N.B. It is possible that thread X is holding a lock L
                        //   and then attempts to queue and allocate a new buffer.
                        //   And that thread Y blocks on lock L, whereby its buffer
                        //   will not be in the queue and therefore the count should
                        //   be greater than 0.
                        __ctCurrentBuffers = __ctMaxBuffers - (memLimitBufCount + 1);
                        memLimitQueue = NULL;
                        memLimitQueueTail = NULL;
                        pthread_cond_broadcast(&__ctFreeSignal);
                    }
                    else
                    {
                        if (memLimitQueueTail == NULL)
                        {
                            memLimitBufCount = 1;
                            memLimitQueue = t;
                            memLimitQueueTail = t;
                            t->next = NULL;
                            // memlimit start
                            struct timeb tp;
                            ftime(&tp);
                            startLimitTime = tp.time*1000 + tp.millitm;
                        }
                        else
                        {
                            memLimitBufCount ++;
                            memLimitQueueTail->next = t;
                            t->next = NULL;
                            memLimitQueueTail = t;
                        }
                    }
                }
                else
                {
                    t->next = __ctFreeBuffers;
                    __ctFreeBuffers = t;
                    if (__ctCurrentBuffers > maxBuffersAlloc)
                    {
                        maxBuffersAlloc = __ctCurrentBuffers;
                    }
                    assert(__ctCurrentBuffers > 0);
                    __ctCurrentBuffers --;
#if DEBUG
                    if (__ctCurrentBuffers < 2)
                    {
                        printf("%p\n", &t->data);
                    }
#endif
                }
            }
            pthread_mutex_unlock(&__ctFreeBufferLock);
        }
        
        // Exit condition is # of threads exited = # of threads
        // N.B. Main is part of this count
        pthread_mutex_lock(&__ctQueueBufferLock);
        if (__ctThreadExitNumber == __ctThreadGlobalNumber && 
            __ctQueuedBuffers == NULL) 
        { 
            // destroy mutex, cond variable
            // TODO: free freedBuffers
            {
                struct timeb tp;
                ftime(&tp);
                printf("CT_COMP: %d.%03d\n", (unsigned int)tp.time, tp.millitm);
                printf("CT_LIMIT: %llu.%03llu\n", totalLimitTime / 1000, totalLimitTime % 1000);
            }
            printf("Total Contexts: %u\n", __ctThreadGlobalNumber);
            printf("Total Uncomp Written: %ld\n", totalWritten);
            printf("Max Buffers Alloc: %u of %lu\n", maxBuffersAlloc, sizeof(ct_serial_buffer_sized));
            {
                struct rusage use;
                if (0 == getrusage(RUSAGE_SELF, &use))
                {
                    printf("Max RSS: %ld\n", use.ru_maxrss);
                }
            }
            printQueueStats();
            fflush(stdout);
            
            fflush(serialFile);
            fclose(serialFile);
            
            pthread_mutex_unlock(&__ctQueueBufferLock);
            pthread_exit(NULL);            
        }
    } while (1);
}