initial implementation
[mirror/winof/.git] / core / complib / cl_async_proc.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\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
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\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
20  *\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
28  * SOFTWARE.\r
29  *\r
30  * $Id:$\r
31  */\r
32 \r
33 \r
34 \r
35 #include <complib/cl_async_proc.h>\r
36 \r
37 #define CL_ASYNC_PROC_MIN               16\r
38 #define CL_ASYNC_PROC_GROWSIZE  16\r
39 \r
40 \r
41 /* Worker function declaration. */\r
42 static void\r
43 __cl_async_proc_worker(\r
44         IN      void* const     context );\r
45 \r
46 \r
47 void\r
48 cl_async_proc_construct(\r
49         IN      cl_async_proc_t* const  p_async_proc )\r
50 {\r
51         CL_ASSERT( p_async_proc );\r
52 \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
57 }\r
58 \r
59 \r
60 cl_status_t\r
61 cl_async_proc_init(\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
65 {\r
66         cl_status_t             status;\r
67 \r
68         CL_ASSERT( p_async_proc );\r
69 \r
70         cl_async_proc_construct( p_async_proc );\r
71 \r
72         status = cl_spinlock_init( &p_async_proc->lock );\r
73         if( status != CL_SUCCESS )\r
74         {\r
75                 cl_async_proc_destroy( p_async_proc );\r
76                 return( status );\r
77         }\r
78 \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
82         {\r
83                 cl_async_proc_destroy( p_async_proc );\r
84                 return (status);\r
85         }\r
86 \r
87         p_async_proc->state = CL_INITIALIZED;\r
88         return( status );\r
89 }\r
90 \r
91 \r
92 void\r
93 cl_async_proc_destroy(\r
94         IN      cl_async_proc_t* const  p_async_proc )\r
95 {\r
96         /* Destroy the thread pool first so that the threads stop. */\r
97         cl_thread_pool_destroy( &p_async_proc->thread_pool );\r
98 \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
102 \r
103         /* Destroy the spinlock. */\r
104         cl_spinlock_destroy( &p_async_proc->lock );\r
105 \r
106         p_async_proc->state = CL_DESTROYED;\r
107 }\r
108 \r
109 \r
110 void\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
114 {\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
118 \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
124 \r
125         /* Signal the thread pool to wake up. */\r
126         cl_thread_pool_signal( &p_async_proc->thread_pool );\r
127 }\r
128 \r
129 \r
130 static void\r
131 __cl_async_proc_worker(\r
132         IN      void* const     context)\r
133 {\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
137 \r
138         CL_ASSERT( p_async_proc->state == CL_INITIALIZED );\r
139 \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
144         {\r
145                 /* Release the lock during the user's callback. */\r
146                 cl_spinlock_release( &p_async_proc->lock );\r
147 \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
151 \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
156         }\r
157 \r
158         /* The queue is empty.  Release the lock and return. */\r
159         cl_spinlock_release( &p_async_proc->lock );\r
160 }\r