ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/evthread.C
(Generate patch)

Comparing deliantra/server/server/evthread.C (file contents):
Revision 1.7 by root, Thu Nov 20 12:18:07 2008 UTC vs.
Revision 1.17 by root, Mon Oct 29 23:55:55 2012 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * 5 *
6 * Deliantra is free software: you can redistribute it and/or modify 6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * it under the terms of the GNU General Public License as published by 7 * the terms of the Affero GNU General Public License as published by the
8 * the Free Software Foundation, either version 3 of the License, or 8 * Free Software Foundation, either version 3 of the License, or (at your
9 * (at your option) any later version. 9 * option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the Affero GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
18 * 19 *
19 * The authors can be reached via e-mail to <support@deliantra.net> 20 * The authors can be reached via e-mail to <support@deliantra.net>
20 */ 21 */
21 22
22#include "global.h" 23#include "global.h"
23#include "evthread.h" 24#include "evthread.h"
24#include "cfperl.h" 25#include "cfperl.h"
25 26
26thread evthread; 27thread evthread;
27static ev_loop *loop; 28static ev_loop *loop;
28 29
29#define TICK_CYCLES 4 30/////////////////////////////////////////////////////////////////////////////
30 31
31// the tick watcher is activated every TICK_CYCLES
32ev_async tick_watcher; 32ev_async tick_watcher;
33EV_ATOMIC_T coroapi::cede_pending; 33EV_ATOMIC_T coroapi::cede_pending;
34 34
35// the ticker runs TICK_CYCLES times as fast as the main server tick
36static ev_periodic cede_watcher; 35static ev_periodic cede_watcher;
37
38/////////////////////////////////////////////////////////////////////////////
39 36
40// it is a bit silly to have to use a mutex, but contention 37// it is a bit silly to have to use a mutex, but contention
41// is basically non-existant, favouring good mutex implementations. 38// is basically non-existant, favouring good mutex implementations.
42static SMUTEX (evthread_mutex); 39static SMUTEX (evthread_mutex);
43static NV next_tick; 40static NV next_tick;
51} 48}
52 49
53static void 50static void
54cede_cb (EV_P_ ev_periodic *w, int revents) 51cede_cb (EV_P_ ev_periodic *w, int revents)
55{ 52{
56 static int cycle = 0;
57
58 if (++cycle == TICK_CYCLES)
59 {
60 cycle = 0;
61
62 SMUTEX_LOCK (evthread_mutex); 53 SMUTEX_LOCK (evthread_mutex);
63 next_tick = w->at + TICK / TICK_CYCLES * (TICK_CYCLES - 1); 54 next_tick = w->at;
64 SMUTEX_UNLOCK (evthread_mutex); 55 SMUTEX_UNLOCK (evthread_mutex);
65
66 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
67 }
68 56
69 coroapi::cede_pending = 1; 57 coroapi::cede_pending = 1;
58
59 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
70} 60}
71 61
72static void 62static void
73tick_cb (EV_P_ ev_async *w, int revents) 63tick_cb (EV_P_ ev_async *w, int revents)
74{ 64{
75 cfperl_tick (); 65 cfperl_tick ();
76} 66}
77 67
78///////////////////////////////////////////////////////////////////////////// 68/////////////////////////////////////////////////////////////////////////////
79 69
70static SMUTEX(cb_mutex);
71static SCOND(cb_done);
72
80static ev_async async_watcher; 73static ev_async async_watcher;
81static ev_io aio1_watcher; 74static ev_io aio_watcher;
82static ev_idle aio2_watcher;
83static EV_ATOMIC_T aio_pending;
84
85static void
86aio2_cb (EV_P_ ev_idle *w, int revents)
87{
88 IV reqs;
89
90 CALL_BEGIN (0);
91 CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
92
93 reqs = POPi;
94 if (count > 0 && reqs < 0)
95 ev_idle_start (EV_A, w);
96 else
97 ev_idle_stop (EV_A, w);
98
99 CALL_END;
100}
101 75
102static void 76static void
103async_cb (EV_P_ ev_async *w, int revents) 77async_cb (EV_P_ ev_async *w, int revents)
104{ 78{
105 aio2_cb (EV_A, &aio2_watcher, 0); 79 CALL_BEGIN (0);
80 CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
81 IV reqs = POPi;
82 CALL_END;
83
84 SMUTEX_LOCK (cb_mutex);
85 SCOND_SIGNAL (cb_done);
86 SMUTEX_UNLOCK (cb_mutex);
106} 87}
107 88
108static void 89static void
109aio1_cb (EV_P_ ev_io *w, int revents) 90aio_cb (EV_P_ ev_io *w, int revents)
110{ 91{
111 char dummy; 92 ev_async_send (EV_DEFAULT_UC, &async_watcher);
112 93
113 if (read (w->fd, &dummy, 1) > 0) 94 coroapi::cede_pending = 1; // to decrease latency
114 { 95
115 ev_async_send (EV_DEFAULT_UC, &async_watcher); 96 SCOND_WAIT (cb_done, cb_mutex);
116 coroapi::cede_pending = 1;
117 }
118} 97}
119 98
120///////////////////////////////////////////////////////////////////////////// 99/////////////////////////////////////////////////////////////////////////////
121 100
122static void * 101static void *
123evthread_proc (void *arg) 102evthread_proc (void *arg)
124{ 103{
104 SMUTEX_LOCK (cb_mutex);
105
125 ev_loop (loop, 0); 106 ev_run (loop, 0);
126 107
127 return 0; 108 return 0;
128} 109}
129 110
130void evthread_start (int aiofd) 111void evthread_start (int aiofd)
138 119
139 ev_async_init (&async_watcher, async_cb); 120 ev_async_init (&async_watcher, async_cb);
140 ev_set_priority (&async_watcher, 1); 121 ev_set_priority (&async_watcher, 1);
141 ev_async_start (EV_DEFAULT_UC, &async_watcher); 122 ev_async_start (EV_DEFAULT_UC, &async_watcher);
142 123
143 ev_idle_init (&aio2_watcher, aio2_cb); 124 // secondary loop, we use select/poll as epoll has very
125 // bad timing characteristics and we only watch a single low fd.
126 loop = ev_loop_new (EVBACKEND_SELECT);
144 127
145 // secondary loop
146 loop = ev_loop_new (0);
147
148 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK / TICK_CYCLES, 0); 128 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK, 0);
149 ev_periodic_start (loop, &cede_watcher); 129 ev_periodic_start (loop, &cede_watcher);
150 130
151 ev_io_init (&aio1_watcher, aio1_cb, aiofd, EV_READ); 131 ev_io_init (&aio_watcher, aio_cb, aiofd, EV_READ);
152 ev_io_start (loop, &aio1_watcher); 132 ev_io_start (loop, &aio_watcher);
153 133
154 evthread.start (evthread_proc); 134 evthread.start (evthread_proc);
155} 135}
156 136
157 137

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines