Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2008-2010, Sine Nomine Associates and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | #ifndef AFS_UTIL_WORK_QUEUE_IMPL_TYPES_H | |
11 | #define AFS_UTIL_WORK_QUEUE_IMPL_TYPES_H 1 | |
12 | ||
13 | #ifndef __AFS_WORK_QUEUE_IMPL | |
14 | #error "do not include this file outside of the work queue implementation" | |
15 | #endif | |
16 | ||
17 | #include "work_queue_types.h" | |
18 | #include <rx/rx_queue.h> | |
19 | ||
20 | /** | |
21 | * implementation-private type definitions for work_queue. | |
22 | */ | |
23 | ||
24 | /** | |
25 | * work_queue node state. | |
26 | */ | |
27 | typedef enum { | |
28 | AFS_WQ_NODE_STATE_INIT, /**< initial state */ | |
29 | AFS_WQ_NODE_STATE_SCHEDULED, /**< scheduled for execution */ | |
30 | AFS_WQ_NODE_STATE_RUNNING, /**< running callback function */ | |
31 | AFS_WQ_NODE_STATE_DONE, /**< callback function finished */ | |
32 | AFS_WQ_NODE_STATE_ERROR, /**< node callback failed, or some dep failed */ | |
33 | AFS_WQ_NODE_STATE_BLOCKED, /**< pending some dependency */ | |
34 | AFS_WQ_NODE_STATE_BUSY, /**< exclusively owned by a thread */ | |
35 | /* add new states above this line */ | |
36 | AFS_WQ_NODE_STATE_TERMINAL | |
37 | } afs_wq_work_state_t; | |
38 | ||
39 | /** | |
40 | * work_queue dependency node. | |
41 | */ | |
42 | struct afs_work_queue_dep_node { | |
43 | struct rx_queue parent_list; /**< parent node's list of children */ | |
44 | struct afs_work_queue_node * parent; /**< parent work node */ | |
45 | struct afs_work_queue_node * child; /**< child work node */ | |
46 | /* coming soon: dep options */ | |
47 | }; | |
48 | ||
49 | /** | |
50 | * work_queue enumeration. | |
51 | * | |
52 | * tells which linked list a given node is attached to. | |
53 | */ | |
54 | typedef enum { | |
55 | AFS_WQ_NODE_LIST_NONE, /**< node is not on a linked list. */ | |
56 | AFS_WQ_NODE_LIST_READY, /**< node is on ready_list */ | |
57 | AFS_WQ_NODE_LIST_BLOCKED, /**< node is on blocked_list */ | |
58 | AFS_WQ_NODE_LIST_DONE, /**< node is on done_list */ | |
59 | /* add new queues above this line */ | |
60 | AFS_WQ_NODE_LIST_TERMINAL | |
61 | } afs_wq_node_list_id_t; | |
62 | ||
63 | /** | |
64 | * work_queue node. | |
65 | */ | |
66 | struct afs_work_queue_node { | |
67 | struct rx_queue node_list; /**< linked list of work queue nodes. */ | |
68 | afs_wq_node_list_id_t qidx; /**< id of linked list */ | |
69 | struct rx_queue dep_children; /**< nodes whose execution depends upon | |
70 | * our completion. */ | |
71 | afs_wq_callback_func_t * cbf; | |
72 | /**< callback function which will be called by scheduler */ | |
73 | afs_wq_callback_dtor_t *rock_dtor; /**< destructor function for 'rock' */ | |
74 | void * rock; /**< opaque pointer passed into cbf */ | |
75 | struct afs_work_queue * queue; /**< our queue */ | |
76 | afs_wq_work_state_t state; /**< state of this queue node */ | |
77 | afs_uint32 refcount; /**< object reference count */ | |
78 | afs_uint32 block_count; /**< dependency blocking count; node is | |
79 | * only a candidate for execution when | |
80 | * this counter reaches zero. */ | |
81 | afs_uint32 error_count; /**< dependency error count; node is only | |
82 | * a candidate for execution when this | |
83 | * counter reaches zero. */ | |
84 | int detached; /**< object is put instead of being placed onto done queue */ | |
85 | int retcode; /**< return code from worker function */ | |
86 | pthread_mutex_t lock; /**< object lock */ | |
87 | pthread_cond_t state_cv; /**< state change cv */ | |
88 | }; | |
89 | ||
90 | /** | |
91 | * linked list | |
92 | */ | |
93 | struct afs_work_queue_node_list { | |
94 | struct rx_queue list; /**< linked list of nodes */ | |
95 | afs_wq_node_list_id_t qidx; /**< id of linked list */ | |
96 | int shutdown; /**< don't allow blocking on dequeue if asserted */ | |
97 | pthread_mutex_t lock; /**< synchronize list access */ | |
98 | pthread_cond_t cv; /**< signal empty->non-empty transition */ | |
99 | }; | |
100 | ||
101 | /** | |
102 | * multilock control structure. | |
103 | */ | |
104 | struct afs_work_queue_node_multilock { | |
105 | struct { | |
106 | struct afs_work_queue_node * node; | |
107 | int lock_held; | |
108 | int busy_held; | |
109 | } nodes[2]; | |
110 | }; | |
111 | ||
112 | /** | |
113 | * work queue. | |
114 | */ | |
115 | struct afs_work_queue { | |
116 | struct afs_work_queue_node_list ready_list; /**< ready work queue nodes. */ | |
117 | struct afs_work_queue_node_list blocked_list; /**< nodes scheduled, but blocked */ | |
118 | struct afs_work_queue_node_list done_list; /**< nodes done/errored */ | |
119 | void * rock; /**< opaque pointer passed to all callbacks */ | |
120 | ||
121 | struct afs_work_queue_opts opts; | |
122 | ||
123 | int drain; /**< 1 if we are waiting for the queue to drain | |
124 | * until the number of pending tasks has | |
125 | * dropped below the low threshold */ | |
126 | int shutdown; /**< 1 if the queue has been shutdown */ | |
127 | int pend_count; /**< number of pending tasks */ | |
128 | int running_count; /**< number of tasks busy running */ | |
129 | pthread_mutex_t lock; /**< lock for the queue */ | |
130 | pthread_cond_t pend_cv; /**< signalled when th queue is draining and | |
131 | * the number of pending tasks dropped below | |
132 | * the low threshold */ | |
133 | pthread_cond_t empty_cv; /**< signalled when the number of pending tasks | |
134 | * reaches 0 */ | |
135 | pthread_cond_t running_cv; /**< signalled once running_count reaches 0 and | |
136 | * the queue is shutting down */ | |
137 | }; | |
138 | ||
139 | #endif /* AFS_UTIL_WORK_QUEUE_IMPL_TYPES_H */ |