1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2008-2011 WiredTiger, Inc.
* All rights reserved.
*/
#include "wt_internal.h"
/*
* __wt_workq_srvr --
* Routine to process the WT_SESSION_IMPL work queue.
*/
void *
__wt_workq_srvr(void *arg)
{
WT_CONNECTION_IMPL *conn;
WT_SESSION_IMPL **tp, *session;
int call_evict, call_read, request;
conn = (WT_CONNECTION_IMPL *)arg;
/* Walk the WT_SESSION_IMPL list and execute requests. */
while (F_ISSET(conn, WT_WORKQ_RUN)) {
WT_STAT_INCR(conn->stats, workq_passes);
call_evict = call_read = request = 0;
for (tp = conn->sessions; (session = *tp) != NULL; ++tp) {
switch (session->wq_state) {
case WT_WORKQ_NONE:
break;
case WT_WORKQ_FUNC:
request = 1;
session->wq_func(session);
break;
case WT_WORKQ_READ:
/*
* Call a function which makes a request of the
* read server. There are two read states: READ
* (the initial request), and READ_SCHED (the
* function has been called and we're waiting on
* the read to complete). There are two states
* because we can race with the server: if the
* called function adds itself to the queue just
* as the server is going to sleep, the server
* might not see the request. So, READ_SCHED
* means we don't have to call the function, but
* we do have check if the server is running.
*
* The read state is eventually reset by the
* read server, so we set it before we call the
* function that will contact the server, so we
* can't race on that update.
*/
session->wq_state = WT_WORKQ_READ_SCHED;
/* Queue the request for the read server. */
session->wq_func(session);
/* FALLTHROUGH */
case WT_WORKQ_READ_SCHED:
call_read = 1;
break;
case WT_WORKQ_EVICT:
/*
* See comment above regarding read scheduling;
* eviction works the same as read, as far as
* the workq is concerned.
*
* We don't have to call a function to contact
* the eviction server, currently the eviction
* server checks the list of open tables each
* time it runs.
*/
session->wq_state = WT_WORKQ_EVICT_SCHED;
/* Queue the request for the eviction server. */
session->wq_func(session);
/* FALLTHROUGH */
case WT_WORKQ_EVICT_SCHED:
call_evict = 1;
break;
}
}
/* If a read is scheduled, check on the read server. */
if (call_read)
__wt_workq_read_server(conn, 0);
/* Check on the eviction server. */
__wt_workq_evict_server(conn, call_evict);
/* If we didn't find work, yield the processor. */
if (!request) {
WT_STAT_INCR(conn->stats, workq_yield);
__wt_yield();
}
}
return (NULL);
}
|