Example #1
0
static InterruptMemberNumber
hard_irq( InterruptSetMember ISTmember, void *ref_con, UInt32 the_int_count )
{
	channel_t *ch = channels;	/* fixme */
	int running, compl_cnt, event;
	request_t *r;
	
	/* Note: Q & A DV 34 explicitly forbids the usage of secondary
	 * interrupts on the page-fault path (it leads to deadlocks).
	 */
	/* Note: The OSI call _always_ modifies the return arguments */
	if( !OSI_ABlkIRQAck( ch->channel, &compl_cnt, &running, &event ) )
		return kIsrIsNotComplete;

	ch->running = running;

	if( event )
		handle_events( ch );

	/* handle overflow buffer */
	if( ch->obuf_cnt && compl_cnt - ch->obuf_completion >= 0 ) {
		if( ch->obuf_dest ) {
			char *dest = ch->obuf_dest, *src = ch->obuf;
			int cnt = ch->obuf_cnt;
			while( cnt-- )
				*dest++ = *src++;
		}
		/* XXX: insert optimization barrier here */
		*(volatile int*)&ch->obuf_cnt = 0;
	}

	/* process completions */
	while( (r=(request_t*)dequeue(&ch->compl_queue)) ) {
		IOCommandID cmdID;

		if( r->req_num - compl_cnt > 0 ) {
			enqueue_tail( &ch->compl_queue, (queue_el_t*)r );
			break;
		}
		/* free resources... */
		if( r->mem_prepared )
			CheckpointIO( r->ioprep.preparationID, 0 );

		if( r->ablk_req & (ABLK_READ_REQ | ABLK_WRITE_REQ) )
			((IOParam*)r->pb)->ioActCount = r->xfer_cnt;
		
		cmdID = r->cmdID;
		fifo_put( &ch->free_fifo, (fifo_el_t*)r );

		/* ...and complete */
		IOCommandIsComplete( cmdID, noErr );
	}
	process_request_queue( ch );

	return kIsrIsComplete;
}
Example #2
0
OSStatus
queue_req( ParamBlockRec *pb, unit_t *unit, int ablk_req, int param, char *buf, int cnt, IOCommandID ioCmdID )
{
	channel_t *ch = unit->ch;
	request_t *r;

	while( !(r=(request_t*)fifo_get( &ch->free_fifo )) ) {
		/* as long as interrupts are on, the fifo ought to fill up */
		lprintf("ablk: free_queue exhausted!\n");
	}

	r->unit = unit->unit;
	r->ablk_req = ablk_req;
	r->param = param;
	r->total_cnt = cnt;
	r->xfer_cnt = -1;
	r->pb = pb;
	r->cmdID = ioCmdID;

	if( cnt && !PrepareMemory(r, buf) ) {
		r->mem_prepared = 1;
	} else {
		r->ioprep.lengthPrepared = 0;
		r->mem_prepared = 0;
	}
	enqueue( &ch->req_queue, (queue_el_t*)r );
	process_request_queue( ch );

#ifdef SYNC_HACK
	/* HACK. This workaround removes a QuickTime problem. Without it,
	 * QT behaves very strangely when mp3s (and movies) are played.
	 * The symptom is that the same disk sector is read 10-20 times
	 * (causing considerable CPU load and sound skips).
	 * Note that the hack is turned off _before_ the QT player 
	 * is started. I have no idea why this magically solves the problem...
	 */
	if( !sync_event_sent && ch->req_count >= 5000 ) {
		sync_event_sent = 1;
		DNeedTime( turn_off_sync, 0, 0 );
	}
	if( !no_sync_hack ) {
		while( *(int volatile *)&ch->running )
			;
	}
#endif

	return ioInProgress;
}
Example #3
0
void connection_accept_loop(void)
{
    connection_t *con;

    if (!kitsune_is_updating()) /**DSU control */
        tid = thread_create("connection thread", _handle_connection, NULL, THREAD_ATTACHED);

    while (global.running == ICE_RUNNING)
    {
      kitsune_update("connection_accept"); /**DSU updatepoint */

        con = _accept_connection();

        if (con)
        {
            client_queue_t *node;
            ice_config_t *config;
            int i;
            client_t *client = NULL;

            global_lock();
            if (client_create (&client, con, NULL) < 0)
            {
                global_unlock();
                client_send_404 (client, "Icecast connection limit reached");
                continue;
            }
            global_unlock();

            /* setup client for reading incoming http */
            client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';

            node = calloc (1, sizeof (client_queue_t));
            if (node == NULL)
            {
                client_destroy (client);
                continue;
            }
            node->client = client;

            /* Check for special shoutcast compatability processing */
            config = config_get_config();
            for (i = 0; i < global.server_sockets; i++)
            {
                if (global.serversock[i] == con->serversock)
                {
                    if (config->listeners[i].shoutcast_compat)
                        node->shoutcast = 1;
                }
            }
            config_release_config(); 

            sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
            sock_set_nodelay (client->con->sock);

            _add_request_queue (node);
            stats_event_inc (NULL, "connections");
        }
        process_request_queue ();
    }

    /* Give all the other threads notification to shut down */
    thread_cond_broadcast(&global.shutdown_cond);

    if (tid)
        thread_join (tid);

    /* wait for all the sources to shutdown */
    thread_rwlock_wlock(&_source_shutdown_rwlock);
    thread_rwlock_unlock(&_source_shutdown_rwlock);
}
Example #4
0
void connection_accept_loop (void)
{
    connection_t *con;
    ice_config_t *config;
    int duration = 300;

    config = config_get_config ();
    get_ssl_certificate (config);
    config_release_config ();

    while (global.running == ICE_RUNNING)
    {
        con = _accept_connection (duration);

        if (con)
        {
            client_queue_t *node;
            ice_config_t *config;
            client_t *client = NULL;
            listener_t *listener;

            global_lock();
            if (client_create (&client, con, NULL) < 0)
            {
                global_unlock();
                client_send_403 (client, "Icecast connection limit reached");
                /* don't be too eager as this is an imposed hard limit */
                thread_sleep (400000);
                continue;
            }

            /* setup client for reading incoming http */
            client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';

            if (sock_set_blocking (client->con->sock, 0) || sock_set_nodelay (client->con->sock))
            {
                global_unlock();
                WARN0 ("failed to set tcp options on client connection, dropping");
                client_destroy (client);
                continue;
            }

            node = calloc (1, sizeof (client_queue_t));
            if (node == NULL)
            {
                global_unlock();
                client_destroy (client);
                continue;
            }
            node->client = client;

            config = config_get_config();
            listener = config_get_listen_sock (config, client->con);

            if (listener)
            {
                if (listener->shoutcast_compat)
                    node->shoutcast = 1;
                if (listener->ssl && ssl_ok)
                    connection_uses_ssl (client->con);
                if (listener->shoutcast_mount)
                    node->shoutcast_mount = strdup (listener->shoutcast_mount);
            }
            global_unlock();
            config_release_config();

            _add_request_queue (node);
            stats_event_inc (NULL, "connections");
            duration = 5;
        }
        else
        {
            if (_req_queue == NULL)
                duration = 300; /* use longer timeouts when nothing waiting */
        }
        process_request_queue ();
    }

    /* Give all the other threads notification to shut down */
    thread_cond_broadcast(&global.shutdown_cond);

    /* wait for all the sources to shutdown */
    thread_rwlock_wlock(&_source_shutdown_rwlock);
    thread_rwlock_unlock(&_source_shutdown_rwlock);
}
Example #5
0
void connection_accept_loop(void)
{
    connection_t *con;
    ice_config_t *config;

    config = config_get_config ();
    get_ssl_certificate (config);
    config_release_config ();

    tid = thread_create ("connection thread", _handle_connection, NULL, THREAD_ATTACHED);

    while (global.running == ICE_RUNNING)
    {
        con = _accept_connection();

        if (con)
        {
            client_queue_t *node;
            ice_config_t *config;
            client_t *client = NULL;
            listener_t *listener;

            global_lock();
            if (client_create (&client, con, NULL) < 0)
            {
                global_unlock();
                client_send_403 (client, "Icecast connection limit reached");
                /* don't be too eager as this is an imposed hard limit */
                thread_sleep (400000);
                continue;
            }
            global_unlock();

            /* setup client for reading incoming http */
            client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';

            node = calloc (1, sizeof (client_queue_t));
            if (node == NULL)
            {
                client_destroy (client);
                continue;
            }
            node->client = client;

            config = config_get_config();
            listener = config_get_listen_sock (config, client->con);

            if (listener)
            {
                if (listener->shoutcast_compat)
                    node->shoutcast = 1;
                if (listener->ssl && ssl_ok)
                    connection_uses_ssl (client->con);
                if (listener->shoutcast_mount)
                    node->shoutcast_mount = strdup (listener->shoutcast_mount);
            }
            config_release_config();

            sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
            sock_set_nodelay (client->con->sock);

            _add_request_queue (node);
            stats_event_inc (NULL, "connections");
        }
        process_request_queue ();
    }

    /* Give all the other threads notification to shut down */
    thread_cond_broadcast(&global.shutdown_cond);

    if (tid)
        thread_join (tid);

    /* wait for all the sources to shutdown */
    thread_rwlock_wlock(&_source_shutdown_rwlock);
    thread_rwlock_unlock(&_source_shutdown_rwlock);
}