Exemplo n.º 1
0
/*
 * chitcpd_server_network_thread_func - Server thread function
 *
 * This function will spawn a connection thread (see connection.c)
 * for each new connection on the UNIX socket.
 *
 * args: arguments (a serverinfo_t variable in network_thread_args_t)
 *
 * Returns: Nothing.
 *
 */
void* chitcpd_server_network_thread_func(void *args)
{
    socklen_t sunSize;
    network_thread_args_t *nta;
    socket_t realsocket;
    serverinfo_t *si;
    tcpconnentry_t* connection;
    char addr_str[100];

    pthread_setname_np(pthread_self(), "network_server");

    /* Unpack arguments */
    nta = (network_thread_args_t *) args;
    si = nta->si;

    struct sockaddr_storage client_addr;

    /* Accept connections on the TCP socket */
    for(;;)
    {
        /* Accept a connection */
        sunSize = sizeof(client_addr);
        if ((realsocket = accept(si->network_socket, (struct sockaddr *)&client_addr, &sunSize)) == -1)
        {
            /* If accept() returns in the CHITCPD_STATE_STOPPING, we don't
             * care what the error is. We just break out of the loop and
             * initiate an orderly shutdown. */
            if(si->state == CHITCPD_STATE_STOPPING)
                break;

            /* If this particular connection fails, no need to kill the entire thread. */
            perror("Could not accept() connection on network socket");
            continue;
        }

        chitcp_addr_str((struct sockaddr *) &client_addr, addr_str, sizeof(addr_str));
        chilog(INFO, "TCP connection received from %s", addr_str);

        /* Check whether the connection already exists. */
        connection = chitcpd_get_connection(si, (struct sockaddr *) &client_addr);
        if (connection != NULL)
        {
            /* If this is a loopback connection, there is already an entry in
             * the connection table, but we need to update its receive socket
             * and create its connection thread. */
           if(chitcp_addr_is_loopback((struct sockaddr *) &client_addr))
           {
               connection->realsocket_recv = realsocket;

               if(chitcpd_create_connection_thread(si, connection) != CHITCP_OK)
               {
                   perror("Could not create connection thread.");
                   // TODO: Perform orderly shutdown
                   pthread_exit(NULL);
               }

               continue;
           }
           else
           /* Otherwise, this is an error. The peer chiTCP daemon tried to create
            * a second connection, which shouldn't happen. */
            {
                perror("Peer chiTCP daemon tried to establish more than one connection.");
                close(realsocket);
                close(si->server_socket);
                // TODO: Perform orderly shutdown instead of just exiting
                pthread_exit(NULL);
            }
        }

        /* If this is not a loopback connection, we need to add an entry
         * for this connection */
        connection = chitcpd_add_connection(si, realsocket, realsocket, (struct sockaddr*) &client_addr);

        if (!connection)
        {
            perror("Could not create a connection to a peer chiTCP daemon");
            // TODO: Perform orderly shutdown
            pthread_exit(NULL);
        }

        if(chitcpd_create_connection_thread(si, connection) != CHITCP_OK)
        {
            perror("Could not create connection thread.");
            // TODO: Perform orderly shutdown
            pthread_exit(NULL);
        }
    }

    /* Close all TCP connections. This will force an exit of the
     * corresponding connection threads. */
    for(int i=0; i < si->connection_table_size; i++)
    {
        connection = &si->connection_table[i];
        if(!connection->available)
        {
            shutdown(connection->realsocket_recv, SHUT_RDWR);
            if (connection->realsocket_recv != connection->realsocket_send)
                shutdown(connection->realsocket_send, SHUT_RDWR);
            pthread_join(connection->thread, NULL);
        }
    }

    pthread_exit(NULL);
}
Exemplo n.º 2
0
void Thread::start() {
	pthread_create(&thread, NULL, pthread_entry, this);
	pthread_setname_np(thread, name.c_str());
}
Exemplo n.º 3
0
/** Our exception handler thread routine.
 * Wait for an exception message, uninstall our exception port, record the
 * exception information, and write a report.
 */
void* ksmachexc_i_handleExceptions(void* const userData)
{
    MachExceptionMessage exceptionMessage = {{0}};
    MachReplyMessage replyMessage = {{0}};

    const char* threadName = (const char*) userData;
    pthread_setname_np(threadName);
    if(threadName == kThreadSecondary)
    {
        KSLOG_DEBUG("This is the secondary thread. Suspending.");
        thread_suspend(ksmach_thread_self());
    }

    for(;;)
    {
        KSLOG_DEBUG("Waiting for mach exception");

        // Wait for a message.
        kern_return_t kr = mach_msg(&exceptionMessage.header,
                                    MACH_RCV_MSG,
                                    0,
                                    sizeof(exceptionMessage),
                                    g_exceptionPort,
                                    MACH_MSG_TIMEOUT_NONE,
                                    MACH_PORT_NULL);
        if(kr == KERN_SUCCESS)
        {
            break;
        }

        // Loop and try again on failure.
        KSLOG_ERROR("mach_msg: %s", mach_error_string(kr));
    }

    KSLOG_DEBUG("Trapped mach exception code 0x%x, subcode 0x%x",
                exceptionMessage.code[0], exceptionMessage.code[1]);
    if(g_installed)
    {
        bool wasHandlingCrash = g_context->handlingCrash;
        kscrashsentry_beginHandlingCrash(g_context);

        KSLOG_DEBUG("Exception handler is installed. Continuing exception handling.");

        KSLOG_DEBUG("Suspending all threads");
        kscrashsentry_suspendThreads();

        // Switch to the secondary thread if necessary, or uninstall the handler
        // to avoid a death loop.
        if(ksmach_thread_self() == g_primaryMachThread)
        {
            KSLOG_DEBUG("This is the primary exception thread. Activating secondary thread.");
            if(thread_resume(g_secondaryMachThread) != KERN_SUCCESS)
            {
                KSLOG_DEBUG("Could not activate secondary thread. Restoring original exception ports.");
                ksmachexc_i_restoreExceptionPorts();
            }
        }
        else
        {
            KSLOG_DEBUG("This is the secondary exception thread. Restoring original exception ports.");
            ksmachexc_i_restoreExceptionPorts();
        }

        if(wasHandlingCrash)
        {
            KSLOG_INFO("Detected crash in the crash reporter. Restoring original handlers.");
            // The crash reporter itself crashed. Make a note of this and
            // uninstall all handlers so that we don't get stuck in a loop.
            g_context->crashedDuringCrashHandling = true;
            kscrashsentry_uninstall(KSCrashTypeAsyncSafe);
        }

        // Fill out crash information
        KSLOG_DEBUG("Fetching machine state.");
        STRUCT_MCONTEXT_L machineContext;
        if(ksmachexc_i_fetchMachineState(exceptionMessage.thread.name, &machineContext))
        {
            if(exceptionMessage.exception == EXC_BAD_ACCESS)
            {
                g_context->faultAddress = ksmach_faultAddress(&machineContext);
            }
            else
            {
                g_context->faultAddress = ksmach_instructionAddress(&machineContext);
            }
        }

        KSLOG_DEBUG("Filling out context.");
        g_context->crashType = KSCrashTypeMachException;
        g_context->offendingThread = exceptionMessage.thread.name;
        g_context->registersAreValid = true;
        g_context->mach.type = exceptionMessage.exception;
        g_context->mach.code = exceptionMessage.code[0];
        g_context->mach.subcode = exceptionMessage.code[1];


        KSLOG_DEBUG("Calling main crash handler.");
        g_context->onCrash();


        KSLOG_DEBUG("Crash handling complete. Restoring original handlers.");
        kscrashsentry_uninstall(KSCrashTypeAsyncSafe);
        kscrashsentry_resumeThreads();
    }

    KSLOG_DEBUG("Replying to mach exception message.");
    // Send a reply saying "I didn't handle this exception".
    replyMessage.header = exceptionMessage.header;
    replyMessage.NDR = exceptionMessage.NDR;
    replyMessage.returnCode = KERN_FAILURE;

    mach_msg(&replyMessage.header,
             MACH_SEND_MSG,
             sizeof(replyMessage),
             0,
             MACH_PORT_NULL,
             MACH_MSG_TIMEOUT_NONE,
             MACH_PORT_NULL);

    return NULL;
}
Exemplo n.º 4
0
int phDal4Nfc_ReaderThread(void * pArg)
{
    char      retvalue;
    NFCSTATUS result = NFCSTATUS_SUCCESS;
    uint8_t   retry_cnt=0;
    void *    memsetRet;

    static int       MsgType= PHDAL4NFC_READ_MESSAGE;
    int *     pmsgType=&MsgType;

    phDal4Nfc_Message_t      sMsg;
    phOsalNfc_Message_t      OsalMsg ;
    int i;
    int i2c_error_count;
    int i2c_workaround;
    if (gDalContext.pDev != NULL) {
        i2c_workaround = gDalContext.pDev->enable_i2c_workaround;
    } else {
        LOGE("gDalContext.pDev is not set");
        return NFCSTATUS_FAILED;
    }

    pthread_setname_np(pthread_self(), "reader");

    /* Create the overlapped event. Must be closed before exiting
    to avoid a handle leak. This event is used READ API and the Reader thread*/

    DAL_PRINT("RX Thread \n");
    DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive);
    DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead);
    while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */
    {
        /* Check for the read request from user */
	DAL_PRINT("RX Thread Sem Lock\n");
        sem_wait(&nfc_read_sem);
        DAL_PRINT("RX Thread Sem UnLock\n");

        if (!gReadWriteContext.nReadThreadAlive)
        {
            /* got the signal that we should exit.  NOTE: we don't
               attempt to read below, since the read may block */
            break;
        }

        /* Issue read operation.*/

    i2c_error_count = 0;
retry:
	gReadWriteContext.nNbOfBytesRead=0;
	DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
	memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead);

	/* Wait for IRQ !!!  */
    gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);

    /* Reading the value 0x57 indicates a HW I2C error at I2C address 0x57
     * (pn544). There should not be false positives because a read of length 1
     * must be a HCI length read, and a length of 0x57 is impossible (max is 33).
     */
    if(i2c_workaround && gReadWriteContext.nNbOfBytesToRead == 1 &&
            gReadWriteContext.pReadBuffer[0] == 0x57)
    {
        i2c_error_count++;
        DAL_DEBUG("RX Thread Read 0x57 %d times\n", i2c_error_count);
        if (i2c_error_count < 5) {
            usleep(2000);
            goto retry;
        }
        DAL_PRINT("RX Thread NOTHING TO READ, RECOVER");
        phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
    }
    else
    {
        i2c_error_count = 0;

        if (low_level_traces)
        {
             phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead,
                    gReadWriteContext.pReadBuffer, low_level_traces);
        }
        DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
        DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
/*      DAL_PRINT("RX Thread ReadBuff[]={ ");
        for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++)
        {
          DAL_DEBUG("RX Thread 0x%x ", gReadWriteContext.pReadBuffer[i]);
        }
        DAL_PRINT("RX Thread }\n"); */

        /* read completed immediately */
        sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE;
        /* Update the state */
        phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
        phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
        memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
        memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
    }

    } /* End of thread Loop*/

    DAL_PRINT("RX Thread  exiting");

    return TRUE;
}
Exemplo n.º 5
0
/* What each thread is doing
*
* In principle this is an endless loop. The only time this loop gets interrupted is once
* thpool_destroy() is invoked or the program exits.
*
* @param  thread        thread that will run this function
* @return nothing
*/
static void* thread_do(Thread* thread) {
    float elapsed;
    int info;
    struct timespec cputime;
    JobQueue* queue;
    WorkGroup* workGroup;
    Job* job;
    thpool_function_type func_buff;
    void* arg_buff;
    int i;

    /* Set thread name for profiling and debugging */
    char thread_name[128] = {0};
    sprintf(thread_name, "thread-pool-%d", thread->id);

#if defined(__linux__)
    /* Use prctl instead to prevent using _GNU_SOURCE flag and implicit declaration */
    prctl(PR_SET_NAME, thread_name);
#elif defined(__APPLE__) && defined(__MACH__)
    pthread_setname_np(thread_name);
#else
    fprintf(stderr, "thread_do(): pthread_setname_np is not supported on this system");
#endif

    /* Assure all threads have been created before starting serving */
    ThPool* thpool = thread->thpool;

    /* Mark thread as alive (initialized) */
    pthread_mutex_lock(&thpool->thcount_lock);
    thpool->num_threads_alive += 1;
    pthread_mutex_unlock(&thpool->thcount_lock);

    queue = thpool->jobqueue;

    while (thpool->threads_keepalive) {

        bsem_wait(queue->has_jobs);

        if (!thpool->threads_keepalive) {
            break;
        }

        pthread_mutex_lock(&thpool->thcount_lock);
        thpool->num_threads_working++;
        pthread_mutex_unlock(&thpool->thcount_lock);

        while (thpool->threads_keepalive) {
            /* Read job from queue and execute it */
            pthread_mutex_lock(&queue->rwmutex);
            workGroup = jobqueue_pull(thpool, thread->id);
            pthread_mutex_unlock(&queue->rwmutex);

            if (workGroup == NULL)
                break;

            if (cppadcg_pool_verbose) {
                get_monotonic_time2(&workGroup->startTime);
            }

            for (i = 0; i < workGroup->size; ++i) {
                job = &workGroup->jobs[i];

                if (cppadcg_pool_verbose) {
                    get_monotonic_time2(&job->startTime);
                }

                int do_benchmark = job->elapsed != NULL;
                if (do_benchmark) {
                    elapsed = -get_thread_time(&cputime, &info);
                }

                /* Execute the job */
                func_buff = job->function;
                arg_buff = job->arg;
                func_buff(arg_buff);

                if (do_benchmark && info == 0) {
                    elapsed += get_thread_time(&cputime, &info);
                    if (info == 0) {
                        (*job->elapsed) = elapsed;
                    }
                }

                if (cppadcg_pool_verbose) {
                    get_monotonic_time2(&job->endTime);
                }
            }

            if (cppadcg_pool_verbose) {
                get_monotonic_time2(&workGroup->endTime);

                if (thread->processed_groups == NULL) {
                    thread->processed_groups = workGroup;
                } else {
                    workGroup->prev = thread->processed_groups;
                    thread->processed_groups = workGroup;
                }
            } else {
                free(workGroup->jobs);
                free(workGroup);
            }
        }

        pthread_mutex_lock(&thpool->thcount_lock);
        thpool->num_threads_working--;
        if (!thpool->num_threads_working) {
            pthread_cond_signal(&thpool->threads_all_idle);
        }
        pthread_mutex_unlock(&thpool->thcount_lock);
    }

    pthread_mutex_lock(&thpool->thcount_lock);
    thpool->num_threads_alive--;
    pthread_mutex_unlock(&thpool->thcount_lock);

    return NULL;
}
    void
    TCPThroughputAdaptation::sampleThread()
    {
        std::mutex m;
        auto prev = std::chrono::steady_clock::now();
        //char* home = getenv("HOME");
        //char* folder = "/Library/Documents";
        
        pthread_setname_np("com.videocore.tcp.adaptation");

        while(!m_exiting) {
            std::unique_lock<std::mutex> l(m);

            
            if(!m_exiting) {
                m_cond.wait_until(l, std::chrono::steady_clock::now() + std::chrono::seconds(kMeasurementDelay));
            }
            if(m_exiting) {
                break;
            }
            
            auto now = std::chrono::steady_clock::now();
            auto diff = now - prev;
            auto previousTurndownDiff = std::chrono::duration_cast<std::chrono::seconds>(now - m_previousTurndown).count();
            auto previousIncreaseDiff = std::chrono::duration_cast<std::chrono::seconds>(now - m_previousIncrease).count();
            prev = now;
            
            m_sentMutex.lock();
            m_buffMutex.lock();
            
            size_t totalSent = 0;
            
            for ( auto & samp : m_sentSamples )
            {
                totalSent += samp;
            }
            
            const float timeDelta            = float(std::chrono::duration_cast<std::chrono::microseconds>(diff).count()) / 1.0e6f;
            const float detectedBytesPerSec  = float(totalSent) / timeDelta;
            float vec = 0.f;
            float avg = 0.f;
            float turnAvg = 0.f;
            
            m_bwSamples.push_front(detectedBytesPerSec);
            if(m_bwSamples.size() > m_bwSampleCount) {
                m_bwSamples.pop_back();
            }
            for( int i = 0 ; i < m_bwSamples.size() ; ++i ) {
                avg += m_bwSamples[i] * m_bwWeights[i];
            }
            
            
            if(!m_bufferSizeSamples.empty()) {
                //const long bufferDelta = long(m_bufferSizeSamples.back()) - long(m_bufferSizeSamples.front());
                
                bool noBuffer = true;
              
                float frontAvg = 0.f;
                float backAvg = 0.f;
                int frontCount = 0;
                int backCount = 0;
                
                for (int i = 0 ; i < m_bufferSizeSamples.size() ; ++i) {

                    const float s1 = m_bufferSizeSamples[i] / 100.f;
                   // if(s1>0) noBuffer = false;
                    
                    if ( i < m_bufferSizeSamples.size() / 2 ) {
                        frontAvg += s1;
                        frontCount++;
                    } else {
                        backAvg += s1;
                        backCount++;
                    }
                }
                frontAvg /= float(frontCount);
                backAvg /= float(backCount);
                
                frontAvg = std::floor(frontAvg);
                backAvg = std::floor(backAvg);
                
                //if(noBuffer && m_bufferSizeSamples.back() > 0) noBuffer = false;
                
                DLog("NB: %d, FT: %f BK: %f\n", noBuffer, frontAvg, backAvg);
                if( (frontAvg > backAvg || backAvg == 0.f) && (!m_hasFirstTurndown || (previousTurndownDiff > kSettlementDelay && previousIncreaseDiff > kIncreaseDelta))) {
                    vec = 1.f;
                }
                else if( frontAvg > 0 && (frontAvg * 1.1 < backAvg)) {
                    vec = -1.f;

                    m_previousTurndown = now;
                    m_hasFirstTurndown = true;
                }

                
                if(m_previousVector < 0 && vec >= 0) {
                    m_turnSamples.push_front(m_bwSamples.front());
                    if(m_turnSamples.size() > kPivotSamples) {
                        m_turnSamples.pop_back();
                    }
                }

                if(m_turnSamples.size() > 0) {
                    
                    
                    for ( int i = 0 ; i < m_turnSamples.size() ; ++i ) {
                        turnAvg += m_turnSamples[i];
                    }
                    turnAvg /= m_turnSamples.size();
                    
                    if(detectedBytesPerSec > turnAvg) {
                        m_turnSamples.push_front(detectedBytesPerSec);
                        if(m_turnSamples.size() > kPivotSamples) {
                            m_turnSamples.pop_back();
                        }
                    }
                    
                    float a = (detectedBytesPerSec - avg) / turnAvg ;
                    float slope = 3.f * powf(a,2.f);
                    
                    vec *= std::min(1.f,std::max(atanf(slope) / kPI_2, 0.1f));
                    //DLog("a: %f slope: %f (%f)\n", a, slope, vec);
                    //DLog("S:%zu Δt:%f AVG:%fB/s Δ:%ld TAVG:%f DET:%f\n", totalSent, timeDelta, avg, bufferDelta, turnAvg, detectedBytesPerSec);
                }

                m_previousVector = vec;

            }
            m_sentSamples.clear();
            m_bufferSizeSamples.clear();
            m_bufferDurationSamples.clear();
            m_sentMutex.unlock();
            m_buffMutex.unlock();
            
            if(m_callback) {
                if(vec > 0.f) {
                    m_previousIncrease = now;
                }
                m_callback(vec, turnAvg);
            }
            
        }
    }
Exemplo n.º 7
0
void set_threadname(const char *name)
{
	pthread_t tid = pthread_self();
	pthread_setname_np(tid, name);
}
Exemplo n.º 8
0
TEST(pthread, pthread_setname_np__self) {
  ASSERT_EQ(0, pthread_setname_np(pthread_self(), "short 1"));
}
Exemplo n.º 9
0
/* Thread: main */
int
filescanner_init(void)
{
  int ret;

  scan_exit = 0;
  scanning = 0;

  evbase_scan = event_base_new();
  if (!evbase_scan)
    {
      DPRINTF(E_FATAL, L_SCAN, "Could not create an event base\n");

      return -1;
    }

#ifdef HAVE_PIPE2
  ret = pipe2(exit_pipe, O_CLOEXEC);
#else
  ret = pipe(exit_pipe);
#endif
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_SCAN, "Could not create pipe: %s\n", strerror(errno));

      goto pipe_fail;
    }

  exitev = event_new(evbase_scan, exit_pipe[0], EV_READ, exit_cb, NULL);
  if (!exitev || (event_add(exitev, NULL) < 0))
    {
      DPRINTF(E_LOG, L_SCAN, "Could not create/add command event\n");
      goto exitev_fail;
    }

  ret = inofd_event_set();
  if (ret < 0)
    {
      goto ino_fail;
    }

  cmdbase = commands_base_new(evbase_scan);

  ret = pthread_create(&tid_scan, NULL, filescanner, NULL);
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_SCAN, "Could not spawn filescanner thread: %s\n", strerror(errno));

      goto thread_fail;
    }

#if defined(HAVE_PTHREAD_SETNAME_NP)
  pthread_setname_np(tid_scan, "filescanner");
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
  pthread_set_name_np(tid_scan, "filescanner");
#endif

  return 0;

 thread_fail:
  commands_base_free(cmdbase);
  close(inofd);
 exitev_fail:
 ino_fail:
  close(exit_pipe[0]);
  close(exit_pipe[1]);
 pipe_fail:
  event_base_free(evbase_scan);

  return -1;
}
Exemplo n.º 10
0
void * Queue1Thread( void * v )
{
	int result = pthread_setname_np( pthread_self(), "FileQueue1" );
	if ( result != 0 )
	{
		LOG( "InitFileQueue: pthread_setname_np failed %s", strerror( result ) );
	}

	// Process incoming messages until queue is empty
	for ( ; ; )
	{
		Queue1.SleepUntilMessage();

		// If Queue3 hasn't finished our last output, sleep until it has.
		pthread_mutex_lock( &QueueMutex );
		while ( !QueueHasCleared )
		{
			// Atomically unlock the mutex and block until we get a message.
			pthread_cond_wait( &QueueWake, &QueueMutex );
		}
		pthread_mutex_unlock( &QueueMutex );

		const char * msg = Queue1.GetNextMessage();

		char commandName[1024] = {};
		sscanf( msg, "%s", commandName );
		const char * filename = msg + strlen( commandName ) + 1;

		MessageQueue * queue = &Queue3;
		char const * suffix = strstr( filename, "_nz.jpg" ); 
		if ( suffix != NULL )	
		{
			// cube map
			const char * const cubeSuffix[6] = { "_px.jpg", "_nx.jpg", "_py.jpg", "_ny.jpg", "_pz.jpg", "_nz.jpg" };
			
			MemBufferFile mbfs[6] = 
			{ 
				MemBufferFile( MemBufferFile::NoInit ), 
				MemBufferFile( MemBufferFile::NoInit ),
				MemBufferFile( MemBufferFile::NoInit ),
				MemBufferFile( MemBufferFile::NoInit ),
				MemBufferFile( MemBufferFile::NoInit ),
				MemBufferFile( MemBufferFile::NoInit ) 
			};

			char filenameWithoutSuffix[1024];
			int suffixStart = suffix - filename;
			strcpy( filenameWithoutSuffix, filename );
			filenameWithoutSuffix[suffixStart] = '\0';
			
			int side = 0;
			for ( ; side < 6; side++ )
			{
				char sideFilename[1024];
				strcpy( sideFilename, filenameWithoutSuffix );
				strcat( sideFilename, cubeSuffix[side] );
				if ( !mbfs[side].LoadFile( sideFilename ) )
				{
					if ( !mbfs[ side ].LoadFileFromPackage( sideFilename ) )
					{
						break;
					}
				}
				LOG( "Queue1 loaded '%s'", sideFilename );
			}
			if ( side >= 6 )
			{
				// if no error occured, post to next thread
				LOG( "%s.PostPrintf( \"%s %p %i %p %i %p %i %p %i %p %i %p %i\" )", "Queue3", commandName, 
						mbfs[0].Buffer, mbfs[0].Length,
						mbfs[1].Buffer, mbfs[1].Length,
						mbfs[2].Buffer, mbfs[2].Length,
						mbfs[3].Buffer, mbfs[3].Length,
						mbfs[4].Buffer, mbfs[4].Length,
						mbfs[5].Buffer, mbfs[5].Length );
				queue->PostPrintf( "%s %p %i %p %i %p %i %p %i %p %i %p %i", commandName,
						mbfs[0].Buffer, mbfs[0].Length,
						mbfs[1].Buffer, mbfs[1].Length,
						mbfs[2].Buffer, mbfs[2].Length,
						mbfs[3].Buffer, mbfs[3].Length,
						mbfs[4].Buffer, mbfs[4].Length,
						mbfs[5].Buffer, mbfs[5].Length );
				for ( int i = 0; i < 6; ++i )
				{
					// make sure we do not free the actual buffers because they're used in the next thread
					mbfs[i].Buffer = NULL;
					mbfs[i].Length = 0;
				}
			}
			else
			{
				// otherwise free the buffers we did manage to allocate
				for ( int i = 0; i < side; ++i )
				{
					mbfs[i].FreeData();
				}
			}
		}
		else
		{
			// non-cube map
			MemBufferFile mbf( filename );
			if ( mbf.Length <= 0 || mbf.Buffer == NULL )
			{
				if ( !mbf.LoadFileFromPackage( filename ) )
				{
					continue;
				}
			}
			LOG( "%s.PostPrintf( \"%s %p %i\" )", "Queue3", commandName, mbf.Buffer, mbf.Length );
			queue->PostPrintf( "%s %p %i", commandName, mbf.Buffer, mbf.Length );
			mbf.Buffer = NULL;
			mbf.Length = 0;
		}

		free( (void *)msg );
	}
	return NULL;
}
Exemplo n.º 11
0
/*^-----------------------------------------------------------------------------
| static PF
| command_line  : parse unix command line options.
|
|   int argc    :
|   char **argv :
|
|   TO DO : allow option values. eg: debug=3
+-----------------------------------------------------------------------------*/
int command_line( int argc, char **argv)
{
    FILE *fp;
    // int i;
    // char startup_info[1024];
    struct tm *ptr;
    time_t tm;
    int c;
    int option_index = 0;
    struct sched_param schedpar;
    int r;
    char command[200];





    static struct option long_options[] =
    {
        /* These options set a flag. */
        {"verbose", no_argument,       &Verbose, 1},
        {"listimf", no_argument,       &Listimfile, 1},
        /* These options don't set a flag.
        We distinguish them by their indices. */
        {"help",       no_argument,       0, 'h'},
        {"info",       no_argument,       0, 'i'},
        {"overwrite",  no_argument,       0, 'o'},
        {"idle",       no_argument,       0, 'e'}, 
        {"debug",      required_argument, 0, 'd'},
        {"mmon",      required_argument, 0, 'm'},
        {"pname",     required_argument, 0, 'n'},
        {"priority",     required_argument, 0, 'p'},
        {"fifo",      required_argument, 0, 'f'},
        {"startup",   required_argument, 0, 's'},
        {0, 0, 0, 0}
    };



    data.fifoON = 0; // default

    while (1)
    {
        c = getopt_long (argc, argv, "hioed:m:n:f:s:",
                         long_options, &option_index);

        /* Detect the end of the options. */
        if (c == -1)
            break;

        switch (c)
        {
        case 0:
            /* If this option set a flag, do nothing else now. */
            if (long_options[option_index].flag != 0)
                break;
            printf ("option %s", long_options[option_index].name);
            if (optarg)
                printf (" with arg %s", optarg);
            printf ("\n");
            break;

        case 'h':
            help();
            exit(0);
            break;

        case 'i':
            printInfo();
            exit(0);
            break;

        case 'd':
            data.Debug = atoi(optarg);
            printf ("Debug = %d\n", data.Debug);
            break;

        case 'o':
            puts ("CAUTION - WILL OVERWRITE EXISTING FITS FILES\n");
            data.overwrite = 1;
            break;

        case 'e':
            printf("Idle mode: only runs process when X is idle (pid %ld)\n", (long) getpid());
            sprintf(command, "runidle %ld > /dev/null &\n", (long) getpid());
            r = system(command);
            break;
            
        case 'm':
            printf("Starting memory monitor on '%s'\n", optarg);
            memory_monitor(optarg);
            break;

        case 'n':
            printf("process name '%s'\n", optarg);
            strcpy(data.processname, optarg);
            memcpy((void *)argv[0], optarg, sizeof(optarg));
#ifdef __linux__
     prctl(PR_SET_NAME, optarg, 0, 0, 0);
#elif defined(HAVE_PTHREAD_SETNAME_NP) && defined(OS_IS_DARWIN)
    pthread_setname_np(optarg);
#endif
//            prctl(PR_SET_NAME, optarg, 0, 0, 0);
            break;

        case 'p':
            schedpar.sched_priority = atoi(optarg);
            #ifndef __MACH__
            r = seteuid(euid_called); //This goes up to maximum privileges
            sched_setscheduler(0, SCHED_FIFO, &schedpar); //other option is SCHED_RR, might be faster
            r = seteuid(euid_real);//Go back to normal privileges
            #endif
            break;

        case 'f':
            printf("using input fifo '%s'\n", optarg);
            data.fifoON = 1;
            strcpy(data.fifoname, optarg);
            printf("FIFO NAME = %s\n", data.fifoname);
            break;

        case 's':
            strcpy(CLIstartupfilename, optarg);
            printf("Startup file : %s\n", CLIstartupfilename);
            break;

        case '?':
            /* getopt_long already printed an error message. */
            break;

        default:
            abort ();
        }
    }


    // fprintf(stdout, "Object directory:        %s\n", OBJDIR);
    //fprintf(stdout, "Source directory:        %s\n", SOURCEDIR);
    //fprintf(stdout, "Documentation directory: %s\n", DOCDIR);

    //	  sprintf(command,"more %s/help.txt",DOCDIR);


    return 0;

}
Exemplo n.º 12
0
void * Queue3Thread( void * v )
{
	int result = pthread_setname_np( pthread_self(), "FileQueue3" );
	if ( result != 0 )
	{
		LOG( "InitFileQueue: pthread_setname_np failed %s", strerror( result ) );
	}

	// Process incoming messages until queue is empty
	for ( ; ; )
	{
		Queue3.SleepUntilMessage();
		const char * msg = Queue3.GetNextMessage();

		LOG( "Queue3 msg = '%s'", msg );

		// Note that Queue3 has cleared the message
		pthread_mutex_lock( &QueueMutex );
		QueueHasCleared = true;
		pthread_cond_signal( &QueueWake );
		pthread_mutex_unlock( &QueueMutex );

		char commandName[1024] = {};
		sscanf( msg, "%s", commandName );
		int numBuffers = strcmp( commandName, "cube" ) == 0 ? 6 : 1;
		unsigned * b[6] = {};
		int blen[6];
		if ( numBuffers == 1 )
		{
			sscanf( msg, "%s %p %i", commandName, &b[0], &blen[0] );
		}
		else
		{
			OVR_ASSERT( numBuffers == 6 );		
			sscanf( msg, "%s %p %i %p %i %p %i %p %i %p %i %p %i ", commandName,
					&b[0], &blen[0],
					&b[1], &blen[1],
					&b[2], &blen[2],
					&b[3], &blen[3],
					&b[4], &blen[4],
					&b[5], &blen[5] );
		}

#define USE_TURBO_JPEG
#if !defined( USE_TURBO_JPEG )
		stbi_uc * data[6];
#else
		unsigned char * data[6];
#endif

		int resolutionX = 0;
		int resolutionY = 0;
		int buffCount = 0;
		for ( ; buffCount < numBuffers; buffCount++ )
		{
			int	x, y;
			unsigned * b1 = b[buffCount];
			int b1len = blen[buffCount];

#if !defined( USE_TURBO_JPEG )
			int comp;
			data[buffCount] = stbi_load_from_memory( (const stbi_uc*)b1, b1len, &x, &y, &comp, 4 );
#else
			data[buffCount] = TurboJpegLoadFromMemory( (unsigned char*)b1, b1len, &x, &y );
#endif
			if ( buffCount == 0 )
			{
				resolutionX = x;
				resolutionY = y;
			}

			// done with the loading buffer now
			free( b1 );

			if ( data[buffCount] == NULL )
			{
				LOG( "LoadingThread: failed to load from buffer" );
				break;
			}
		}

		if ( buffCount != numBuffers )	// an image load failed, free everything and abort this load
		{
			for ( int i = 0; i < numBuffers; ++i )
			{
				free( data[i] );
				data[i] = NULL;
			}
		}
		else
		{
			if ( numBuffers == 1 )
			{
				OVR_ASSERT( data[0] != NULL );
				LOG( "Queue3.PostPrintf( \"%s %p %i %i\" )", commandName, data[0], resolutionX, resolutionY );
				( ( Oculus360Photos * )v )->GetBGMessageQueue( ).PostPrintf( "%s %p %i %i", commandName, data[ 0 ], resolutionX, resolutionY );
			}
			else 
			{
				OVR_ASSERT( numBuffers == 6 );
				LOG( "Queue3.PostPrintf( \"%s %i %p %p %p %p %p %p\" )", commandName, resolutionX, 
						data[0], data[1], data[2], data[3], data[4], data[5] );
				( ( Oculus360Photos * )v )->GetBGMessageQueue( ).PostPrintf( "%s %i %p %p %p %p %p %p", commandName, resolutionX,
						data[0], data[1], data[2], data[3], data[4], data[5] );
			}
		}

		free( (void *)msg );
	}
	return NULL;
}
Exemplo n.º 13
0
static int midoflus_init(void *arg)
{
    int ret;
    char *sfont;
    char *def_sfonts[] = {
	"/usr/share/soundfonts/default.sf2",		// fedora
	"/usr/share/soundfonts/FluidR3_GM.sf2",		// fedora
	"/usr/share/sounds/sf2/FluidR3_GM.sf2.flac",	// ubuntu
	"/usr/share/sounds/sf2/FluidR3_GM.sf2",		// debian
	NULL };
    int use_defsf = 0;

    settings = new_fluid_settings();
    fluid_settings_setint(settings, "synth.lock-memory", 0);
    fluid_settings_setnum(settings, "synth.gain", flus_gain);
    ret = fluid_settings_setint(settings, "synth.threadsafe-api", 1);
    if (ret == 0) {
	warn("fluidsynth: no threadsafe API\n");
	goto err1;
    }
    ret = fluid_settings_getnum(settings, "synth.sample-rate", &flus_srate);
    if (ret == 0) {
	warn("fluidsynth: cannot get samplerate\n");
	goto err1;
    }
    ret = fluid_settings_getstr(settings, "synth.default-soundfont", &sfont);
    if (ret == 0) {
	int i = 0;
	warn("Your fluidsynth is too old\n");
	while (def_sfonts[i]) {
	    if (access(def_sfonts[i], R_OK) == 0) {
		sfont = def_sfonts[i];
		use_defsf = 1;
		break;
	    }
	    i++;
	}
	if (!use_defsf) {
	    error("Your fluidsynth is too old and soundfonts not found\n");
	    goto err1;
	}
    }

    synth = new_fluid_synth(settings);
    ret = fluid_synth_sfload(synth, sfont, TRUE);
    if (ret == FLUID_FAILED) {
	warn("fluidsynth: cannot load soundfont %s\n", sfont);
	if (use_defsf)
	    error("Your fluidsynth is too old\n");
	goto err2;
    }
    fluid_settings_setstr(settings, "synth.midi-bank-select", "gm");
    S_printf("fluidsynth: loaded soundfont %s ID=%i\n", sfont, ret);
    sequencer = new_fluid_sequencer2(0);
    synthSeqID = fluid_sequencer_register_fluidsynth2(sequencer, synth);

    sem_init(&syn_sem, 0, 0);
    pthread_create(&syn_thr, NULL, synth_thread, NULL);
#ifdef HAVE_PTHREAD_SETNAME_NP
    pthread_setname_np(syn_thr, "dosemu: fluid");
#endif
    pcm_stream = pcm_allocate_stream(FLUS_CHANNELS, "MIDI",
	    (void*)MC_MIDI);

    return 1;

err2:
    delete_fluid_synth(synth);
err1:
    delete_fluid_settings(settings);
    return 0;
}
Exemplo n.º 14
0
void *
invoke_listener(void * /*arg*/) 
{
    //
    //  Setup to wait for a client to connect
    //
    pthread_t thisThread = pthread_self();
    network::CHEC chec = network::EC_NONE;

    int err = 0;

    err = pthread_setname_np(thisThread, "vogl_listen");
    if (0 != err)
    {
        syslog(VOGL_ERROR, "%s:%d %s Unable to set the name of the thread. returned %d, errno %d\n", __FILE__, __LINE__, __func__, err, errno);
    }

    syslog(VOGL_INFO, "Listener for VOGL Tracing in operation...\n");

    g_clientChannelMgr = new network::channelmgr();
    if (NULL == g_clientChannelMgr)
    {
        syslog(VOGL_ERROR, "%s:%d %s Unable to allocation networking channelmgr.  OOM?\n", __FILE__, __LINE__, __func__);
        return NULL;
    }

    //  Create a client channel
    chec = g_clientChannelMgr->Connect( const_cast<char *>("localhost"), g_vogl_traceport, (SENDASYNC|RECVASYNC), process_trace_command, NULL );
    //chec = g_clientChannelMgr->Accept( g_vogl_traceport, (RECVASYNC|SENDASYNC), true,  process_trace_command, NULL, NULL, NULL );
    if (network::EC_NONE != chec)
    {
        syslog(VOGL_ERROR, "%s:%d %s Unable to connect on port %d\nExiting.\n", __FILE__, __LINE__, __func__, g_vogl_traceport);
        return NULL;
    }

    //
    //  Tell the client we're up and running.
    send_status_to_client("Game is up and running.");

    //
    //  Start capturing output from the tracer
    vogl::console::add_console_output_func(log_output_func, NULL);

    while (true)
    {
        if (g_fKillApp)
        {
            break;
        }
        sleep(1);  //  Don't busy spin...
    }

    if (g_fKillApp)
    {
        syslog(VOGL_INFO, "%lx: VOGL Tracing server thread: Terminating the application.\n", thisThread);
        kill(getpid(), SIGTERM); // SIGINT);
    }

    syslog(VOGL_INFO, "%lx: VOGL Tracing server thread: Terminating.\n", thisThread);

    return NULL;
}
Exemplo n.º 15
0
Arquivo: main.c Projeto: aosm/gdb
static int
captured_main (void *data)
{
  /* If you add initializations here, you also need to add then to the
     proc do_steps_and_nexts in selftest.exp.  */
  struct captured_main_args *context = data;
  int argc = context->argc;
  char **argv = context->argv;
  int count;
  static int quiet = 0;
  static int batch = 0;
  static int set_args = 0;

  /* Pointers to various arguments from command line.  */
  char *symarg = NULL;
  char *execarg = NULL;
  char *corearg = NULL;
  char *cdarg = NULL;
  char *ttyarg = NULL;
  /* APPLE LOCAL: Set the osabi via option.  */
  char *osabiarg = NULL;  


  /* These are static so that we can take their address in an initializer.  */
  static int print_help;
  static int print_version;

  /* Pointers to all arguments of --command option.  */
  char **cmdarg;
  /* Allocated size of cmdarg.  */
  int cmdsize;
  /* Number of elements of cmdarg used.  */
  int ncmd;

  /* Indices of all arguments of --directory option.  */
  char **dirarg;
  /* Allocated size.  */
  int dirsize;
  /* Number of elements used.  */
  int ndir;

  /* APPLE LOCAL globalbuf */
  struct stat homebuf, cwdbuf, globalbuf;
  char *homedir;
  /* APPLE LOCAL attach -waitfor */
  char *attach_waitfor = NULL;
  /* APPLE LOCAL: set the architecture.  */
  char *initial_arch = NULL;

  int i;

  long time_at_startup = get_run_time ();

#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
  setlocale (LC_MESSAGES, "");
#endif
#if defined (HAVE_SETLOCALE)
  setlocale (LC_CTYPE, "");
#endif
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  /* APPLE LOCAL memory */
#ifdef USE_MMALLOC
  init_mmalloc_default_pool ((PTR) NULL);
#endif
 
  /* This needs to happen before the first use of malloc.  */
  init_malloc (NULL);

#ifdef HAVE_SBRK
  lim_at_start = (char *) sbrk (0);
#endif

#if defined (ALIGN_STACK_ON_STARTUP)
  i = (int) &count & 0x3;
  if (i != 0)
    alloca (4 - i);
#endif

  cmdsize = 1;
  cmdarg = (char **) xmalloc (cmdsize * sizeof (*cmdarg));
  ncmd = 0;
  dirsize = 1;
  dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
  ndir = 0;

  quit_flag = 0;
  line = (char *) xmalloc (linesize);
  line[0] = '\0';		/* Terminate saved (now empty) cmd line */
  instream = stdin;

  getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
  current_directory = gdb_dirbuf;

  /* APPLE LOCAL gdb_null */
  gdb_null = ui_file_new ();
  gdb_stdout = stdio_fileopen (stdout);
  gdb_stderr = stdio_fileopen (stderr);
  gdb_stdlog = gdb_stderr;	/* for moment */
  gdb_stdtarg = gdb_stderr;	/* for moment */
  gdb_stdin = stdio_fileopen (stdin);
  gdb_stdtargerr = gdb_stderr;	/* for moment */
  gdb_stdtargin = gdb_stdin;	/* for moment */

  /* APPLE LOCAL: set our main thread's name */
#ifdef HAVE_PTHREAD_SETNAME_NP
  pthread_setname_np ("gdb main thread");
#endif

  /* Set the sysroot path.  */
#ifdef TARGET_SYSTEM_ROOT_RELOCATABLE
  gdb_sysroot = make_relative_prefix (argv[0], BINDIR, TARGET_SYSTEM_ROOT);
  if (gdb_sysroot)
    {
      struct stat s;
      int res = 0;

      if (stat (gdb_sysroot, &s) == 0)
	if (S_ISDIR (s.st_mode))
	  res = 1;

      if (res == 0)
	{
	  xfree (gdb_sysroot);
	  gdb_sysroot = TARGET_SYSTEM_ROOT;
	}
    }
  else
    gdb_sysroot = TARGET_SYSTEM_ROOT;
#else
#if defined (TARGET_SYSTEM_ROOT)
  gdb_sysroot = TARGET_SYSTEM_ROOT;
#else
  gdb_sysroot = "";
#endif
#endif

  /* There will always be an interpreter.  Either the one passed into
     this captured main, or one specified by the user at start up, or
     the console.  Initialize the interpreter to the one requested by 
     the application.  */
  interpreter_p = xstrdup (context->interpreter_p);

  /* Parse arguments and options.  */
  {
    int c;
    /* When var field is 0, use flag field to record the equivalent
       short option (or arbitrary numbers starting at 10 for those
       with no equivalent).  */
    enum {
      OPT_SE = 10,
      OPT_CD,
      OPT_ANNOTATE,
      OPT_STATISTICS,
      OPT_TUI,
      OPT_NOWINDOWS,
      OPT_WINDOWS,
      OPT_WAITFOR,  /* APPLE LOCAL */
      OPT_ARCH,     /* APPLE LOCAL */
      OPT_OSABI	    /* APPLE LOCAL */
    };
    static struct option long_options[] =
    {
#if defined(TUI)
      {"tui", no_argument, 0, OPT_TUI},
#endif
      {"xdb", no_argument, &xdb_commands, 1},
      {"dbx", no_argument, &dbx_commands, 1},
      {"readnow", no_argument, &readnow_symbol_files, 1},
      {"r", no_argument, &readnow_symbol_files, 1},
      {"quiet", no_argument, &quiet, 1},
      {"q", no_argument, &quiet, 1},
      {"silent", no_argument, &quiet, 1},
      {"nx", no_argument, &inhibit_gdbinit, 1},
      {"n", no_argument, &inhibit_gdbinit, 1},
      {"batch", no_argument, &batch, 1},
      {"epoch", no_argument, &epoch_interface, 1},

    /* This is a synonym for "--annotate=1".  --annotate is now preferred,
       but keep this here for a long time because people will be running
       emacses which use --fullname.  */
      {"fullname", no_argument, 0, 'f'},
      {"f", no_argument, 0, 'f'},

      {"annotate", required_argument, 0, OPT_ANNOTATE},
      {"help", no_argument, &print_help, 1},
      {"se", required_argument, 0, OPT_SE},
      {"symbols", required_argument, 0, 's'},
      {"s", required_argument, 0, 's'},
      {"exec", required_argument, 0, 'e'},
      {"e", required_argument, 0, 'e'},
      {"core", required_argument, 0, 'c'},
      {"c", required_argument, 0, 'c'},
      {"pid", required_argument, 0, 'p'},
      {"p", required_argument, 0, 'p'},
      {"command", required_argument, 0, 'x'},
      {"version", no_argument, &print_version, 1},
      {"x", required_argument, 0, 'x'},
#ifdef GDBTK
      {"tclcommand", required_argument, 0, 'z'},
      {"enable-external-editor", no_argument, 0, 'y'},
      {"editor-command", required_argument, 0, 'w'},
#endif
      {"ui", required_argument, 0, 'i'},
      {"interpreter", required_argument, 0, 'i'},
      {"i", required_argument, 0, 'i'},
      {"directory", required_argument, 0, 'd'},
      {"d", required_argument, 0, 'd'},
      {"cd", required_argument, 0, OPT_CD},
      {"tty", required_argument, 0, 't'},
      {"baud", required_argument, 0, 'b'},
      {"b", required_argument, 0, 'b'},
      {"nw", no_argument, NULL, OPT_NOWINDOWS},
      {"nowindows", no_argument, NULL, OPT_NOWINDOWS},
      {"w", no_argument, NULL, OPT_WINDOWS},
      {"windows", no_argument, NULL, OPT_WINDOWS},
      {"statistics", no_argument, 0, OPT_STATISTICS},
      {"write", no_argument, &write_files, 1},
      {"args", no_argument, &set_args, 1},
/* APPLE LOCAL: */
      {"waitfor", required_argument, 0, OPT_WAITFOR},
/* APPLE LOCAL: */
      {"arch", required_argument, 0, OPT_ARCH},
/* APPLE LOCAL: */
      {"osabi", required_argument, 0, OPT_OSABI},
      {"l", required_argument, 0, 'l'},
      {0, no_argument, 0, 0}
    };

    while (1)
      {
	int option_index;

	c = getopt_long_only (argc, argv, "",
			      long_options, &option_index);
	if (c == EOF || set_args)
	  break;

	/* Long option that takes an argument.  */
	if (c == 0 && long_options[option_index].flag == 0)
	  c = long_options[option_index].val;

	switch (c)
	  {
	  case 0:
	    /* Long option that just sets a flag.  */
	    break;
	  case OPT_SE:
	    symarg = optarg;
	    execarg = optarg;
	    break;
	  case OPT_CD:
	    cdarg = optarg;
	    break;
	  case OPT_ANNOTATE:
	    /* FIXME: what if the syntax is wrong (e.g. not digits)?  */
	    annotation_level = atoi (optarg);
	    break;
	  case OPT_STATISTICS:
	    /* Enable the display of both time and space usage.  */
	    display_time = 1;
	    display_space = 1;
	    break;
	  case OPT_TUI:
	    /* --tui is equivalent to -i=tui.  */
	    xfree (interpreter_p);
	    interpreter_p = xstrdup ("tui");
	    break;
	  case OPT_WINDOWS:
	    /* FIXME: cagney/2003-03-01: Not sure if this option is
               actually useful, and if it is, what it should do.  */
	    use_windows = 1;
	    break;
	  case OPT_NOWINDOWS:
	    /* -nw is equivalent to -i=console.  */
	    xfree (interpreter_p);
	    interpreter_p = xstrdup (INTERP_CONSOLE);
	    use_windows = 0;
	    break;
	  /* APPLE LOCAL: */
	  case OPT_WAITFOR:
	    attach_waitfor = (char *) xmalloc (12 + strlen (optarg));
	    sprintf (attach_waitfor, "-waitfor \"%s\"", optarg);
	    break;
	  /* APPLE LOCAL: */
	  case OPT_ARCH:
	    initial_arch = xstrdup (optarg);
	    break;
	  /* APPLE LOCAL: Set the osabi via option. This option was 
	     added along with a modification to the gdb driver shell script
	     for armv6. Binaries with the "arm" architecture (ARM v4T)
	     and "armv6" (ARM v6) can be inter mixed on armv6 capaable 
	     targets since all instructions in the ARM v4T instruction set
	     are present in the ARM v6 instruction set. The same gdb
	     executable is used for both, and the osabi set/show variable
	     controls which gets used for cross targets. We need to set this
	     variable prior to loading any executables so that the correct
	     slice of a fat file can be selected. Now gdb can be launched
	     with the "armv6" arch along with an executable and the correct
	     slice will be selected:
	     gdb -arch armv6 <file>  */
	  case OPT_OSABI:
	    osabiarg = optarg;
	    break;
	  /* APPLE LOCAL END */
	  case 'f':
	    annotation_level = 1;
/* We have probably been invoked from emacs.  Disable window interface.  */
	    use_windows = 0;
	    break;
	  case 's':
	    symarg = optarg;
	    break;
	  case 'e':
	    execarg = optarg;
	    break;
	  case 'c':
	    corearg = optarg;
	    break;
	  case 'p':
	    /* "corearg" is shared by "--core" and "--pid" */
	    corearg = optarg;
	    break;
	  case 'x':
	    cmdarg[ncmd++] = optarg;
	    if (ncmd >= cmdsize)
	      {
		cmdsize *= 2;
		cmdarg = (char **) xrealloc ((char *) cmdarg,
					     cmdsize * sizeof (*cmdarg));
	      }
	    break;
#ifdef GDBTK
	  case 'z':
	    {
extern int gdbtk_test (char *);
	      if (!gdbtk_test (optarg))
		{
		  fprintf_unfiltered (gdb_stderr, _("%s: unable to load tclcommand file \"%s\""),
				      argv[0], optarg);
		  exit (1);
		}
	      break;
	    }
	  case 'y':
	    /* Backwards compatibility only.  */
	    break;
	  case 'w':
	    {
	      external_editor_command = xstrdup (optarg);
	      break;
	    }
#endif /* GDBTK */
	  case 'i':
	    xfree (interpreter_p);
	    interpreter_p = xstrdup (optarg);
	    break;
	  case 'd':
	    dirarg[ndir++] = optarg;
	    if (ndir >= dirsize)
	      {
		dirsize *= 2;
		dirarg = (char **) xrealloc ((char *) dirarg,
					     dirsize * sizeof (*dirarg));
	      }
	    break;
	  case 't':
	    ttyarg = optarg;
	    break;
	  case 'q':
	    quiet = 1;
	    break;
	  case 'b':
	    {
	      int i;
	      char *p;

	      i = strtol (optarg, &p, 0);
	      if (i == 0 && p == optarg)

		/* Don't use *_filtered or warning() (which relies on
		   current_target) until after initialize_all_files(). */

		fprintf_unfiltered
		  (gdb_stderr,
		   _("warning: could not set baud rate to `%s'.\n"), optarg);
	      else
		baud_rate = i;
	    }
            break;
	  case 'l':
	    {
	      int i;
	      char *p;

	      i = strtol (optarg, &p, 0);
	      if (i == 0 && p == optarg)

		/* Don't use *_filtered or warning() (which relies on
		   current_target) until after initialize_all_files(). */

		fprintf_unfiltered
		  (gdb_stderr,
		 _("warning: could not set timeout limit to `%s'.\n"), optarg);
	      else
		remote_timeout = i;
	    }
	    break;

	  case '?':
	    fprintf_unfiltered (gdb_stderr,
			_("Use `%s --help' for a complete list of options.\n"),
				argv[0]);
	    exit (1);
	  }
      }

    /* If --help or --version, disable window interface.  */
    if (print_help || print_version)
      {
	use_windows = 0;
      }

    if (set_args)
      {
	/* The remaining options are the command-line options for the
	   inferior.  The first one is the sym/exec file, and the rest
	   are arguments.  */
	if (optind >= argc)
	  {
	    fprintf_unfiltered (gdb_stderr,
				_("%s: `--args' specified but no program specified\n"),
				argv[0]);
	    exit (1);
	  }
	symarg = argv[optind];
	execarg = argv[optind];
	++optind;
	set_inferior_args_vector (argc - optind, &argv[optind]);
      }
    else
      {
	/* OK, that's all the options.  The other arguments are filenames.  */
	count = 0;
	for (; optind < argc; optind++)
	  switch (++count)
	    {
	    case 1:
	      symarg = argv[optind];
	      execarg = argv[optind];
	      break;
	    case 2:
	      /* The documentation says this can be a "ProcID" as well. 
	         We will try it as both a corefile and a pid.  */
	      corearg = argv[optind];
	      break;
	    case 3:
	      fprintf_unfiltered (gdb_stderr,
				  _("Excess command line arguments ignored. (%s%s)\n"),
				  argv[optind], (optind == argc - 1) ? "" : " ...");
	      break;
	    }
      }
    if (batch)
      quiet = 1;
  }

  /* Initialize all files.  Give the interpreter a chance to take
     control of the console via the deprecated_init_ui_hook ().  */
  gdb_init (argv[0]);

  /* Do these (and anything which might call wrap_here or *_filtered)
     after initialize_all_files() but before the interpreter has been
     installed.  Otherwize the help/version messages will be eaten by
     the interpreter's output handler.  */

  if (print_version)
    {
      print_gdb_version (gdb_stdout);
      wrap_here ("");
      printf_filtered ("\n");
      exit (0);
    }

  if (print_help)
    {
      print_gdb_help (gdb_stdout);
      fputs_unfiltered ("\n", gdb_stdout);
      exit (0);
    }

  /* FIXME: cagney/2003-02-03: The big hack (part 1 of 2) that lets
     GDB retain the old MI1 interpreter startup behavior.  Output the
     copyright message before the interpreter is installed.  That way
     it isn't encapsulated in MI output.  */
  if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0)
    {
      /* APPLE LOCAL begin don't print dots */
      /* Print all the junk at the top. */
      print_gdb_version (gdb_stdout);
      printf_filtered ("\n");
      /* APPLE LOCAL end don't print dots */
      wrap_here ("");
      gdb_flush (gdb_stdout);	/* Force to screen during slow operations */
    }


  /* APPLE LOCAL begin */
  if (state_change_hook)
    {
      state_change_hook (STATE_ACTIVE);
    }
  /* APPLE LOCAL end */
  
  /* Install the default UI.  All the interpreters should have had a
     look at things by now.  Initialize the default interpreter. */

  {
    /* Find it.  */
    struct interp *interp = interp_lookup (interpreter_p);
    if (interp == NULL)
      error (_("Interpreter `%s' unrecognized"), interpreter_p);
    /* Install it.  */
    /* APPLE LOCAL clarity */
    if (interp_set (interp) == NULL)
      {
        fprintf_unfiltered (gdb_stderr,
			    "Interpreter `%s' failed to initialize.\n",
                            interpreter_p);
        exit (1);
      }
  }

  /* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
     GDB retain the old MI1 interpreter startup behavior.  Output the
     copyright message after the interpreter is installed when it is
     any sane interpreter.  */
  if (!quiet && !current_interp_named_p (INTERP_MI1))
    {
      /* Print all the junk at the top, with trailing "..." if we are about
         to read a symbol file (possibly slowly).  */
      print_gdb_version (gdb_stdout);
      if (symarg)
	printf_filtered ("..");
      wrap_here ("");
      gdb_flush (gdb_stdout);	/* Force to screen during slow operations */
    }

  error_pre_print = "\n\n";
  quit_pre_print = error_pre_print;

  /* We may get more than one warning, don't double space all of them... */
  warning_pre_print = _("\nwarning: ");

  /* APPLE LOCAL begin move inits up */
  /* Make sure that they are zero in case one of them fails (this
     guarantees that they won't match if either exists).  */
  
  memset (&homebuf, 0, sizeof (struct stat));
  memset (&cwdbuf, 0, sizeof (struct stat));
  /* APPLE LOCAL end move inits up */
  /* APPLE LOCAL begin global gdbinit */
  memset (&globalbuf, 0, sizeof (struct stat));
  stat (gdbinit_global, &globalbuf);
  if (!inhibit_gdbinit)
    {
      /* if (!SET_TOP_LEVEL ()) */
	 source_file (gdbinit_global, 0);
    }
  do_cleanups (ALL_CLEANUPS);
  /* APPLE LOCAL end global gdbinit */
 
  /* APPLE LOCAL: Set the $_Xcode convenience variable at '0' before sourcing
     any .gdbinit files.  Xcode will override this to 1 when it is launching
     gdb but we need to start with a value of 0 so .gdbinit files can use it 
     in conditional expressions.  */
  set_internalvar (lookup_internalvar ("_Xcode"),
                   value_from_longest (builtin_type_int, (LONGEST) 0));

  /* Read and execute $HOME/.gdbinit file, if it exists.  This is done
     *before* all the command line arguments are processed; it sets
     global parameters, which are independent of what file you are
     debugging or what directory you are in.  */
  homedir = getenv ("HOME");
  if (homedir)
    {
      char *homeinit = xstrprintf ("%s/%s", homedir, gdbinit);

      /* APPLE LOCAL move inits up */
      stat (homeinit, &homebuf);
      /* APPLE LOCAL gdbinit */
      if (!inhibit_gdbinit)
	if ((globalbuf.st_dev != homebuf.st_dev) || (globalbuf.st_ino != homebuf.st_ino))
	  {
	    catch_command_errors (source_file, homeinit, 0, RETURN_MASK_ALL);
	  }
    }

  /* Now perform all the actions indicated by the arguments.  */
  if (cdarg != NULL)
    {
      catch_command_errors (cd_command, cdarg, 0, RETURN_MASK_ALL);
    }

  for (i = 0; i < ndir; i++)
    catch_command_errors (directory_command, dirarg[i], 0, RETURN_MASK_ALL);
  xfree (dirarg);

  /* APPLE LOCAL: If an architecture has been supplied, process it. 
     FIXME: Note, this is a TOTAL hack.  There should be some gdbarch'y type
     function that processes these options.  The odd thing is that you would
     want the SAME function for all the gdbarch'es that are registered, so
     it actually lives a little above the gdbarch....  
     Not sure how to do that.  So instead, I just hack...  */
#if defined (USE_POSIX_SPAWN) || defined (USE_ARCH_FOR_EXEC)
  if (initial_arch != NULL)
    {
      char *arch_string = NULL;
      char *osabi_string;
#if defined (TARGET_POWERPC)
      if (strcmp (initial_arch, "ppc") == 0)
	{
	  arch_string = "powerpc:common";
	  osabi_string = "Darwin";
	}
      else if (strcmp (initial_arch, "ppc64") == 0)
	{
	  arch_string = "powerpc:common64";
	  osabi_string = "Darwin64";
	}
      else
	  warning ("invalid argument \"%s\" for \"--arch\", should be one of "
		 "\"ppc\" or \"ppc64\"\n", initial_arch);
#elif defined (TARGET_I386)
      if (strcmp (initial_arch, "i386") == 0)
	{
	  arch_string = "i386";
	  osabi_string = "Darwin";
	}
      else if (strcmp (initial_arch, "x86_64") == 0)
	{
	  arch_string = "i386:x86-64";
	  osabi_string = "Darwin64";
	}
      else
	warning ("invalid argument \"%s\" for \"--arch\", should be one of "
		 "\"i386\" or \"x86_64\"\n", initial_arch);
#elif defined (TARGET_ARM)
      if (strcmp (initial_arch, "arm") == 0)
	{
	  arch_string = "arm";
	  osabi_string = "Darwin";
	}
      else if (strcmp (initial_arch, "armv6") == 0)
	{
	  arch_string = "armv6";
	  osabi_string = "DarwinV6";
	}
      else
	warning ("invalid argument \"%s\" for \"--arch\", should be one of "
		 "\"armv\" or \"armv6\"\n", initial_arch);
#endif
      if (arch_string != NULL)
	{
	  set_architecture_from_string (arch_string);
	  set_osabi_from_string (osabi_string);
	}
    }
#else
  warning ("--arch option not supported in this gdb.");
#endif

  /* APPLE LOCAL BEGIN: Set the osabi via option.  */
  if (osabiarg != NULL)
    set_osabi_option (osabiarg);
  /* APPLE LOCAL END */

  if (execarg != NULL
      && symarg != NULL
      && strcmp (execarg, symarg) == 0)
    {
      /* The exec file and the symbol-file are the same.  If we can't
         open it, better only print one error message.
         catch_command_errors returns non-zero on success! */
      if (catch_command_errors (exec_file_attach, execarg, !batch, RETURN_MASK_ALL))
	catch_command_errors (symbol_file_add_main, symarg, 0, RETURN_MASK_ALL);
    }
  else
    {
      if (execarg != NULL)
	catch_command_errors (exec_file_attach, execarg, !batch, RETURN_MASK_ALL);
      if (symarg != NULL)
	catch_command_errors (symbol_file_add_main, symarg, 0, RETURN_MASK_ALL);
    }

  /* APPLE LOCAL begin */
  if (state_change_hook && symarg != NULL)
    {
      state_change_hook (STATE_INFERIOR_LOADED);
    }
  /* APPLE LOCAL end */
  
  /* APPLE LOCAL begin */
  if (attach_waitfor != NULL)
    {
      printf_filtered ("\n");
      catch_command_errors (attach_command, attach_waitfor, 0, RETURN_MASK_ALL);
    }
    
  /* After the symbol file has been read, print a newline to get us
     beyond the copyright line...  But errors should still set off
     the error message with a (single) blank line.  */
  if (!quiet)
    printf_filtered ("\n");
  error_pre_print = "\n";
  quit_pre_print = error_pre_print;
  warning_pre_print = _("\nwarning: ");

  if (corearg != NULL)
    {
      if (catch_command_errors (core_file_attach, corearg, !batch, RETURN_MASK_ALL) == 0)
	{
	  /* See if the core file is really a PID. */
	  /* Be careful, we have quoted the corearg above... */
	  if (corearg[0] == '"')
	    {
	      int len = strlen (corearg);
	      if (corearg[len - 1] == '"')
		{
		  corearg[len - 1] = '\0';
		  corearg += 1;
		}
	    }

	  if (isdigit (corearg[0]))
	    catch_command_errors (attach_command, corearg, !batch, RETURN_MASK_ALL);
	}
    }

  if (ttyarg != NULL)
    catch_command_errors (tty_command, ttyarg, !batch, RETURN_MASK_ALL);

  /* Error messages should no longer be distinguished with extra output. */
  error_pre_print = NULL;
  quit_pre_print = NULL;
  warning_pre_print = _("warning: ");

  /* Read the .gdbinit file in the current directory, *if* it isn't
     the same as the $HOME/.gdbinit file (it should exist, also).  */

  stat (gdbinit, &cwdbuf);
  if (!inhibit_gdbinit)
    if (((globalbuf.st_dev != cwdbuf.st_dev) || (globalbuf.st_ino != cwdbuf.st_ino))
	&& ((homebuf.st_dev != cwdbuf.st_dev) || (homebuf.st_ino != cwdbuf.st_ino)))
      {
        /* APPLE LOCAL: fix for CVE-2005-1705 */
        if (cwdbuf.st_uid == getuid ())
	  catch_command_errors (source_file, gdbinit, 0, RETURN_MASK_ALL);
      }
  
  /* These need to be set this late in the initialization to ensure that
     they are defined for the current environment.  They define the
     radix variables needed by a save-breakpoints file to preserve the
     radix across the breakpoints restoration assuming they are restored
     using the -x (-command) command line options.  */
     
  set_internalvar (lookup_internalvar ("input_radix"),
		   value_from_longest (builtin_type_int, (LONGEST) input_radix));
  set_internalvar (lookup_internalvar ("output_radix"),
		   value_from_longest (builtin_type_int, (LONGEST) output_radix));

  for (i = 0; i < ncmd; i++)
    {
#if 0
      /* NOTE: cagney/1999-11-03: SET_TOP_LEVEL() was a macro that
         expanded into a call to setjmp().  */
      if (!SET_TOP_LEVEL ()) /* NB: This is #if 0'd out */
	{
	  /* NOTE: I am commenting this out, because it is not clear
	     where this feature is used. It is very old and
	     undocumented. ezannoni: 1999-05-04 */
#if 0
	  if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0')
	    read_command_file (stdin);
	  else
#endif
	    source_file (cmdarg[i], !batch);
	  do_cleanups (ALL_CLEANUPS);
	}
#endif
      catch_command_errors (source_file, cmdarg[i], !batch, RETURN_MASK_ALL);
    }
  xfree (cmdarg);

  /* Read in the old history after all the command files have been read. */
  init_history ();

  if (batch)
    {
      if (attach_flag)
	/* Either there was a problem executing the command in the
	   batch file aborted early, or the batch file forgot to do an
	   explicit detach.  Explicitly detach the inferior ensuring
	   that there are no zombies.  */
	target_detach (NULL, 0);
      
      /* We have hit the end of the batch file.  */
      exit (0);
    }

  /* Do any host- or target-specific hacks.  This is used for i960 targets
     to force the user to set a nindy target and spec its parameters.  */

#ifdef BEFORE_MAIN_LOOP_HOOK
  BEFORE_MAIN_LOOP_HOOK;
#endif

  /* Show time and/or space usage.  */

  if (display_time)
    {
      long init_time = get_run_time () - time_at_startup;

      printf_unfiltered (_("Startup time: %ld.%06ld\n"),
			 init_time / 1000000, init_time % 1000000);
    }

  if (display_space)
    {
#ifdef HAVE_SBRK
      extern char **environ;
      char *lim = (char *) sbrk (0);

      printf_unfiltered (_("Startup size: data size %ld\n"),
			 (long) (lim - (char *) &environ));
#endif
    }

#if 0
  /* FIXME: cagney/1999-11-06: The original main loop was like: */
  while (1)
    {
      if (!SET_TOP_LEVEL ())
	{
	  do_cleanups (ALL_CLEANUPS);	/* Do complete cleanup */
	  /* GUIs generally have their own command loop, mainloop, or
	     whatever.  This is a good place to gain control because
	     many error conditions will end up here via longjmp().  */
	  if (deprecated_command_loop_hook)
	    deprecated_command_loop_hook ();
	  else
	    deprecated_command_loop ();
	  quit_command ((char *) 0, instream == stdin);
	}
    }
  /* NOTE: If the command_loop() returned normally, the loop would
     attempt to exit by calling the function quit_command().  That
     function would either call exit() or throw an error returning
     control to SET_TOP_LEVEL. */
  /* NOTE: The function do_cleanups() was called once each time round
     the loop.  The usefulness of the call isn't clear.  If an error
     was thrown, everything would have already been cleaned up.  If
     command_loop() returned normally and quit_command() was called,
     either exit() or error() (again cleaning up) would be called. */
#endif
  /* NOTE: cagney/1999-11-07: There is probably no reason for not
     moving this loop and the code found in captured_command_loop()
     into the command_loop() proper.  The main thing holding back that
     change - SET_TOP_LEVEL() - has been eliminated. */
  while (1)
    {
      catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL);
    }
  /* No exit -- exit is through quit_command.  */
}
Exemplo n.º 16
0
/*****************************************************************************
 * main()
 *
 * Parse command line, load patch, start midi_tx, midi_rx, and jack threads.
 *****************************************************************************/
int
main(int argc, char **argv)
{
	char            thread_name[16];
	char            opts[NUM_OPTS * 2 + 1];
	struct option   *op;
	char            *cp;
	char            *p;
	char            *term;
	char            *tokbuf;
	int             c;
	int             j                       = 0;
	int             ret                     = 0;
	int             saved_errno;
	int             argcount                = 0;
	char            **argvals               = argv;
	char            **envp                  = environ;
	char            *argvend                = (char *)argv;
	size_t          argsize;
	unsigned char   rx_channel;

	setlocale(LC_ALL, "C");

	jamrouter_instance = get_instance_num();
	fprintf(stderr, "Starting jamrouter instance %d.\n", jamrouter_instance);

	/* Start debug thread.  debug_class is not set until arguemnts are parsed,
	   so use fprintf() until then. */
	if ((ret = pthread_create(&debug_thread_p, NULL, &jamrouter_debug_thread, NULL)) != 0) {
		fprintf(stderr, "***** ERROR:  Unable to start debug thread.\n");
	}

	/* lock down memory (rt hates page faults) */
	if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
		saved_errno = errno;
		fprintf(stderr, "Unable to unlock memory:  errno=%d (%s)\n",
		        saved_errno, strerror(saved_errno));
	}

	/* init lash client */
#ifndef WITHOUT_LASH
	for (j = 0; j < argc; j++) {
		if ((strcmp(argv[j], "-L") == 0) || (strcmp(argv[j], "--disable-lash") == 0) ||
		    (strcmp(argv[j], "-h") == 0) || (strcmp(argv[j], "--help") == 0) ||
		    (strcmp(argv[j], "-l") == 0) || (strcmp(argv[j], "--list") == 0) ||
		    (strcmp(argv[j], "-v") == 0) || (strcmp(argv[j], "--version") == 0) ||
		    (strcmp(argv[j], "-D") == 0) || (strcmp(argv[j], "--session-dir") == 0) ||
		    (strcmp(argv[j], "-u") == 0) || (strcmp(argv[j], "--uuid") == 0)) {
			lash_disabled = 1;
			break;
		}
	}
	if (!lash_disabled) {
		snprintf(thread_name, 16, "jamrouter%c-lash", ('0' + jamrouter_instance));
		pthread_setname_np(pthread_self(), thread_name);
		if (lash_client_init(&argc, &argv) == 0) {
			lash_poll_event();
		}
		snprintf(thread_name, 16, "jamrouter%c-main", ('0' + jamrouter_instance));
		pthread_setname_np(pthread_self(), thread_name);
	}
#endif

	/* startup initializations */
	init_midi_event_queue();
	init_jack_audio_driver();
	select_midi_driver(NULL, DEFAULT_MIDI_DRIVER);

	/* save original command line for session handling */
	if (jamrouter_cmdline[0] == '\0') {
		jamrouter_cmdline[0] = '\0';
		for (j = 0; j < argc; j++) {
			strcat(&(jamrouter_cmdline[0]), argv[j]);
			strcat(&(jamrouter_cmdline[0]), " ");
		}
		jamrouter_cmdline[strlen(jamrouter_cmdline) - 1] = '\0';
		term = get_color_terminal();
		if (term == NULL) {
			strcpy(jamrouter_full_cmdline, jamrouter_cmdline);
		}
		else {
			snprintf(jamrouter_full_cmdline, 512, "%s -e \"%s \"",
			         term, jamrouter_cmdline);
		}
		argcount = argc;
		argvals  = argv;
	}
	/* command line args supplied by session manager */
	else {
		argcount = 0;
		cp = strdup(jamrouter_cmdline);
		p = cp;
		while ((p = index(p, ' ')) != NULL) {
			p++;
			argcount++;
		}
		if ((argvals = malloc(((size_t)(argcount) + 1UL) *
		                      (size_t)sizeof(char *))) == NULL) {
			fprintf(stderr, "Out of Memory!\n");
			return -1;
		}
		if ((tokbuf = alloca(strlen(jamrouter_cmdline) * 4)) == NULL) {
			fprintf(stderr, "Out of Memory!\n");
			return -1;
		}
		while ((p = strtok_r(cp, " ", &tokbuf)) != NULL) {
			cp = NULL;
			argvals[j++] = p;
		}
		argvals[argcount] = NULL;
	}

	/* build the short option string */
	cp = opts;
	for (op = long_opts; op < &long_opts[NUM_OPTS]; op++) {
		*cp++ = (char) op->val;
		if (op->has_arg) {
			*cp++ = ':';
		}
	}

	/* handle options */
	for (;;) {
		c = getopt_long(argcount, argvals, opts, long_opts, NULL);
		if (c == -1) {
			break;
		}

		switch (c) {
		case 'M':   /* MIDI driver */
			select_midi_driver(optarg, -1);
			break;
		case 'D':   /* MIDI Rx/Tx port/device */
			midi_rx_port_name = strdup(optarg);
			midi_tx_port_name = strdup(optarg);
			break;
		case 'r':   /* MIDI Rx port/device */
			midi_rx_port_name = strdup(optarg);
			break;
		case 't':   /* MIDI Tx port/device */
			midi_tx_port_name = strdup(optarg);
			break;
		case 'x':   /* MIDI Rx latency periods */
			rx_latency_periods = atoi(optarg);
			break;
		case 'X':   /* MIDI Tx latency periods */
			tx_latency_periods = atoi(optarg);
			break;
		case 'g':   /* Tx byte guard time in usec */
			byte_guard_time_usec = atoi(optarg);
			break;
		case 'G':   /* Tx event guard time in usec */
			event_guard_time_usec = atoi(optarg);
			break;
		case 'i':   /* JACK MIDI input port */
			jack_input_port_name = strdup(optarg);
			break;
		case 'o':   /* JACK MIDI output port */
			jack_output_port_name = strdup(optarg);
			break;
		case 'j':   /* Jitter correction mode */
			jitter_correct_mode = 1;
			break;
		case 'z':   /* JACK wake phase within MIDI Rx/Tx period */
			setting_midi_phase_lock = (timecalc_t)(atof(optarg));
			if (setting_midi_phase_lock < (timecalc_t)(0.0625)) {
				setting_midi_phase_lock = (timecalc_t)(0.0625);
			}
			else if (setting_midi_phase_lock > (timecalc_t)(0.9375)) {
				setting_midi_phase_lock = (timecalc_t)(0.9375);
			}
			break;
#ifndef WITHOUT_JACK_DLL
		case '4':   /* JACK DLL timing level 4 */
			jack_dll_level = 4;
			break;
		case '3':   /* JACK DLL timing level 3 */
			jack_dll_level = 3;
			break;
		case '2':   /* JACK DLL timing level 2 */
			jack_dll_level = 2;
			break;
		case '1':   /* JACK DLL timing level 1 */
			jack_dll_level = 1;
			break;
#endif
		case 'k':   /* key to controller mapping */
			if (optarg != NULL) {
				if ((tokbuf = alloca(strlen((const char *)optarg) * 4)) == NULL) {
					jamrouter_shutdown("Out of memory!\n");
				}
				if ((p = strtok_r(optarg, ",", &tokbuf)) != NULL) {
					rx_channel = (atoi(p) - 1) & 0x0F;
					if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
						keymap_tx_channel[rx_channel] = (atoi(p) - 1) & 0x0F;
						if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
							keymap_tx_controller[rx_channel] = atoi(p) & 0x7F;
						}
					}
					JAMROUTER_DEBUG(DEBUG_CLASS_INIT, "Key --> Controller Map:  "
					                "rx_channel=%0d  tx_channel=%d  tx_cc=%d\n",
					                rx_channel + 1,
					                keymap_tx_channel[rx_channel] + 1,
					                keymap_tx_controller[rx_channel]);
				}
			}
			break;
		case 'p':   /* key to pitchbend translation */
			if (optarg != NULL) {
				if ((tokbuf = alloca(strlen((const char *)optarg) * 4)) == NULL) {
					jamrouter_shutdown("Out of memory!\n");
				}
				if ((p = strtok_r(optarg, ",", &tokbuf)) != NULL) {
					rx_channel = (atoi(p) - 1) & 0x0F;
					if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
						pitchmap_tx_channel[rx_channel] = (atoi(p) - 1) & 0x0F;
						if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
							pitchmap_center_note[rx_channel] = atoi(p) & 0x7F;
							if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
								pitchmap_bend_range[rx_channel] = atoi(p) & 0x7F;
							}
						}
					}
					JAMROUTER_DEBUG(DEBUG_CLASS_INIT,
					                "Key --> Pitchbend Map:  "
					                "rx_chan=%0d  tx_chan=%d  center=%d  range=%d\n",
					                rx_channel + 1, pitchmap_tx_channel[rx_channel] + 1,
					                pitchmap_center_note[rx_channel],
					                pitchmap_bend_range[rx_channel]);
				}
			}
			break;
		case 'q':   /* pitchbend to controller translation */
			if (optarg != NULL) {
				if ((tokbuf = alloca(strlen((const char *)optarg) * 4)) == NULL) {
					jamrouter_shutdown("Out of memory!\n");
				}
				if ((p = strtok_r(optarg, ",", &tokbuf)) != NULL) {
					rx_channel = (atoi(p) - 1) & 0x0F;
					if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
						pitchcontrol_tx_channel[rx_channel] = (atoi(p) - 1) & 0x0F;
						if ((p = strtok_r(NULL, ",", &tokbuf)) != NULL) {
							pitchcontrol_controller[rx_channel] = atoi(p) & 0x7F;
						}
					}
					JAMROUTER_DEBUG(DEBUG_CLASS_INIT,
					                "Pitchbend --> Controller Map:  "
					                "rx_chan=%0d  tx_chan=%d  controller=%d\n",
					                rx_channel + 1, pitchcontrol_tx_channel[rx_channel] + 1,
					                pitchcontrol_controller[rx_channel]);
				}
			}
			break;
#ifndef WITHOUT_JUNO
		case 'J':   /* Juno-106 sysex controller translation */
			translate_juno_sysex = 1;
			break;
		case 's':   /* echo sysex translations back to originator */
			echosysex = 1;
			break;
