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; }
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; }
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); }
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); }
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); }