static void start_threads(void) { long i, n; /* Create access log flushing thread */ if (log_access && st_thread_create(flush_acclog_buffer, NULL, 0, 0) == NULL) err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create" " log flushing thread", my_index, my_pid); /* Create connections handling threads */ for (i = 0; i < sk_count; i++) { err_report(errfd, "INFO: process %d (pid %d): starting %d threads" " on %s:%u", my_index, my_pid, max_wait_threads, srv_socket[i].addr, srv_socket[i].port); WAIT_THREADS(i) = 0; BUSY_THREADS(i) = 0; RQST_COUNT(i) = 0; for (n = 0; n < max_wait_threads; n++) { if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL) WAIT_THREADS(i)++; else err_sys_report(errfd, "ERROR: process %d (pid %d): can't create" " thread", my_index, my_pid); } if (WAIT_THREADS(i) == 0) exit(1); } }
static void dump_server_info(void) { char *buf; int i, len; if ((buf = malloc(sk_count * 512)) == NULL) { err_sys_report(errfd, "ERROR: malloc failed"); return; } len = sprintf(buf, "\n\nProcess #%d (pid %d):\n", my_index, (int)my_pid); for (i = 0; i < sk_count; i++) { len += sprintf(buf + len, "\nListening Socket #%d:\n" "-------------------------\n" "Address %s:%u\n" "Thread limits (min/max) %d/%d\n" "Waiting threads %d\n" "Busy threads %d\n" "Requests served %d\n", i, srv_socket[i].addr, srv_socket[i].port, max_wait_threads, max_threads, WAIT_THREADS(i), BUSY_THREADS(i), RQST_COUNT(i)); } write(STDERR_FILENO, buf, len); free(buf); }
static void *handle_connections(void *arg) { st_netfd_t srv_nfd, cli_nfd; struct sockaddr_in from; int fromlen; long i = (long) arg; srv_nfd = srv_socket[i].nfd; fromlen = sizeof(from); while (WAIT_THREADS(i) <= max_wait_threads) { cli_nfd = st_accept(srv_nfd, (struct sockaddr *)&from, &fromlen, ST_UTIME_NO_TIMEOUT); if (cli_nfd == NULL) { err_sys_report(errfd, "ERROR: can't accept connection: st_accept"); continue; } /* Save peer address, so we can retrieve it later */ st_netfd_setspecific(cli_nfd, &from.sin_addr, NULL); WAIT_THREADS(i)--; BUSY_THREADS(i)++; if (WAIT_THREADS(i) < min_wait_threads && TOTAL_THREADS(i) < max_threads) { /* Create another spare thread */ if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL) WAIT_THREADS(i)++; else err_sys_report(errfd, "ERROR: process %d (pid %d): can't create" " thread", my_index, my_pid); } handle_session(i, cli_nfd); st_netfd_close(cli_nfd); WAIT_THREADS(i)++; BUSY_THREADS(i)--; } WAIT_THREADS(i)--; return NULL; }
int main(int ac, char **av) { int i, ret = 0; int max_queue_size; int nb_senders, sender_min_load, sender_max_load; int nb_receivers, receiver_min_load, receiver_max_load; struct sender_data *senders; struct receiver_data *receivers; AVThreadMessageQueue *queue = NULL; if (ac != 8) { av_log(NULL, AV_LOG_ERROR, "%s <max_queue_size> " "<nb_senders> <sender_min_send> <sender_max_send> " "<nb_receivers> <receiver_min_recv> <receiver_max_recv>\n", av[0]); return 1; } max_queue_size = atoi(av[1]); nb_senders = atoi(av[2]); sender_min_load = atoi(av[3]); sender_max_load = atoi(av[4]); nb_receivers = atoi(av[5]); receiver_min_load = atoi(av[6]); receiver_max_load = atoi(av[7]); if (max_queue_size <= 0 || nb_senders <= 0 || sender_min_load <= 0 || sender_max_load <= 0 || nb_receivers <= 0 || receiver_min_load <= 0 || receiver_max_load <= 0) { av_log(NULL, AV_LOG_ERROR, "negative values not allowed\n"); return 1; } av_log(NULL, AV_LOG_INFO, "qsize:%d / %d senders sending [%d-%d] / " "%d receivers receiving [%d-%d]\n", max_queue_size, nb_senders, sender_min_load, sender_max_load, nb_receivers, receiver_min_load, receiver_max_load); senders = av_mallocz_array(nb_senders, sizeof(*senders)); receivers = av_mallocz_array(nb_receivers, sizeof(*receivers)); if (!senders || !receivers) { ret = AVERROR(ENOMEM); goto end; } ret = av_thread_message_queue_alloc(&queue, max_queue_size, sizeof(struct message)); if (ret < 0) goto end; av_thread_message_queue_set_free_func(queue, free_frame); #define SPAWN_THREADS(type) do { \ for (i = 0; i < nb_##type##s; i++) { \ struct type##_data *td = &type##s[i]; \ \ td->id = i; \ td->queue = queue; \ td->workload = get_workload(type##_min_load, type##_max_load); \ \ ret = pthread_create(&td->tid, NULL, type##_thread, td); \ if (ret) { \ const int err = AVERROR(ret); \ av_log(NULL, AV_LOG_ERROR, "Unable to start " AV_STRINGIFY(type) \ " thread: %s\n", av_err2str(err)); \ goto end; \ } \ } \ } while (0) #define WAIT_THREADS(type) do { \ for (i = 0; i < nb_##type##s; i++) { \ struct type##_data *td = &type##s[i]; \ \ ret = pthread_join(td->tid, NULL); \ if (ret) { \ const int err = AVERROR(ret); \ av_log(NULL, AV_LOG_ERROR, "Unable to join " AV_STRINGIFY(type) \ " thread: %s\n", av_err2str(err)); \ goto end; \ } \ } \ } while (0) SPAWN_THREADS(receiver); SPAWN_THREADS(sender); WAIT_THREADS(sender); WAIT_THREADS(receiver); end: av_thread_message_queue_free(&queue); av_freep(&senders); av_freep(&receivers); if (ret < 0 && ret != AVERROR_EOF) { av_log(NULL, AV_LOG_ERROR, "Error: %s\n", av_err2str(ret)); return 1; } return 0; }