#endif
		case 'e':   /* echo pitchbend and controller translations back to originator */
			echotrans = 1;
			break;
		case 'T':   /* alternate sysex terminator byte */
			sysex_terminator = hex_to_byte(optarg);
			break;
		case 'U':   /* alternate sysex terminator byte */
			sysex_extra_terminator = hex_to_byte(optarg);
			break;
		case 'A':   /* Active-Sensing mode */
			if (strcmp(optarg, "on") == 0) {
				active_sensing_mode = ACTIVE_SENSING_MODE_ON;
			}
			else if (strcmp(optarg, "thru") == 0) {
				active_sensing_mode = ACTIVE_SENSING_MODE_THRU;
			}
			else if (strcmp(optarg, "drop") == 0) {
				active_sensing_mode = ACTIVE_SENSING_MODE_DROP;
			}
			break;
		case 'R':   /* Omit running status byte on MIDI Tx */
			use_running_status = 1;
			break;
		case 'n':   /* Note-On Velocity */
			note_on_velocity = hex_to_byte(optarg);
			break;
		case 'N':   /* Note-Off Velocity */
			note_off_velocity = hex_to_byte(optarg);
			break;
		case 'f':   /* Send multiple Note-Off messages as All-Notes-Off */
			tx_prefer_all_notes_off = 1;
			break;
		case 'F':   /* Tx send real Note-Off instead of Velocity-0-Note-On */
			tx_prefer_real_note_off = 1;
			break;
		case '0':   /* Rx queue real Note-Off instead of Velocity-0-Note-On */
			rx_queue_real_note_off = 1;
			break;
		case 'y':   /* MIDI Rx thread priority */
			if ((midi_rx_thread_priority = atoi(optarg)) <= 0) {
				midi_rx_thread_priority = MIDI_RX_THREAD_PRIORITY;
			}
			break;
		case 'Y':   /* MIDI Tx thread priority */
			if ((midi_tx_thread_priority = atoi(optarg)) <= 0) {
				midi_tx_thread_priority = MIDI_TX_THREAD_PRIORITY;
			}
			break;
		case 'd':   /* debug */
			debug = 1;
			for (j = 0; debug_class_list[j].name != NULL; j++) {
				if (strcmp(debug_class_list[j].name, optarg) == 0) {
					debug_class |= debug_class_list[j].id;
				}
			}
			break;
		case 'v':   /* version */
			printf("jamrouter-%s\n", PACKAGE_VERSION);
			return 0;
		case 'L':   /* disable lash */
			lash_disabled = 1;
			break;
		case 'l':   /* list midi devices */
			scan_midi();
			return 0;
		case 'u':   /* jack session uuid */
			jack_session_uuid = strdup(optarg);
			break;
		case '?':
		case 'h':   /* help */
		default:
			showusage(argv[0]);
			return -1;
		}
	}

	/* Rewrite process title */
	argcount = argc;
	argvals  = argv;
	for (j = 0; j <= argcount; j++) {
		if ((j == 0) || ((argvend + 1) == argvals[j])) {
			argvend = argvals[j] + strlen(argvals[j]);
		}
		else {
			continue;
		}
	}

	/* steal space from first environment entry */
	if (envp[0] != NULL) {
		argvend = envp[0] + strlen (envp[0]);
	}

	/* calculate size we have for process title */
	argsize = (size_t)((char *)argvend - (char *)*argvals - 1);
	memset (*argvals, 0, argsize);

	/* rewrite process title */
	argc = 0;
	snprintf((char *)*argvals, argsize, "jamrouter%d", jamrouter_instance);

	/* signal handlers for clean shutdown */
	init_signal_handlers();

	/* init MIDI system based on selected driver */
	JAMROUTER_DEBUG(DEBUG_CLASS_INIT, "Initializing MIDI:  driver=%s.\n",
	                midi_driver_names[midi_driver]);
	init_sync_info(0, 0);
	init_midi();

	/* initialize JACK audio system based on selected driver */
	snprintf(thread_name, 16, "jamrouter%c-clnt", ('0' + jamrouter_instance));
	pthread_setname_np(pthread_self(), thread_name);
	init_jack_audio();
	while (sample_rate == 0) {
		JAMROUTER_DEBUG(DEBUG_CLASS_INIT,
		                "JACK did not set sample rate.  Re-initializing...\n");
		init_jack_audio();
		usleep(125000);
	}

	/* start the JACK audio system */
	start_jack_audio();

	/* wait for JACK audio to start before starting midi. */
	wait_jack_audio_start();

	snprintf(thread_name, 16, "jamrouter%c-main", ('0' + jamrouter_instance));
	pthread_setname_np(pthread_self(), thread_name);

	/* start MIDI Rx/Tx threads. */
	start_midi_rx();
	wait_midi_rx_start();
	start_midi_tx();
	wait_midi_tx_start();

	/* debug thread not needed once watchdog is running */
	debug_done = 1;
	pthread_join(debug_thread_p, NULL);

	/* Jamrouter watchdog handles restarting threads on config changes,
	   runs driver supplied watchdog loop iterations, and handles debug
	   output. */
	jamrouter_watchdog();
	stop_midi_tx();
	stop_midi_rx();
	stop_jack_audio();
	output_pending_debug();

	/* Wait for threads created directly by JAMROUTER to terminate. */
	if (midi_rx_thread_p != 0) {
		pthread_join(midi_rx_thread_p,  NULL);
	}
	if (midi_tx_thread_p != 0) {
		pthread_join(midi_tx_thread_p,  NULL);
	}
	output_pending_debug();

	return 0;
}
Exemplo n.º 17
0
int
do_test (int argc, char **argv)
{
  pthread_t self;
  int res;
  int ret = 0;
  char name[TASK_COMM_LEN];
  char name_check[TASK_COMM_LEN];

  memset (name, '\0', TASK_COMM_LEN);
  memset (name_check, '\0', TASK_COMM_LEN);

  /* Test 1: Get the name of the task via pthread_getname_np and /proc
     and verify that they both match.  */
  self = pthread_self ();
  res = pthread_getname_np (self, name, TASK_COMM_LEN);

  if (res == 0)
    {
      res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);

#ifndef __ASSUME_PROC_PID_TASK_COMM
      /* On this first test we look for ENOENT to be returned from
         get_self_comm to indicate that the kernel is older than
         2.6.33 and doesn't contain comm within the proc structure.
         In that case we skip the entire test.  */
      if (res == ENOENT)
	{
	  printf ("SKIP: The kernel does not have /proc/self/task/%%lu/comm.\n");
	  return 0;
	}
#endif

      if (res == 0)
       {
         if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
           printf ("PASS: Test 1 - pthread_getname_np and /proc agree.\n");
         else
           {
             printf ("FAIL: Test 1 - pthread_getname_np and /proc differ"
                     " i.e. %s != %s\n", name, name_check);
             ret++;
           }
       }
      else
       {
         printf ("FAIL: Test 1 - unable read task name via proc.\n");
         ret++;
        }
    }
  else
    {
      printf ("FAIL: Test 1 - pthread_getname_np failed with error %d\n", res);
      ret++;
    }

  /* Test 2: Test setting the name and then independently verify it
             was set.  */
  res = pthread_setname_np (self, NEW_NAME);

  if (res == 0)
    {
      res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
      if (res == 0)
        {
         if (strncmp (NEW_NAME, name_check, strlen (BIG_NAME)) == 0)
           printf ("PASS: Test 2 - Value used in pthread_setname_np and"
                   " /proc agree.\n");
         else
           {
             printf ("FAIL: Test 2 - Value used in pthread_setname_np"
		     " and /proc differ i.e. %s != %s\n",
		     NEW_NAME, name_check);
             ret++;
           }
        }
      else
       {
         printf ("FAIL: Test 2 - unable to read task name via proc.\n");
         ret++;
        }
    }
  else
    {
      printf ("FAIL: Test 2 - pthread_setname_np failed with error %d\n", res);
      ret++;
    }

  /* Test 3: Test setting a name that is one-byte too big.  */
  res = pthread_getname_np (self, name, TASK_COMM_LEN);

  if (res == 0)
    {
      res = pthread_setname_np (self, BIG_NAME);
      if (res != 0)
        {
         if (res == ERANGE)
           {
             printf ("PASS: Test 3 - pthread_setname_np returned ERANGE"
                     " for a process name that was too long.\n");

             /* Verify the old name didn't change.  */
             res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
             if (res == 0)
               {
                 if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
                   printf ("PASS: Test 3 - Original name unchanged after"
                           " pthread_setname_np returned ERANGE.\n");
                 else
                   {
                     printf ("FAIL: Test 3 - Original name changed after"
                             " pthread_setname_np returned ERANGE"
                             " i.e. %s != %s\n",
                             name, name_check);
                     ret++;
                   }
               }
             else
               {
                 printf ("FAIL: Test 3 - unable to read task name.\n");
                 ret++;
               }
           }
         else
           {
             printf ("FAIL: Test 3 - Wrong error returned"
		     " i.e. ERANGE != %d\n", res);
             ret++;
           }
        }
      else
        {
         printf ("FAIL: Test 3 - Too-long name accepted by"
	         " pthread_setname_np.\n");
         ret++;
        }
    }
  else
    {
      printf ("FAIL: Test 3 - Unable to get original name.\n");
      ret++;
    }

  /* Test 4: Verify that setting the longest name works.  */
  res = pthread_setname_np (self, LONGEST_NAME);

  if (res == 0)
    {
      res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
      if (res == 0)
        {
         if (strncmp (LONGEST_NAME, name_check, strlen (BIG_NAME)) == 0)
           printf ("PASS: Test 4 - Longest name set via pthread_setname_np"
                   " agrees with /proc.\n");
         else
           {
             printf ("FAIL: Test 4 - Value used in pthread_setname_np and /proc"
		     " differ i.e. %s != %s\n", LONGEST_NAME, name_check);
             ret++;
           }
        }
      else
       {
         printf ("FAIL: Test 4 - unable to read task name via proc.\n");
         ret++;
        }
    }
  else
    {
      printf ("FAIL: Test 4 - pthread_setname_np failed with error %d\n", res);
      ret++;
    }

  /* Test 5: Verify that getting a long name into a small buffer fails.  */
  strncpy (name, CANARY_NAME, strlen (CANARY_NAME) + 1);

  /* Claim the buffer length is strlen (LONGEST_NAME).  This is one character
     too small to hold LONGEST_NAME *and* the null terminator.  We should get
     back ERANGE and name should be unmodified.  */
  res = pthread_getname_np (self, name, strlen (LONGEST_NAME));

  if (res != 0)
    {
      if (res == ERANGE)
        {
	  if (strncmp (CANARY_NAME, name, strlen (BIG_NAME)) == 0)
	    {
	      printf ("PASS: Test 5 - ERANGE and buffer unmodified.\n");
	    }
	  else
	    {
	      printf ("FAIL: Test 5 - Original buffer modified.\n");
	      ret++;
	    }
        }
      else
        {
	  printf ("FAIL: Test 5 - Did not return ERANGE for small buffer.\n");
	  ret++;
        }
    }
  else
    {
      printf ("FAIL: Test 5 - Returned name longer than buffer.\n");
      ret++;
    }

  /* Test 6: Lastly make sure we can read back the longest name.  */
  res = pthread_getname_np (self, name, strlen (LONGEST_NAME) + 1);

  if (res == 0)
    {
      if (strncmp (LONGEST_NAME, name, strlen (BIG_NAME)) == 0)
        {
	  printf ("PASS: Test 6 - Read back longest name correctly.\n");
        }
      else
        {
	  printf ("FAIL: Test 6 - Read \"%s\" instead of longest name.\n",
		  name);
	  ret++;
        }
    }
  else
    {
      printf ("FAIL: Test 6 - pthread_getname_np failed with error %d\n", res);
      ret++;
    }

  return ret;
}
Exemplo n.º 18
0
static void* pfpf_worker(void* _data)
{
	int epoll_count = -1;
	socklen_t restrict_length = 0;
	int client_socket = -1;
	struct sockaddr_in client;
	struct epoll_event client_epoll_event;
	struct epoll_event epoll_events[EPOLL_MAXEVENTS];
	sigset_t epoll_sigmask_new;
	sigset_t epoll_sigmask_old;
	pfpf_worker_context_t* data = _data;

	pfcq_zero(&client, sizeof(struct sockaddr_in));
	pfcq_zero(&client_epoll_event, sizeof(struct epoll_event));
	pfcq_zero(epoll_events, EPOLL_MAXEVENTS * sizeof(struct epoll_event));
	pfcq_zero(&epoll_sigmask_new, sizeof(sigset_t));
	pfcq_zero(&epoll_sigmask_old, sizeof(sigset_t));

	pthread_setname_np(pthread_self(), "worker");

	if (unlikely(!data))
		goto out;

	if (unlikely(sigemptyset(&epoll_sigmask_new) != 0))
		panic("sigemptyset");
	if (unlikely(sigaddset(&epoll_sigmask_new, SIGTERM) != 0))
		panic("sigaddset");
	if (unlikely(sigaddset(&epoll_sigmask_new, SIGINT) != 0))
		panic("sigaddset");
	if (unlikely(pthread_sigmask(SIG_BLOCK, &epoll_sigmask_new, &epoll_sigmask_old) != 0))
		panic("pthread_sigmask");

	for (;;)
	{
		epoll_count = epoll_pwait(data->epoll_fd, epoll_events, EPOLL_MAXEVENTS, -1, &epoll_sigmask_old);

		if (unlikely(epoll_count == -1))
		{
			if (likely(errno == EINTR))
			{
				if (likely(data->parent_pool->should_exit))
				{
					debug("Worker #%d got interrupt signal, attempting to exit gracefully...\n", data->server_socket);
					goto lfree;
				} else
					continue;
			}
			else
			{
				warning("epoll_pwait");
				continue;
			}
		} else
		{
			for (int i = 0; i < epoll_count; i++)
			{
				int cfd = epoll_events[i].data.fd;
				if (likely(epoll_events[i].events & EPOLLIN && !(epoll_events[i].events & EPOLLERR)))
				{
					if (unlikely(cfd == data->server_socket))
					{
						restrict_length = (socklen_t)sizeof(struct sockaddr_in);
						pfcq_zero(&client, sizeof(struct sockaddr_in));
						pfcq_zero(&client_epoll_event, sizeof(struct epoll_event));

						client_socket = accept4(data->server_socket, (struct sockaddr*)&client, &restrict_length, SOCK_NONBLOCK);
						if (unlikely(client_socket < 0))
						{
							if (likely(errno == EAGAIN || errno == EWOULDBLOCK))
								continue;
							else
							{
								warning("accept4");
								continue;
							}
						}
						pfpf_client_context_t* new_pfpf_client_context = pfcq_alloc(sizeof(pfpf_client_context_t));
						new_pfpf_client_context->socket = client_socket;
						data->initializer(&new_pfpf_client_context->data);
						data->clients[client_socket] = new_pfpf_client_context;
						data->clients_count++;

						debug("Accepted client to #%d socket by #%d server\n", client_socket, data->server_socket);
						debug("Total clients of server #%d: %d\n", data->server_socket, data->clients_count);

						client_epoll_event.data.fd = client_socket;
						client_epoll_event.events = EPOLLIN;
						if (unlikely(epoll_ctl(data->epoll_fd, EPOLL_CTL_ADD, client_socket, &client_epoll_event) == -1))
							panic("epoll_ctl");
					} else
					{
						pfpf_client_context_t* current_pfpf_client_context = data->clients[cfd];

						current_pfpf_client_context->bytes_read = read(current_pfpf_client_context->socket, current_pfpf_client_context->buffer, NET_CHUNK_SIZE);
						if (likely(current_pfpf_client_context->bytes_read > 0))
						{
							data->handler(current_pfpf_client_context);
							if (current_pfpf_client_context->should_close)
								goto should_close;
						} else
						{
should_close:
							debug("Saying good bye to socket #%d from server #%d\n", current_pfpf_client_context->socket, data->server_socket);
							if (unlikely(epoll_ctl(data->epoll_fd, EPOLL_CTL_DEL, current_pfpf_client_context->socket, NULL) == -1))
								panic("epoll_ctl");
							if (unlikely(close(current_pfpf_client_context->socket) == -1))
								warning("close");
							if (likely(current_pfpf_client_context->data))
							{
								data->finalizer(current_pfpf_client_context->data);
								pfcq_free(current_pfpf_client_context->data);
							}
							pfcq_free(current_pfpf_client_context);
							data->clients[cfd] = NULL;
							data->clients_count--;
						}
					}
				} else
				{
					warning("epoll_wait");
					continue;
				}
			}
		}
	}

lfree:
	debug("Cleaning up #%d server...\n", data->server_socket);

	for (int i = 0; i < data->clients_pool_size; i++)
	{
		if (unlikely(data->clients[i]))
		{
			debug("Detaching client #%d of server #%d...\n", data->clients[i]->socket, data->server_socket);
			close(data->clients[i]->socket);
			debug("Freeing client #%d data of server #%d...\n", data->clients[i]->socket, data->server_socket);
			if (likely(data->clients[i]->data))
			{
				data->finalizer(data->clients[i]->data);
				pfcq_free(data->clients[i]->data);
			}
			pfcq_free(data->clients[i]);
			data->clients_count--;
		}
	}
	debug("Destroying clients list of server #%d...\n", data->server_socket);
	pfcq_free(data->clients);

	close(data->server_socket);
	close(data->epoll_fd);

	debug("Server #%d cleaned up\n", data->server_socket);

out:

	return NULL;
}
Exemplo n.º 19
0
void *probe_worker_runfn(void *arg)
{
	probe_pwpair_t *pair = (probe_pwpair_t *)arg;

	SEXP_t *probe_res, *obj, *oid;
	int     probe_ret;

#if defined(HAVE_PTHREAD_SETNAME_NP)
# if defined(__APPLE__)
	pthread_setname_np("probe_worker");
# else
	pthread_setname_np(pthread_self(), "probe_worker");
# endif
#endif
	dD("handling SEAP message ID %u", pair->pth->sid);
	//
	probe_ret = -1;
	probe_res = pair->pth->msg_handler(pair->probe, pair->pth->msg, &probe_ret);
	//
	dD("handler result = %p, return code = %d", probe_res, probe_ret);

	/* Assuming that the red-black tree API is doing locking for us... */
	if (rbt_i32_del(pair->probe->workers, pair->pth->sid, NULL) != 0) {
		dW("thread not found in the probe thread tree, probably canceled by an external signal");
		/*
		 * XXX: this is a possible deadlock; we can't send anything from
		 * here because the signal handler replied to the message
		 */
		arg = NULL;

                SEAP_msg_free(pair->pth->msg);
                SEXP_free(probe_res);
                oscap_free(pair);

                return (NULL);
	} else {
                SEXP_t *items;

		dD("probe thread deleted");

		obj = SEAP_msg_get(pair->pth->msg);
		oid = probe_obj_getattrval(obj, "id");
                items = probe_cobj_get_items(probe_res);

                if (items != NULL) {
                        SEXP_list_sort(items, SEXP_refcmp);
                        SEXP_free(items);
                }

		if (probe_rcache_sexp_add(pair->probe->rcache, oid, probe_res) != 0) {
			/* TODO */
			abort();
		}

		SEXP_vfree(obj, oid, NULL);
	}

	if (probe_ret != 0) {
		/*
		 * Something bad happened. A hint of the cause is stored as a error code in
		 * probe_ret (should be). We'll send it to the library using a SEAP error packet.
		 */
		if (SEAP_replyerr(pair->probe->SEAP_ctx, pair->probe->sd, pair->pth->msg, probe_ret) == -1) {
			int ret = errno;

			dE("An error ocured while sending error status. errno=%u, %s.", errno, strerror(errno));
			SEXP_free(probe_res);

			/* FIXME */
			exit(ret);
		}
		SEXP_free(probe_res);
	} else {
		SEAP_msg_t *seap_reply;
		/*
		 * OK, the probe actually returned something, let's send it to the library.
		 */
		seap_reply = SEAP_msg_new();
		SEAP_msg_set(seap_reply, probe_res);

		if (SEAP_reply(pair->probe->SEAP_ctx, pair->probe->sd, seap_reply, pair->pth->msg) == -1) {
			int ret = errno;

			SEAP_msg_free(seap_reply);
			SEXP_free(probe_res);

			exit(ret);
		}

		SEAP_msg_free(seap_reply);
                SEXP_free(probe_res);
	}

        SEAP_msg_free(pair->pth->msg);
        oscap_free(pair->pth);
	oscap_free(pair);
	pthread_detach(pthread_self());

	return (NULL);
}
Exemplo n.º 20
0
void *__memory_logging_event_writing_thread(void *param)
{
	pthread_setname_np("Memory Logging");
	
	working_thread_id = current_thread_id(); // for preventing deadlock'ing on stack logging on a single thread
	log_internal_without_this_thread(working_thread_id);
	
	struct timeval delay;
	delay.tv_sec = 0;
	delay.tv_usec = 10 * 1000; // 10 ms
	
	while (logging_is_enable) {
		while (has_event_in_buffer(event_buffer) == false) {
			usleep(15000);
			//select(0, NULL, NULL, NULL, &delay);
		}
		
		if (!logging_is_enable) {
			break;
		}
		
		// pick an event from buffer
		int64_t next_index = 0;
		memory_logging_event *curr_event = get_event_from_buffer(event_buffer, &next_index);
		bool is_skip = (curr_event->event_type == EventType_Invalid);
		
		if (is_next_index_valid(event_buffer, next_index) == false) {
			// Impossible...
			continue;
		}
		
		// compaction
		uint32_t object_type = 0;
		if (curr_event->event_type == EventType_Alloc && has_event_in_buffer(event_buffer, next_index)) {
			memory_logging_event *next_event = get_event_from_buffer(event_buffer, NULL, next_index);
			if (curr_event->address == next_event->address) {
				if (curr_event->type_flags & memory_logging_type_alloc) {
					if (next_event->type_flags & memory_logging_type_dealloc) {
						// *waves hand* current allocation never occurred
						is_skip = true;
						next_event->event_type = EventType_Invalid;
					} else if (next_event->event_type == EventType_Update) {
						object_type = next_event->argument;
						next_event->event_type = EventType_Invalid;
					}
				} else if (next_event->type_flags & memory_logging_type_vm_deallocate) {
					// *waves hand* current allocation(VM) never occurred
					is_skip = true;
					next_event->event_type = EventType_Invalid;
				}
			}
		}
		
		if (!is_skip) {
			// Can't lock like this without brain, or affect performance
			//__malloc_lock_lock(&working_thread_lock);
			if (should_working_thread_lock == 1) {
				should_working_thread_lock = 2;
				while (should_working_thread_lock == 2);
			}
			
			if (curr_event->event_type == EventType_Alloc) {
				uint32_t stack_identifier = 0;
				if (curr_event->stack_size > 0) {
					stack_identifier = add_stack_frames_in_table(stack_frames_writer, curr_event->stacks + curr_event->num_hot_to_skip, curr_event->stack_size - curr_event->num_hot_to_skip); // unique stack in memory
				} else {
					__malloc_printf("Data corrupted!");
					
					//__malloc_lock_unlock(&working_thread_lock);
					// Restore abort()?
					//abort();
					report_error(MS_ERRC_DATA_CORRUPTED);
					disable_memory_logging();
					break;
				}
				// Try to get vm memory type from type_flags
				if (object_type == 0) {
					VM_GET_FLAGS_ALIAS(curr_event->type_flags, object_type);
				}
				add_allocation_event(allocation_event_writer, curr_event->address, curr_event->type_flags, object_type, curr_event->argument, stack_identifier, curr_event->t_id);
			} else if (curr_event->event_type == EventType_Free) {
				del_allocation_event(allocation_event_writer, curr_event->address, curr_event->type_flags);
			} else {
				update_allocation_event_object_type(allocation_event_writer, curr_event->address, curr_event->argument);
			}
			
			//__malloc_lock_unlock(&working_thread_lock);
		}
		
		update_read_index(event_buffer, next_index);
	}
	return NULL;
}
Exemplo n.º 21
0
static void *probe_icache_worker(void *arg)
{
        probe_icache_t *cache = (probe_icache_t *)(arg);
        probe_iqpair_t *pair, pair_mem;
        SEXP_ID_t       item_ID;

        assume_d(cache != NULL, NULL);

	pthread_setname_np(pthread_self(), "icache_worker");

        if (pthread_mutex_lock(&cache->queue_mutex) != 0) {
                dE("An error ocured while locking the queue mutex: %u, %s",
                   errno, strerror(errno));
                return (NULL);
        }

	pair = &pair_mem;
        dD("icache worker ready");

        switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier)))
        {
        case 0:
        case PTHREAD_BARRIER_SERIAL_THREAD:
	        break;
        default:
	        dE("pthread_barrier_wait: %d, %s.",
	           errno, strerror(errno));
	        pthread_mutex_unlock(&cache->queue_mutex);
	        return (NULL);
        }

        while(pthread_cond_wait(&cache->queue_notempty, &cache->queue_mutex) == 0) {
                assume_d(cache->queue_cnt > 0, NULL);
        next:
                dD("Extracting item from the cache queue: cnt=%"PRIu16", beg=%"PRIu16"", cache->queue_cnt, cache->queue_beg);
                /*
                 * Extract an item from the queue and update queue beg, end & cnt
                 */
                pair_mem = cache->queue[cache->queue_beg];
#ifndef NDEBUG
		memset(cache->queue + cache->queue_beg, 0, sizeof(probe_iqpair_t));
#endif
                --cache->queue_cnt;
		++cache->queue_beg;

		if (cache->queue_beg == cache->queue_max)
			cache->queue_beg = 0;

		assume_d(cache->queue_cnt == 0 ?
			 cache->queue_end == cache->queue_beg :
			 cache->queue_end != cache->queue_beg, NULL);

                /*
                 * Release the mutex
                 */
                if (pthread_mutex_unlock(&cache->queue_mutex) != 0) {
                        dE("An error ocured while unlocking the queue mutex: %u, %s",
                           errno, strerror(errno));
                        abort();
                }

                dD("Signaling `notfull'");

                if (pthread_cond_signal(&cache->queue_notfull) != 0) {
                        dE("An error ocured while signaling the `notfull' condition: %u, %s",
                           errno, strerror(errno));
                        abort();
                }

                if (pair->cobj == NULL) {
                        /*
                         * Handle NOP case (synchronization)
                         */
                        assume_d(pair->p.cond != NULL, NULL);

                        dD("Handling NOP");

                        if (pthread_cond_signal(pair->p.cond) != 0) {
                                dE("An error ocured while signaling NOP condition: %u, %s",
                                   errno, strerror(errno));
                                abort();
                        }
                } else {
                        probe_citem_t *cached = NULL;

                        dD("Handling cache request");

                        /*
                         * Compute item ID
                         */
                        item_ID = SEXP_ID_v(pair->p.item);
                        dD("item ID=%"PRIu64"", item_ID);

                        /*
                         * Perform cache lookup
                         */
                        if (rbt_i64_get(cache->tree, (int64_t)item_ID, (void *)&cached) == 0) {
                                register uint16_t i;
				SEXP_t   rest1, rest2;
                                /*
                                 * Maybe a cache HIT
                                 */
                                dD("cache HIT #1");

                                for (i = 0; i < cached->count; ++i) {
                                        if (SEXP_deepcmp(SEXP_list_rest_r(&rest1, pair->p.item),
							 SEXP_list_rest_r(&rest2, cached->item[i])))
					{
						SEXP_free_r(&rest1);
						SEXP_free_r(&rest2);
                                                break;
					}

					SEXP_free_r(&rest1);
					SEXP_free_r(&rest2);
                                }

                                if (i == cached->count) {
                                        /*
                                         * Cache MISS
                                         */
                                        dD("cache MISS");

                                        cached->item = oscap_realloc(cached->item, sizeof(SEXP_t *) * ++cached->count);
                                        cached->item[cached->count - 1] = pair->p.item;

                                        /* Assign an unique item ID */
                                        probe_icache_item_setID(pair->p.item, item_ID);
                                } else {
                                        /*
                                         * Cache HIT
                                         */
                                        dD("cache HIT #2 -> real HIT");
                                        SEXP_free(pair->p.item);
                                        pair->p.item = cached->item[i];
                                }
                        } else {
                                /*
                                 * Cache MISS
                                 */
                                dD("cache MISS");
                                cached = oscap_talloc(probe_citem_t);
                                cached->item = oscap_talloc(SEXP_t *);
                                cached->item[0] = pair->p.item;
                                cached->count = 1;

                                /* Assign an unique item ID */
                                probe_icache_item_setID(pair->p.item, item_ID);

                                if (rbt_i64_add(cache->tree, (int64_t)item_ID, (void *)cached, NULL) != 0) {
                                        dE("Can't add item (k=%"PRIi64" to the cache (%p)", (int64_t)item_ID, cache->tree);

                                        oscap_free(cached->item);
                                        oscap_free(cached);

                                        /* now what? */
                                        abort();
                                }
                        }

                        if (probe_cobj_add_item(pair->cobj, pair->p.item) != 0) {
                            dW("An error ocured while adding the item to the collected object");
                        }
                }

                if (pthread_mutex_lock(&cache->queue_mutex) != 0) {
                        dE("An error ocured while re-locking the queue mutex: %u, %s",
                           errno, strerror(errno));
                        abort();
                }

                if (cache->queue_cnt > 0)
                        goto next;
        }

        return (NULL);
}
Exemplo n.º 22
0
void setThreadName(ThreadID thread_id, const char* thread_name)
{
	pthread_setname_np(thread_id, thread_name);
}
Exemplo n.º 23
0
/* Attempt to set the threads name; note that this is for debug, so
 * we're not going to fail if we can't set it.
 */
static void qemu_thread_set_name(QemuThread *thread, const char *name)
{
#ifdef CONFIG_PTHREAD_SETNAME_NP
    pthread_setname_np(thread->thread, name);
#endif
}
Exemplo n.º 24
0
/*
 * Nfs server daemon mostly just a user context for nfssvc()
 *
 * 1 - do file descriptor and signal cleanup
 * 2 - create the nfsd thread(s)
 * 3 - create server socket(s)
 * 4 - register socket with portmap
 *
 * For connectionless protocols, just pass the socket into the kernel via
 * nfssvc().
 * For connection based sockets, loop doing accepts. When you get a new
 * socket from accept, pass the msgsock into the kernel via nfssvc().
 * The arguments are:
 *	-r - reregister with portmapper
 *	-t - support only tcp nfs clients
 *	-u - support only udp nfs clients
 *	-n num how many threads to create.
 *	-4 - use only ipv4
 *	-6 - use only ipv6
 */
int
main(int argc, char *argv[])
{
	struct conf cfg[4];
	struct pollfd set[__arraycount(cfg)];
	int ch, connect_type_cnt;
	size_t i, nfsdcnt;
	int reregister;
	int tcpflag, udpflag;
	int ip6flag, ip4flag;
	int s, compat;
	int parent_fd = -1;

#define	DEFNFSDCNT	 4
	nfsdcnt = DEFNFSDCNT;
	compat = reregister = 0;
	tcpflag = udpflag = 1;
	ip6flag = ip4flag = 1;
#define	GETOPT	"46dn:rtu"
#define	USAGE	"[-46drtu] [-n num_servers]"
	while ((ch = getopt(argc, argv, GETOPT)) != -1) {
		switch (ch) {
		case '6':
			ip6flag = 1;
			ip4flag = 0;
			s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
			if (s < 0 && (errno == EPROTONOSUPPORT ||
			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
				ip6flag = 0;
			else
				close(s);
			break;
		case '4':
			ip6flag = 0;
			ip4flag = 1;
			s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
			if (s < 0 && (errno == EPROTONOSUPPORT ||
			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
				ip4flag = 0;
			else
				close(s);
			break;
		case 'd':
			debug++;
			break;
		case 'n':
			nfsdcnt = atoi(optarg);
			if (nfsdcnt < 1) {
				warnx("nfsd count %zu; reset to %d", nfsdcnt,
				    DEFNFSDCNT);
				nfsdcnt = DEFNFSDCNT;
			}
			break;
		case 'r':
			reregister = 1;
			break;
		case 't':
			compat |= 2;
			tcpflag = 1;
			udpflag = 0;
			break;
		case 'u':
			compat |= 1;
			tcpflag = 0;
			udpflag = 1;
			break;
		default:
		case '?':
			usage();
		}
	}
	argv += optind;
	argc -= optind;

	if (compat == 3) {
		warnx("Old -tu options detected; enabling both udp and tcp.");
		warnx("This is the default behavior now and you can remove");
		warnx("all options.");
		tcpflag = udpflag = 1;
		if (ip6flag == 1 && ip4flag == 0)
			ip4flag = 1;
	}

	if (debug == 0) {
		parent_fd = daemon2_fork();
		openlog("nfsd", LOG_PID, LOG_DAEMON);
	}


	memset(cfg, 0, sizeof(cfg));
	for (i = 0; i < __arraycount(cfg); i++) {
		if (ip4flag == 0 && cfg_family[i] == PF_INET)
			continue;
		if (ip6flag == 0 && cfg_family[i] == PF_INET6)
			continue;
		if (tcpflag == 0 && cfg_protocol[i] == IPPROTO_TCP)
			continue;
		if (udpflag == 0 && cfg_protocol[i] == IPPROTO_UDP)
			continue;
		tryconf(&cfg[i], i, reregister);
	}

	for (i = 0; i < nfsdcnt; i++) {
		pthread_t t;
		int error;

		error = pthread_create(&t, NULL, worker, NULL);
		if (error) {
			errno = error;
			logit(LOG_ERR, "pthread_create: %s", strerror(errno));
			exit(1);
		}
	}

	connect_type_cnt = 0;
	for (i = 0; i < __arraycount(cfg); i++) {
		set[i].fd = -1;
		set[i].events = POLLIN;
		set[i].revents = 0;

		if (cfg[i].nc == NULL)
			continue;

		setupsock(&cfg[i], &set[i], i);
		if (set[i].fd != -1)
			connect_type_cnt++;

	}

	if (connect_type_cnt == 0)
		exit(0);

	pthread_setname_np(pthread_self(), "master", NULL);

	if (debug == 0) {
		daemon2_detach(parent_fd, 0, 0);
		(void)signal(SIGHUP, SIG_IGN);
		(void)signal(SIGINT, SIG_IGN);
		(void)signal(SIGQUIT, SIG_IGN);
		(void)signal(SIGSYS, nonfs);
	}

	/*
	 * Loop forever accepting connections and passing the sockets
	 * into the kernel for the mounts.
	 */
	for (;;) {
		if (poll(set, __arraycount(set), INFTIM) == -1) {
			logit(LOG_ERR, "poll failed: %s", strerror(errno));
			exit(1);
		}

		for (i = 0; i < __arraycount(set); i++) {
			struct nfsd_args nfsdargs;
			struct sockaddr_storage ss;
			socklen_t len;
			int msgsock;
			int on = 1;

			if ((set[i].revents & POLLIN) == 0)
				continue;
			len = sizeof(ss);
			if ((msgsock = accept(set[i].fd,
			    (struct sockaddr *)&ss, &len)) == -1) {
				int serrno = errno;
				logit(LOG_ERR, "accept failed: %s",
				    strerror(errno));
				if (serrno == EINTR || serrno == ECONNABORTED)
					continue;
				exit(1);
			}
			if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, &on,
			    sizeof(on)) == -1)
				logit(LOG_ERR, "setsockopt SO_KEEPALIVE: %s",
				    strerror(errno));
			nfsdargs.sock = msgsock;
			nfsdargs.name = (void *)&ss;
			nfsdargs.namelen = len;
			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
			(void)close(msgsock);
		}
	}
}
Exemplo n.º 25
0
static void *close_thread(void *p) {
        (void) pthread_setname_np(pthread_self(), "close");

        assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF);
        return NULL;
}
Exemplo n.º 26
0
/* What each thread is doing
*
* In principle this is an endless loop. The only time this loop gets interuppted is once
* thpool_destroy() is invoked or the program exits.
*
* @param  thread        thread that will run this function
* @return nothing
*/
static void* thread_do(struct thread* thread_p){

	/* Set thread name for profiling and debuging */
	char thread_name[128] = {0};
	sprintf(thread_name, "thread-pool-%d", thread_p->id);

#if defined(__linux__)
	/* Use prctl instead to prevent using _GNU_SOURCE flag and implicit declaration */
	prctl(PR_SET_NAME, thread_name);
#elif defined(__APPLE__) && defined(__MACH__)
	pthread_setname_np(thread_name);
#else
	fprintf(stderr, "thread_do(): pthread_setname_np is not supported on this system");
#endif

	/* Assure all threads have been created before starting serving */
	thpool_* thpool_p = thread_p->thpool_p;

	/* Register signal handler */
	struct sigaction act;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	act.sa_handler = thread_hold;
	if (sigaction(SIGUSR1, &act, NULL) == -1) {
		fprintf(stderr, "thread_do(): cannot handle SIGUSR1");
	}

	/* Mark thread as alive (initialized) */
	pthread_mutex_lock(&thpool_p->thcount_lock);
	thpool_p->num_threads_alive += 1;
	pthread_mutex_unlock(&thpool_p->thcount_lock);

	while(threads_keepalive){

		bsem_wait(thpool_p->jobqueue_p->has_jobs);

		if (threads_keepalive){

			pthread_mutex_lock(&thpool_p->thcount_lock);
			thpool_p->num_threads_working++;
			pthread_mutex_unlock(&thpool_p->thcount_lock);

			/* Read job from queue and execute it */
			void*(*func_buff)(void* arg);
			void*  arg_buff;
			job* job_p;
			pthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex);
			job_p = jobqueue_pull(thpool_p);
			pthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex);
			if (job_p) {
				func_buff = job_p->function;
				arg_buff  = job_p->arg;
				func_buff(arg_buff);
				free(job_p);
			}

			pthread_mutex_lock(&thpool_p->thcount_lock);
			thpool_p->num_threads_working--;
			if (!thpool_p->num_threads_working) {
				pthread_cond_signal(&thpool_p->threads_all_idle);
			}
			pthread_mutex_unlock(&thpool_p->thcount_lock);

		}
	}
	pthread_mutex_lock(&thpool_p->thcount_lock);
	thpool_p->num_threads_alive --;
	pthread_mutex_unlock(&thpool_p->thcount_lock);

	return NULL;
}
//-----------------------------------------------------------------------------
int
pdcp_netlink_init(
  void
)
//-----------------------------------------------------------------------------
{

  int                i;
  int                nb_inst_enb;
  int                nb_inst_ue;
  pthread_attr_t     attr;
  struct sched_param sched_param;

  reset_meas(&ip_pdcp_stats_tmp);
#if defined(USER_MODE) && defined(OAI_EMU)
  nb_inst_enb = oai_emulation.info.nb_enb_local;
  nb_inst_ue  = oai_emulation.info.nb_ue_local;
#else
  nb_inst_enb = 1;
  nb_inst_ue  = 1;
#endif

#if defined(LINK_ENB_PDCP_TO_GTPV1U)
  nb_inst_enb = 0;
  LOG_I(PDCP, "[NETLINK] Creating 0 queues for eNB Netlink -> PDCP communication\n");
#else
#warning " LG: When there will be handover in, there will problems because dim is based on local nums of ues"
  pdcp_netlink_queue_enb      = calloc(nb_inst_enb, sizeof(struct lfds611_queue_state*));
  pdcp_netlink_nb_element_enb = malloc(nb_inst_enb * sizeof(uint32_t));
  LOG_I(PDCP, "[NETLINK] Creating %d queues for eNB Netlink -> PDCP communication\n", nb_inst_enb);

  for (i = 0; i < nb_inst_enb; i++) {
    pdcp_netlink_nb_element_enb[i] = 0;

    if (lfds611_queue_new(&pdcp_netlink_queue_enb[i], PDCP_QUEUE_NB_ELEMENTS) < 0) {
      LOG_E(PDCP, "Failed to create new FIFO for eNB Netlink -> PDCP communcation instance %d\n", i);
      exit(EXIT_FAILURE);
    }
  }

#endif

  if (nb_inst_ue  > 0) {
    pdcp_netlink_queue_ue       = calloc(nb_inst_ue, sizeof(struct lfds611_queue_state*));
    pdcp_netlink_nb_element_ue  = malloc(nb_inst_ue * sizeof(uint32_t));

    LOG_I(PDCP, "[NETLINK] Creating %d queues for UE Netlink -> PDCP communication\n", nb_inst_ue);

    for (i = 0; i < nb_inst_ue; i++) {
      pdcp_netlink_nb_element_ue[i] = 0;

      if (lfds611_queue_new(&pdcp_netlink_queue_ue[i], PDCP_QUEUE_NB_ELEMENTS) < 0) {
        LOG_E(PDCP, "Failed to create new FIFO for UE Netlink -> PDCP communcation instance %d\n", i);
        exit(EXIT_FAILURE);
      }
    }
  }

  if ((nb_inst_ue + nb_inst_enb) > 0) {
    if (pthread_attr_init(&attr) != 0) {
      LOG_E(PDCP, "[NETLINK]Failed to initialize pthread attribute for Netlink -> PDCP communication (%d:%s)\n",
            errno, strerror(errno));
      exit(EXIT_FAILURE);
    }

    sched_param.sched_priority = 10;

    pthread_attr_setschedpolicy(&attr, SCHED_RR);
    pthread_attr_setschedparam(&attr, &sched_param);

    /* Create one thread that fetchs packets from the netlink.
     * When the netlink fifo is full, packets are silently dropped, this behaviour
     * should be avoided if we want a reliable link.
     */
    if (pthread_create(&pdcp_netlink_thread, &attr, pdcp_netlink_thread_fct, NULL) != 0) {
      LOG_E(PDCP, "[NETLINK]Failed to create new thread for Netlink/PDCP communication (%d:%s)\n",
            errno, strerror(errno));
      exit(EXIT_FAILURE);
    }

    pthread_setname_np( pdcp_netlink_thread, "PDCP netlink" );
  }

  return 0;
}
Exemplo n.º 28
0
void logger::run()
{
    utxx::signal_block block_signals(m_block_signals);

    if (m_on_before_run)
        m_on_before_run();

    if (!m_ident.empty())
        pthread_setname_np(pthread_self(), m_ident.c_str());

    int event_val;
    do
    {
        event_val = m_event.value();
        //wakeup_result rc = wakeup_result::TIMEDOUT;

        while (!m_abort && m_queue.empty()) {
            m_event.wait(&m_wait_timeout, &event_val);

            ASYNC_DEBUG_TRACE(
                ("  %s LOGGER awakened (res=%s, val=%d, futex=%d), abort=%d, head=%s\n",
                 timestamp::to_string().c_str(), to_string(rc).c_str(),
                 event_val, m_event.value(), m_abort,
                 m_queue.empty() ? "empty" : "data")
            );
        }

        // When running with maximum priority, occasionally excessive use of
        // sched_yield may use to system slowdown, so this option is
        // configurable by m_sched_yield_us:
        if (m_queue.empty() && m_sched_yield_us >= 0) {
            time_val deadline(rel_time(0, m_sched_yield_us));
            while (m_queue.empty()) {
                if (m_abort)
                    goto DONE;
                if (now_utc() > deadline)
                    break;
                sched_yield();
            }
        }

        // Get all pending items from the queue
        for (auto* item = m_queue.pop_all(), *next=item; item; item = next) {
            next = item->next();

            try   {
                dolog_msg(item->data());
            }
            catch ( std::exception const& e  )
            {
                // Unhandled error writing data to some destination
                // Print error report to stderr (can't do anything better --
                // the error happened in the m_on_error callback!)
                const msg msg(LEVEL_INFO, "",
                              std::string("Fatal exception in logger"),
                              UTXX_LOG_SRCINFO);
                detail::basic_buffered_print<1024> buf;
                char  pfx[256], sfx[256];
                char* p = format_header(msg, pfx, pfx + sizeof(pfx));
                char* q = format_footer(msg, sfx, sfx + sizeof(sfx));
                auto ps = p - pfx;
                auto qs = q - sfx;
                buf.reserve(msg.m_fun.str.size() + ps + qs + 1);
                buf.sprint(pfx, ps);
                buf.print(msg.m_fun.str);
                buf.sprint(sfx, qs);
                std::cerr << buf.str() << std::endl;

                m_abort = true;

                // TODO: implement attempt to store transient messages to some
                // other medium

                // Free all pending messages
                while (item) {
                    m_queue.free(item);
                    item = next;
                    next = item->next();
                }

                goto DONE;
            }

            m_queue.free(item);
            item = next;
        }
    } while (!m_abort);

DONE:
    if (!m_silent_finish) {
        const msg msg(LEVEL_INFO, "", std::string("Logger thread finished"),
                      UTXX_LOG_SRCINFO);
        try {
            dolog_msg(msg);
        }
        catch (...) {}
    }

    if (m_on_after_run)
        m_on_after_run();
}
Exemplo n.º 29
0
TEST(pthread, pthread_setname_np__too_long) {
    ASSERT_EQ(ERANGE, pthread_setname_np(pthread_self(), "this name is far too long for linux"));
}
Exemplo n.º 30
0
/*
 * chitcpd_server_thread_func - Server thread function
 *
 * This function will spawn a handler thread (see handler.c) for each
 * new connection on the UNIX socket.
 *
 * args: arguments (a serverinfo_t variable in server_threads_args_t)
 *
 * Returns: Nothing.
 *
 */
