Squid aiops. c multi-thread Io understanding

Source: Internet
Author: User

// Initialize AIO. Create an AIO disk Io thread Based on the configuration file
Void
Squidaio_init (void)
{
Int I;
Int done_pipe [2];
Squidaio_thread_t * threadp;

If (squidaio_initialised)
Return;

Pthread_attr_init (& globattr );
# If have_pthread_attr_setscope
Pthread_attr_setscope (& globattr, pthread_scope_system );
# Endif
# If have_sched_h
Globsched. sched_priority = 1;
# Endif
Main_thread = pthread_self ();
# If have_sched_h & have_pthread_setschedparam
Pthread_setschedparam (main_thread, sched_other, & globsched );
# Endif
# If have_sched_h
Globsched. sched_priority = 2;
# Endif
# If have_sched_h & have_pthread_attr_setschedparam
Pthread_attr_setschedparam (& globattr, & globsched );
# Endif

/* Give each thread a smaller 256kb stack, shocould be more than sufficient */
Pthread_attr_setstacksize (& globattr, 256*1024 );

/* Initialize Request queue */
If (pthread_mutex_init (& (request_queue.mutex), null ))
Libcore_fatalf ("failed to create mutex ");
If (pthread_cond_init (& (request_queue.cond), null ))
Libcore_fatalf ("failed to create condition variable ");
Request_queue.head = NULL;
Request_queue.tailp = & request_queue.head;
Request_queue.requests = 0;
Request_queue.blocked = 0;

/* Initialize done queue */
If (pthread_mutex_init (& (done_queue.mutex), null ))
Libcore_fatalf ("failed to create mutex ");
If (pthread_cond_init (& (done_queue.cond), null ))
Libcore_fatalf ("failed to create condition variable ");
Done_queue.head = NULL;
Done_queue.tailp = & done_queue.head;
Done_queue.requests = 0;
Done_queue.blocked = 0;

/* Initialize done pipe signal */
Pipe (done_pipe );
Done_fd = done_pipe [1];
Done_fd_read = done_pipe [0];
Fd_open (done_fd_read, fd_pipe, "async-io completion event: Main ");
Fd_open (done_fd, fd_pipe, "async-io completion event: Threads ");
Commsetnonblocking (done_pipe [0]);
Commsetnonblocking (done_pipe [1]);
Commsetcloseonexec (done_pipe [0]);
Commsetcloseonexec (done_pipe [1]);
Commsetselect (done_pipe [0], comm_select_read, squidaio_fdhandler, null, 0 );

/* Create threads and get them to sit in their wait loop */
Squidaio_thread_pool = mempoolcreate ("aio_thread", sizeof (squidaio_thread_t ));

/* Default to basing the thread count on thread_factor and aiops_default_ndirs */
If (squidaio_nthreads = 0 ){
Int J = thread_factor;
For (I = 0; I <aiops_default_ndirs; I ++ ){
Squidaio_nthreads + = J;
J = J * 2/3;
If (j <4)
J = 4;
}
}
If (squidaio_nthreads = 0)
Squidaio_nthreads = thread_factor;
Squidaio_magic1 = squidaio_nthreads * magic1_factor;
Squidaio_magic2 = squidaio_nthreads * magic2_factor;
For (I = 0; I <squidaio_nthreads; I ++ ){
Threadp = mempoolalloc (squidaio_thread_pool );
Threadp-> Status = _ thread_starting;
Threadp-> current_req = NULL;
Threadp-> requests = 0;
Threadp-> next = threads;
Threads = threadp;
If (pthread_create (& threadp-> thread, & globattr, squidaio_thread_loop, threadp )){
Fprintf (stderr, "thread creation failed \ n ");
Threadp-> Status = _ thread_failed;
Continue;
}
}

/* CREATE request pool */
Squidaio_request_pool = mempoolcreate ("aio_request", sizeof (squidaio_request_t ));

Squidaio_initialised = 1;
}

// Thread processing function

