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.11 by root, Fri Mar 26 01:04:45 2010 UTC vs.
Revision 1.18 by root, Wed Nov 16 23:42:02 2016 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 (©) 2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * 5 *
6 * Deliantra is free software: you can redistribute it and/or modify it under 6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * the terms of the Affero GNU General Public License as published by the 7 * the terms of the Affero GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your 8 * Free Software Foundation, either version 3 of the License, or (at your
9 * 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 Affero GNU General Public License 16 * You should have received a copy of the Affero GNU General Public License
17 * and the GNU General Public License along with this program. If not, see 17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>. 18 * <http://www.gnu.org/licenses/>.
19 * 19 *
20 * 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>
21 */ 21 */
22 22
23#include "global.h" 23#include "global.h"
24#include "evthread.h" 24#include "evthread.h"
25#include "cfperl.h" 25#include "cfperl.h"
26 26
27thread evthread; 27thread evthread;
28static ev_loop *loop; 28static ev_loop *loop;
29 29
30#define TICK_CYCLES 4 30/////////////////////////////////////////////////////////////////////////////
31 31
32// the tick watcher is activated every TICK_CYCLES
33ev_async tick_watcher; 32ev_async tick_watcher;
34EV_ATOMIC_T coroapi::cede_pending; 33EV_ATOMIC_T coroapi::cede_pending;
35 34
36// the ticker runs TICK_CYCLES times as fast as the main server tick
37static ev_periodic cede_watcher; 35static ev_periodic cede_watcher;
38
39/////////////////////////////////////////////////////////////////////////////
40 36
41// 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
42// is basically non-existant, favouring good mutex implementations. 38// is basically non-existant, favouring good mutex implementations.
43static SMUTEX (evthread_mutex); 39static SMUTEX (evthread_mutex);
44static NV next_tick; 40static NV next_tick;
52} 48}
53 49
54static void 50static void
55cede_cb (EV_P_ ev_periodic *w, int revents) 51cede_cb (EV_P_ ev_periodic *w, int revents)
56{ 52{
57 static int cycle = 0;
58
59 if (++cycle == TICK_CYCLES)
60 {
61 cycle = 0;
62
63 SMUTEX_LOCK (evthread_mutex); 53 SMUTEX_LOCK (evthread_mutex);
64 next_tick = w->at + TICK / TICK_CYCLES * (TICK_CYCLES - 1); 54 next_tick = w->at;
65 SMUTEX_UNLOCK (evthread_mutex); 55 SMUTEX_UNLOCK (evthread_mutex);
66
67 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
68 }
69 56
70 coroapi::cede_pending = 1; 57 coroapi::cede_pending = 1;
58
59 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
71} 60}
72 61
73static void 62static void
74tick_cb (EV_P_ ev_async *w, int revents) 63tick_cb (EV_P_ ev_async *w, int revents)
75{ 64{
76 cfperl_tick (); 65 cfperl_tick ();
77} 66}
78 67
79///////////////////////////////////////////////////////////////////////////// 68/////////////////////////////////////////////////////////////////////////////
80 69
70static SMUTEX(cb_mutex);
71static SCOND(cb_done);
72
81static ev_async async_watcher; 73static ev_async async_watcher;
82static ev_io aio1_watcher; 74static ev_io aio_watcher;
83static ev_idle aio2_watcher;
84static EV_ATOMIC_T aio_pending;
85
86static void
87aio2_cb (EV_P_ ev_idle *w, int revents)
88{
89 IV reqs;
90
91 CALL_BEGIN (0);
92 CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
93
94 reqs = POPi;
95 if (count > 0 && reqs < 0)
96 ev_idle_start (EV_A, w);
97 else
98 ev_idle_stop (EV_A, w);
99
100 CALL_END;
101}
102 75
103static void 76static void
104async_cb (EV_P_ ev_async *w, int revents) 77async_cb (EV_P_ ev_async *w, int revents)
105{ 78{
106 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);
107} 87}
108 88
109static void 89static void
110aio1_cb (EV_P_ ev_io *w, int revents) 90aio_cb (EV_P_ ev_io *w, int revents)
111{ 91{
112 char dummy[9]; 92 ev_async_send (EV_DEFAULT_UC, &async_watcher);
113 93
114 if (read (w->fd, dummy, sizeof (dummy)) > 0) 94 coroapi::cede_pending = 1; // to decrease latency
115 { 95
116 ev_async_send (EV_DEFAULT_UC, &async_watcher); 96 SCOND_WAIT (cb_done, cb_mutex);
117 coroapi::cede_pending = 1;
118 }
119} 97}
120 98
121///////////////////////////////////////////////////////////////////////////// 99/////////////////////////////////////////////////////////////////////////////
122 100
123static void * 101static void *
124evthread_proc (void *arg) 102evthread_proc (void *arg)
125{ 103{
104 SMUTEX_LOCK (cb_mutex);
105
126 ev_loop (loop, 0); 106 ev_run (loop, 0);
127 107
128 return 0; 108 return 0;
129} 109}
130 110
131void evthread_start (int aiofd) 111void evthread_start (int aiofd)
139 119
140 ev_async_init (&async_watcher, async_cb); 120 ev_async_init (&async_watcher, async_cb);
141 ev_set_priority (&async_watcher, 1); 121 ev_set_priority (&async_watcher, 1);
142 ev_async_start (EV_DEFAULT_UC, &async_watcher); 122 ev_async_start (EV_DEFAULT_UC, &async_watcher);
143 123
144 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);
145 127
146 // secondary loop
147 loop = ev_loop_new (0);
148
149 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK / TICK_CYCLES, 0); 128 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK, 0);
150 ev_periodic_start (loop, &cede_watcher); 129 ev_periodic_start (loop, &cede_watcher);
151 130
152 ev_io_init (&aio1_watcher, aio1_cb, aiofd, EV_READ); 131 ev_io_init (&aio_watcher, aio_cb, aiofd, EV_READ);
153 ev_io_start (loop, &aio1_watcher); 132 ev_io_start (loop, &aio_watcher);
154 133
155 evthread.start (evthread_proc); 134 evthread.start (evthread_proc);
156} 135}
157 136
158 137

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines