manoj 99/02/21 23:49:34
Modified: pthreads/src/include fdqueue.h pthreads/src/main fdqueue.c http_main.c Log: Change the fdqueue's handling of blocking when there are no idle threads. Advantages: - We used to add to the queue before checking if it was full. Fixed. - The server was responding to almost no requests. I think the above is why. - The fdqueue no longer requires that the space allocated for the queue be equal to the number of worker threads. This means that if we want to change scheduling policies in the future to allow a changing number of worker threads in the future, we can do so. Revision Changes Path 1.4 +1 -1 apache-apr/pthreads/src/include/fdqueue.h Index: fdqueue.h =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/include/fdqueue.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -u -r1.3 -r1.4 --- fdqueue.h 1999/02/19 20:33:21 1.3 +++ fdqueue.h 1999/02/22 07:49:32 1.4 @@ -25,6 +25,7 @@ int bounds; int blanks; pthread_mutex_t one_big_mutex; + pthread_cond_t thread_is_idle; pthread_cond_t not_empty; pthread_cond_t not_full; } FDQueue; @@ -34,6 +35,5 @@ int queue_push(FDQueue *queue, int fd, struct sockaddr *addr); int queue_pop(FDQueue *queue, struct sockaddr *addr); int queue_size(FDQueue *queue); -int increase_blanks(FDQueue *queue); #endif /* FDQUEUE_H */ 1.9 +30 -19 apache-apr/pthreads/src/main/fdqueue.c Index: fdqueue.c =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/main/fdqueue.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -u -r1.8 -r1.9 --- fdqueue.c 1999/02/21 03:20:05 1.8 +++ fdqueue.c 1999/02/22 07:49:33 1.9 @@ -6,12 +6,15 @@ int queue_init(FDQueue *queue, size_t bounds, pool *a) { int i; pthread_mutex_init(&queue->one_big_mutex, NULL); + pthread_cond_init(&queue->thread_is_idle, NULL); pthread_cond_init(&queue->not_empty, NULL); pthread_cond_init(&queue->not_full, NULL); queue->head = queue->tail = 0; + /* Note, bounds is being increased to account for the bookkeeping slot */ queue->data = ap_palloc(a, (++bounds) * sizeof(FDQueueElement)); queue->bounds = bounds; - queue->blanks = bounds - 1; + /* A thread isn't idle until it has asked for a connection */ + queue->blanks = 0; ap_register_cleanup(a, queue, (void (*)(void *))queue_destroy, ap_null_cleanup); for (i=0; i < bounds; ++i) queue->data[i].fd = -1; @@ -20,6 +23,7 @@ void *queue_destroy(FDQueue *queue) { /* Ignore errors here, we can't do anything about them anyway */ + pthread_cond_destroy(&queue->thread_is_idle); pthread_cond_destroy(&queue->not_empty); pthread_cond_destroy(&queue->not_full); pthread_mutex_destroy(&queue->one_big_mutex); @@ -29,17 +33,29 @@ if (pthread_mutex_lock(&queue->one_big_mutex) != 0) { return FD_QUEUE_FAILURE; } + while (queue->head == ((queue->tail + 1) % queue->bounds)) { + pthread_cond_wait(&queue->not_full, &queue->one_big_mutex); + } queue->data[queue->tail].fd = fd; queue->data[queue->tail].addr = *addr; + /* If the queue was empty, signal that it no longer is */ + /* if (queue->head == queue->tail) { */ + pthread_cond_signal(&queue->not_empty); + /* } */ queue->tail = (queue->tail + 1) % queue->bounds; queue->blanks--; - pthread_cond_signal(&queue->not_empty); - if (queue->blanks == 0) { - pthread_cond_wait(&queue->not_full, &queue->one_big_mutex); + + /* If the content in the queue is enough to satisfy all of our threads, + * then wait until this is no longer the case so that we don't accept + * connections we can't handle */ + while (queue->blanks <= 0) { + pthread_cond_wait(&queue->thread_is_idle, &queue->one_big_mutex); } + if (pthread_mutex_unlock(&queue->one_big_mutex) != 0) { return FD_QUEUE_FAILURE; } + return FD_QUEUE_SUCCESS; } int queue_pop(FDQueue *queue, struct sockaddr *addr) { @@ -47,7 +63,13 @@ if (pthread_mutex_lock(&queue->one_big_mutex) != 0) { return FD_QUEUE_FAILURE; } - if (queue->blanks >= queue->bounds - 1) { + + if (queue->blanks <= 0) { + pthread_cond_signal(&queue->thread_is_idle); + } + queue->blanks++; + + if (queue->head == queue->tail) { pthread_cond_wait(&queue->not_empty, &queue->one_big_mutex); } @@ -55,25 +77,14 @@ *addr = queue->data[queue->head].addr; queue->data[queue->head].fd = -1; /* If the queue was full, signal that it no longer is */ - queue->head = (queue->head + 1) % queue->bounds; - if (pthread_mutex_unlock(&queue->one_big_mutex) != 0) { - return FD_QUEUE_FAILURE; - } - return fd; -} - -int increase_blanks(FDQueue *queue) { - if (pthread_mutex_lock(&queue->one_big_mutex) != 0) { - return FD_QUEUE_FAILURE; - } - if (queue->blanks == 0) { + if (queue->head == ((queue->tail + 1) % queue->bounds)) { pthread_cond_signal(&queue->not_full); } - queue->blanks++; + queue->head = (queue->head + 1) % queue->bounds; if (pthread_mutex_unlock(&queue->one_big_mutex) != 0) { return FD_QUEUE_FAILURE; } - return FD_QUEUE_SUCCESS; + return fd; } int queue_size(FDQueue *queue) { 1.51 +0 -1 apache-apr/pthreads/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/main/http_main.c,v retrieving revision 1.50 retrieving revision 1.51 diff -u -u -r1.50 -r1.51 --- http_main.c 1999/02/19 20:35:41 1.50 +++ http_main.c 1999/02/22 07:49:33 1.51 @@ -2379,7 +2379,6 @@ csd = queue_pop(&csd_queue, &sa_client); if (csd >= 0) { process_socket(ptrans, &sa_client, csd, my_pid, my_tid); - increase_blanks(&csd_queue); } ap_clear_pool(ptrans); }