2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\r
8 * Redistribution and use in source and binary forms, with or
\r
9 * without modification, are permitted provided that the following
\r
10 * conditions are met:
\r
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\r
16 * - Redistributions in binary form must reproduce the above
\r
17 * copyright notice, this list of conditions and the following
\r
18 * disclaimer in the documentation and/or other materials
\r
19 * provided with the distribution.
\r
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
35 #include <complib/cl_async_proc.h>
\r
37 #define CL_ASYNC_PROC_MIN 16
\r
38 #define CL_ASYNC_PROC_GROWSIZE 16
\r
41 /* Worker function declaration. */
\r
43 __cl_async_proc_worker(
\r
44 IN void* const context );
\r
48 cl_async_proc_construct(
\r
49 IN cl_async_proc_t* const p_async_proc )
\r
51 CL_ASSERT( p_async_proc );
\r
53 cl_qlist_init( &p_async_proc->item_queue );
\r
54 cl_spinlock_construct( &p_async_proc->lock );
\r
55 cl_thread_pool_construct( &p_async_proc->thread_pool );
\r
56 p_async_proc->state = CL_UNINITIALIZED;
\r
62 IN cl_async_proc_t* const p_async_proc,
\r
63 IN const uint32_t thread_count,
\r
64 IN const char* const name )
\r
68 CL_ASSERT( p_async_proc );
\r
70 cl_async_proc_construct( p_async_proc );
\r
72 status = cl_spinlock_init( &p_async_proc->lock );
\r
73 if( status != CL_SUCCESS )
\r
75 cl_async_proc_destroy( p_async_proc );
\r
79 status = cl_thread_pool_init( &p_async_proc->thread_pool, thread_count,
\r
80 __cl_async_proc_worker, p_async_proc, name );
\r
81 if( status != CL_SUCCESS )
\r
83 cl_async_proc_destroy( p_async_proc );
\r
87 p_async_proc->state = CL_INITIALIZED;
\r
93 cl_async_proc_destroy(
\r
94 IN cl_async_proc_t* const p_async_proc )
\r
96 /* Destroy the thread pool first so that the threads stop. */
\r
97 cl_thread_pool_destroy( &p_async_proc->thread_pool );
\r
99 /* Flush all queued callbacks. */
\r
100 if( p_async_proc->state == CL_INITIALIZED )
\r
101 __cl_async_proc_worker( p_async_proc );
\r
103 /* Destroy the spinlock. */
\r
104 cl_spinlock_destroy( &p_async_proc->lock );
\r
106 p_async_proc->state = CL_DESTROYED;
\r
111 cl_async_proc_queue(
\r
112 IN cl_async_proc_t* const p_async_proc,
\r
113 IN cl_async_proc_item_t* const p_item )
\r
115 CL_ASSERT( p_async_proc );
\r
116 CL_ASSERT( p_item->pfn_callback );
\r
117 CL_ASSERT( p_async_proc->state == CL_INITIALIZED );
\r
119 /* Enqueue this item for processing. */
\r
120 cl_spinlock_acquire( &p_async_proc->lock );
\r
121 cl_qlist_insert_tail( &p_async_proc->item_queue,
\r
122 &p_item->pool_item.list_item );
\r
123 cl_spinlock_release( &p_async_proc->lock );
\r
125 /* Signal the thread pool to wake up. */
\r
126 cl_thread_pool_signal( &p_async_proc->thread_pool );
\r
131 __cl_async_proc_worker(
\r
132 IN void* const context)
\r
134 cl_async_proc_t *p_async_proc = (cl_async_proc_t*)context;
\r
135 cl_list_item_t *p_list_item;
\r
136 cl_async_proc_item_t *p_item;
\r
138 CL_ASSERT( p_async_proc->state == CL_INITIALIZED );
\r
140 /* Process items from the head of the queue until it is empty. */
\r
141 cl_spinlock_acquire( &p_async_proc->lock );
\r
142 p_list_item = cl_qlist_remove_head( &p_async_proc->item_queue );
\r
143 while( p_list_item != cl_qlist_end( &p_async_proc->item_queue ) )
\r
145 /* Release the lock during the user's callback. */
\r
146 cl_spinlock_release( &p_async_proc->lock );
\r
148 /* Invoke the user callback. */
\r
149 p_item = (cl_async_proc_item_t*)p_list_item;
\r
150 p_item->pfn_callback( p_item );
\r
152 /* Acquire the lock again to continue processing. */
\r
153 cl_spinlock_acquire( &p_async_proc->lock );
\r
154 /* Get the next item in the queue. */
\r
155 p_list_item = cl_qlist_remove_head( &p_async_proc->item_queue );
\r
158 /* The queue is empty. Release the lock and return. */
\r
159 cl_spinlock_release( &p_async_proc->lock );
\r