Static void *
Squidaio_thread_loop (void * PTR)
{
Squidaio_thread_t * threadp = PTR;
Squidaio_request_t * request;
Sigset_t new;

/*
* Make sure to ignore signals which may possibly get sent
* The parent squid thread. causes havoc with mutex's and
* Condition waits otherwise
*/
// Clear the signal space

Sigemptyset (& New );

// Add a new signal to the signal space

Sigaddset (& New, sigpipe );
Sigaddset (& New, sigchld );
# Ifdef _ squid_linux_threads _
Sigaddset (& New, sigquit );
Sigaddset (& New, sigtrap );
# Else
Sigaddset (& New, SIGUSR1 );
Sigaddset (& New, sigusr2 );
# Endif
Sigaddset (& New, sighup );
Sigaddset (& New, sigterm );
Sigaddset (& New, SIGINT );

Sigaddset (& New, sigalrm );

// Block the signal mask

Pthread_sigmask (sig_block, & New, null );

While (1 ){
Threadp-> current_req = request = NULL;
Request = NULL;
/* Get a request to process */
Threadp-> Status = _ thread_waiting;

Pthread_mutex_lock (& request_queue.mutex );

// View the Request queue cyclically, if not null. Unlock and check whether there is a signal request. If not, enter the sleep status and wait for the signal.

While (! Request_queue.head ){
Pthread_cond_wait (& request_queue.cond, & request_queue.mutex );

}

// The request just processed

Request = request_queue.head;
If (request)

Request_queue.head = request-> next;

// Process. If request_queue is empty, set the end of request_queue to the header after reinitialization.

If (! Request_queue.head)

Request_queue.tailp = & request_queue.head;

// Unlock to process the request. Sets the status of the current thread. Different AIO processes are called based on different types of requests.

Pthread_mutex_unlock (& request_queue.mutex );
/* Process the request */
Threadp-> Status = _ thread_busy;
Request-> next = NULL;
Threadp-> current_req = request;
Errno = 0;
If (! Request-> canceled ){
Switch (request-> REQUEST_TYPE ){
Case _ aio_op_open:
Squidaio_do_open (request );
Break;
Case _ aio_op_read:
Squidaio_do_read (request );
Break;
Case _ aio_op_write:
Squidaio_do_write (request );
Break;
Case _ aio_op_close:
Squidaio_do_close (request );
Break;
Case _ aio_op_unlink:
Squidaio_do_unlink (request );
Break;
Case _ aio_op_truncate:
Squidaio_do_truncate (request );
Break;
# If aio_opendir/* opendir not implemented yet */
Case _ aio_op_opendir:
Squidaio_do_opendir (request );
Break;
# Endif
Case _ aio_op_stat:
Squidaio_do_stat (request );
Break;
Default:
Request-> ret =-1;
Request-> err = einval;
Break;
}
} Else {/* canceled */
Request-> ret =-1;
Request-> err = eintr;
}
Threadp-> Status = _ thread_done;

/* Put the request in the done queue */

// Lock the request and put it in the Completion queue to unlock

Pthread_mutex_lock (& done_queue.mutex );
* Done_queue.tailp = request;
Done_queue.tailp = & request-> next;
Pthread_mutex_unlock (& done_queue.mutex );
If (! Done_signalled ){
Done_signalled = 1;
Fd_write_method (done_fd ,"! ", 1 );
}
Threadp-> requests ++;
}/* While forever */
Return NULL;

}/* Squidaio_thread_loop */

// Squid AIO Request queue

Static void
Squidaio_queue_request (squidaio_request_t * request)
{
Static int high_start = 0;
Debug (43, 9) ("squidaio_queue_request: % P type = % d result = % P \ n ",
Request, request-> REQUEST_TYPE, request-> resultp );
/* Mark it as not executed (failing result, no error )*/
Request-> ret =-1;
Request-> err = 0;
/* Internal housekeeping */
Request_queue_len + = 1;
Request-> resultp-> _ DATA = request;
/* Play some tricks with the request_queue2 queue */

Request-> next = NULL;

// If the request queue is null (request_queue2 blocks the queue)

If (! Request_queue2.head ){

// If the request queue is successfully locked (normal)

If (pthread_mutex_trylock (& request_queue.mutex) = 0 ){

/* Normal path */

// Assign a value to the next of the last request in the queue

// Assign the value of tail to the next request

* Request_queue.tailp = request;

Request_queue.tailp = & request-> next;

// Send a signal to the blocked wait state and unlock it

Pthread_cond_signal (& request_queue.cond );
Pthread_mutex_unlock (& request_queue.mutex );
} Else {

/* Oops, the request queue is blocked, use request_queue2 */

// If the lock fails, add the request to the queue 2

* Request_queue2.tailp = request;
Request_queue2.tailp = & request-> next;
}
} Else {
/* Secondary path. We have blocked requests to deal */

/* Add the request to the chain */

// If request_queue2 is not empty, add the request to the Request queue 2.

* Request_queue2.tailp = request;
If (pthread_mutex_trylock (& request_queue.mutex) = 0 ){
/* OK, the queue is no longer blocked */
* Request_queue.tailp = request_queue2.head;
Request_queue.tailp = & request-> next;
Pthread_cond_signal (& request_queue.cond );
Pthread_mutex_unlock (& request_queue.mutex );
Request_queue2.head = NULL;
Request_queue2.tailp = & request_queue2.head;
} Else {
/* Still blocked, bump the blocked request chain */
Request_queue2.tailp = & request-> next;
}
}
If (request_queue2.head ){
Static int filter = 0;
Static int filter_limit = 8;
If (++ filter> = filter_limit ){
Filter_limit + = filter;
Filter = 0;
Debug (43, 1) ("squidaio_queue_request: Warning-queue congestion \ n ");
}
}

/* Warn if out of threads */

// If the thread warning is exceeded

If (request_queue_len> magic1 ){
Static int last_warn = 0;
Static int queue_high, queue_low;
If (high_start = 0 ){
High_start = squid_curtime;
Queue_high = request_queue_len;
Queue_low = request_queue_len;
}
If (request_queue_len> queue_high)
Queue_high = request_queue_len;
If (request_queue_len <queue_low)
Queue_low = request_queue_len;
If (squid_curtime >=( last_warn + 15 )&&
Squid_curtime> = (high_start + 5 )){
Debug (43, 1) ("squidaio_queue_request: Warning-disk I/O overloading \ n ");
If (squid_curtime> = (high_start + 15 ))
Debug (43, 1) ("squidaio_queue_request: queue length: Current = % d, high = % d, low = % d, duration = % LD \ n ",
Request_queue_len, queue_high, queue_low, (long INT) (squid_curtime-high_start ));
Last_warn = squid_curtime;
}
} Else {
High_start = 0;
}
/* Warn if seriously overloaded */
If (request_queue_len> ridiculous_length ){
Debug (43, 0) ("squidaio_queue_request: async Request queue growing uncontrollably! \ N ");
Debug (43, 0) ("squidaio_queue_request: syncing pending I/O operations... (blocking) \ n ");
Squidaio_sync ();
Debug (43, 0) ("squidaio_queue_request: synced \ n ");
}
}/* Squidaio_queue_request */

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.