void* chitcpd_server_thread_func(void *args)
{
    socklen_t sunSize;
    handler_thread_t *handler_thread;
    server_thread_args_t *sta;
    serverinfo_t *si;
    handler_thread_args_t *ha;
    list_t handler_thread_list;
    int rc;
    ChitcpdMsg *req;
    ChitcpdInitArgs *init_args;
    ChitcpdConnectionType conntype;
    ChitcpdMsg resp_outer = CHITCPD_MSG__INIT;
    ChitcpdResp resp_inner = CHITCPD_RESP__INIT;

    resp_outer.code = CHITCPD_MSG_CODE__RESP;
    resp_outer.resp = &resp_inner;

    /* For naming the handler threads we create (for debugging/logging) */
    int next_thread_id = 0;
    pthread_setname_np(pthread_self(), "unix_server");

    /* Unpack arguments */
    sta = (server_thread_args_t *) args;
    si = sta->si;

    list_init(&handler_thread_list);

    struct sockaddr_un client_addr;

    /* Accept connections on the UNIX socket */
    for(;;)
    {
        socket_t client_socket;

        /* Accept a connection */
        sunSize = sizeof(client_addr);
        if ((client_socket = accept(si->server_socket, (struct sockaddr *)&client_addr, &sunSize)) == -1)
        {
            /* If accept() returns in the CHITCPD_STATE_STOPPING, we don't
             * care what the error is. We just break out of the loop and
             * initiate an orderly shutdown. */
            if(si->state == CHITCPD_STATE_STOPPING)
                break;

            /* If this particular connection fails, no need to kill the entire thread. */
            perror("Could not accept() connection on UNIX socket");
            continue;
        }

        /* We receive a single message, which has to be an INIT message */
        rc = chitcpd_recv_msg(client_socket, &req);
        if (rc < 0)
        {
            if(si->state == CHITCPD_STATE_STOPPING)
                break;
            else
            {
                chilog(ERROR, "Error when receiving lead message through UNIX socket");
                shutdown(client_socket, SHUT_RDWR);
                continue;
            }
        }

        if(req->code != CHITCPD_MSG_CODE__INIT)
        {
            chilog(ERROR, "Expected INIT message, instead got message code %i", req->code);
            chitcpd_msg__free_unpacked(req, NULL);
            shutdown(client_socket, SHUT_RDWR);
            continue;
        }

        /* Unpack INIT request */
        assert(req->init_args != NULL);
        init_args = req->init_args;

        conntype = init_args->connection_type;


        /* There are two types of connections: command connections and debug
         * connections.
         *
         * When a command connection is created, a new thread is created to
         * handle the incoming chisocket commands on that connection (socket,
         * send, recv, etc.)
         *
         * When a debug connection is created, no additional thread is necessary.
         * The connection on the UNIX socket is simply "handed off" to a
         * debug monitor that will be associated with a chiTCP socket.
         * That UNIX socket is then used to send back debug messages.
         */

        if (conntype == CHITCPD_CONNECTION_TYPE__COMMAND_CONNECTION)
        {
            /* Create arguments for handler thread */
            ha = malloc(sizeof(handler_thread_args_t));
            ha->si = si;

            handler_thread = malloc(sizeof(handler_thread_t));
            handler_thread->handler_socket = client_socket;
            pthread_mutex_init(&handler_thread->handler_lock, NULL);

            /* Create handler thread to handle this connection */
            ha->client_socket = handler_thread->handler_socket;
            ha->handler_lock = &handler_thread->handler_lock;
            snprintf(ha->thread_name, 16, "handler-%d", next_thread_id++);
            if (pthread_create(&handler_thread->thread, NULL, chitcpd_handler_dispatch, ha) != 0)
            {
                perror("Could not create a worker thread");

                resp_outer.resp->ret = CHITCP_ETHREAD;
                resp_outer.resp->error_code = 0;
                rc = chitcpd_send_msg(client_socket, &resp_outer);

                free(ha);
                close(ha->client_socket);
                close(si->server_socket);
                // TODO: Perform an orderly shutdown instead of exiting
                pthread_exit(NULL);
            }
            resp_outer.resp->ret = CHITCP_OK;
            resp_outer.resp->error_code = 0;
            rc = chitcpd_send_msg(client_socket, &resp_outer);

            list_append(&handler_thread_list, handler_thread);
        }
        else if(conntype == CHITCPD_CONNECTION_TYPE__DEBUG_CONNECTION)
        {
            int debug_sockfd, debug_event_flags;
            ChitcpdDebugArgs *debug_args;

            /* Unpack debug parameter */
            assert(init_args->debug != NULL);
            debug_args = init_args->debug;

            debug_sockfd = debug_args->sockfd;
            debug_event_flags = debug_args->event_flags;

            rc = chitcpd_init_debug_connection(si, debug_sockfd, debug_event_flags, client_socket);
            if(rc == CHITCP_OK)
            {
                resp_outer.resp->ret = CHITCP_OK;
                resp_outer.resp->error_code = 0;
                rc = chitcpd_send_msg(client_socket, &resp_outer);
            }
            else
            {
                chilog(ERROR, "Error when creating debug connection for socket %i", debug_sockfd);
                resp_outer.resp->ret = CHITCP_EINIT;
                resp_outer.resp->error_code = rc;
                rc = chitcpd_send_msg(client_socket, &resp_outer);

                shutdown(client_socket, SHUT_RDWR);
            }
        }
        else
        {
            chilog(ERROR, "Received INIT message with unknown connection type %i", conntype);
            resp_outer.resp->ret = CHITCP_EINVAL;
            resp_outer.resp->error_code = 0;
            rc = chitcpd_send_msg(client_socket, &resp_outer);
            shutdown(client_socket, SHUT_RDWR);
        }

        chitcpd_msg__free_unpacked(req, NULL);
    }

    while(!list_empty(&handler_thread_list))
    {
        /* For each handler thread we spawned, we close its socket, which
         * will force the thread to exit (and we then join it).
         *
         * Note that closing a handler thread will also free up all chiTCP
         * sockets created through that thread, and will also terminate
         * all associated TCP threads.
         *
         * TODO: We should simply detach those threads, since they can exit
         * before an orderly shutdown and would be left lingering until
         * we call join here. */
        handler_thread_t *ht = list_fetch(&handler_thread_list);

        /* We don't want to shutdown the handler's socket if an operation is
         * in progress. The handler thread may have read a command, but
         * not sent a response back yet */
        pthread_mutex_lock(&ht->handler_lock);
        shutdown(ht->handler_socket, SHUT_RDWR);
        pthread_mutex_unlock(&ht->handler_lock);
        pthread_join(ht->thread, NULL);
        pthread_mutex_destroy(&ht->handler_lock);
        free(ht);
    }

    list_destroy(&handler_thread_list);

    pthread_exit(NULL);
}