sysdeps_qemu.c revision c2db2b6accc7888df514261a7240e7759df95a4c
1/* Copyright (C) 2007-2008 The Android Open Source Project 2** 3** This software is licensed under the terms of the GNU General Public 4** License version 2, as published by the Free Software Foundation, and 5** may be copied, distributed, and modified under those terms. 6** 7** This program is distributed in the hope that it will be useful, 8** but WITHOUT ANY WARRANTY; without even the implied warranty of 9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10** GNU General Public License for more details. 11*/ 12#include "sockets.h" 13#include "sysdeps.h" 14#include "vl.h" 15 16#define DEBUG 1 17 18#define D_ACTIVE DEBUG 19 20#if DEBUG 21#define D(...) do { if (D_ACTIVE) fprintf(stderr, __VA_ARGS__); } while (0) 22#else 23#define D(...) ((void)0) 24#endif 25 26/** TIME 27 **/ 28 29SysTime 30sys_time_ms( void ) 31{ 32 return qemu_get_clock( rt_clock ); 33} 34 35/** TIMERS 36 **/ 37 38typedef struct SysTimerRec_ { 39 QEMUTimer* timer; 40 QEMUTimerCB* callback; 41 void* opaque; 42 SysTimer next; 43} SysTimerRec; 44 45#define MAX_TIMERS 32 46 47static SysTimerRec _s_timers0[ MAX_TIMERS ]; 48static SysTimer _s_free_timers; 49 50static void 51sys_init_timers( void ) 52{ 53 int nn; 54 for (nn = 0; nn < MAX_TIMERS-1; nn++) 55 _s_timers0[nn].next = _s_timers0 + (nn+1); 56 57 _s_free_timers = _s_timers0; 58} 59 60static SysTimer 61sys_timer_alloc( void ) 62{ 63 SysTimer timer = _s_free_timers; 64 65 if (timer != NULL) { 66 _s_free_timers = timer->next; 67 timer->next = NULL; 68 timer->timer = NULL; 69 } 70 return timer; 71} 72 73 74static void 75sys_timer_free( SysTimer timer ) 76{ 77 if (timer->timer) { 78 qemu_del_timer( timer->timer ); 79 qemu_free_timer( timer->timer ); 80 timer->timer = NULL; 81 } 82 timer->next = _s_free_timers; 83 _s_free_timers = timer; 84} 85 86 87SysTimer sys_timer_create( void ) 88{ 89 SysTimer timer = sys_timer_alloc(); 90 return timer; 91} 92 93void 94sys_timer_set( SysTimer timer, SysTime when, SysCallback _callback, void* opaque ) 95{ 96 QEMUTimerCB* callback = (QEMUTimerCB*)_callback; 97 98 if (callback == NULL) { /* unsetting the timer */ 99 if (timer->timer) { 100 qemu_del_timer( timer->timer ); 101 qemu_free_timer( timer->timer ); 102 timer->timer = NULL; 103 } 104 timer->callback = callback; 105 timer->opaque = NULL; 106 return; 107 } 108 109 if ( timer->timer ) { 110 if ( timer->callback == callback && timer->opaque == opaque ) 111 goto ReuseTimer; 112 113 /* need to replace the timer */ 114 qemu_free_timer( timer->timer ); 115 } 116 117 timer->timer = qemu_new_timer( rt_clock, callback, opaque ); 118 timer->callback = callback; 119 timer->opaque = opaque; 120 121ReuseTimer: 122 qemu_mod_timer( timer->timer, when ); 123} 124 125void 126sys_timer_unset( SysTimer timer ) 127{ 128 if (timer->timer) { 129 qemu_del_timer( timer->timer ); 130 } 131} 132 133void 134sys_timer_destroy( SysTimer timer ) 135{ 136 sys_timer_free( timer ); 137} 138 139 140/** CHANNELS 141 **/ 142 143typedef struct SysChannelRec_ { 144 int fd; 145 SysChannelCallback callback; 146 void* opaque; 147 SysChannel next; 148} SysChannelRec; 149 150#define MAX_CHANNELS 16 151 152static SysChannelRec _s_channels0[ MAX_CHANNELS ]; 153static SysChannel _s_free_channels; 154 155static void 156sys_init_channels( void ) 157{ 158 int nn; 159 160 for ( nn = 0; nn < MAX_CHANNELS-1; nn++ ) { 161 _s_channels0[nn].next = _s_channels0 + (nn+1); 162 } 163 _s_free_channels = _s_channels0; 164} 165 166static SysChannel 167sys_channel_alloc( ) 168{ 169 SysChannel channel = _s_free_channels; 170 if (channel != NULL) { 171 _s_free_channels = channel->next; 172 channel->next = NULL; 173 channel->fd = -1; 174 channel->callback = NULL; 175 channel->opaque = NULL; 176 } 177 return channel; 178} 179 180static void 181sys_channel_free( SysChannel channel ) 182{ 183 if (channel->fd >= 0) { 184 socket_close( channel->fd ); 185 channel->fd = -1; 186 } 187 channel->next = _s_free_channels; 188 _s_free_channels = channel; 189} 190 191 192static void 193sys_channel_read_handler( void* _channel ) 194{ 195 SysChannel channel = _channel; 196 D( "%s: read event for channel %p:%d\n", __FUNCTION__, 197 channel, channel->fd ); 198 channel->callback( channel->opaque, SYS_EVENT_READ ); 199} 200 201static void 202sys_channel_write_handler( void* _channel ) 203{ 204 SysChannel channel = _channel; 205 D( "%s: write event for channel %p:%d\n", __FUNCTION__, channel, channel->fd ); 206 channel->callback( channel->opaque, SYS_EVENT_WRITE ); 207} 208 209void 210sys_channel_on( SysChannel channel, 211 int events, 212 SysChannelCallback event_callback, 213 void* event_opaque ) 214{ 215 IOHandler* read_handler = NULL; 216 IOHandler* write_handler = NULL; 217 218 if (events & SYS_EVENT_READ) { 219 read_handler = sys_channel_read_handler; 220 } 221 if (events & SYS_EVENT_WRITE) { 222 write_handler = sys_channel_write_handler; 223 } 224 channel->callback = event_callback; 225 channel->opaque = event_opaque; 226 qemu_set_fd_handler( channel->fd, read_handler, write_handler, channel ); 227} 228 229int 230sys_channel_read( SysChannel channel, void* buffer, int size ) 231{ 232 int len = size; 233 char* buf = (char*) buffer; 234 235 while (len > 0) { 236 int ret = socket_recv(channel->fd, buf, len); 237 if (ret < 0) { 238 if (errno == EINTR) 239 continue; 240 if (errno == EWOULDBLOCK) 241 break; 242 D( "%s: after reading %d bytes, recv() returned error %d: %s\n", 243 __FUNCTION__, size - len, errno, errno_str); 244 return -1; 245 } else if (ret == 0) { 246 break; 247 } else { 248 buf += ret; 249 len -= ret; 250 } 251 } 252 return size - len; 253} 254 255 256int 257sys_channel_write( SysChannel channel, const void* buffer, int size ) 258{ 259 int len = size; 260 const char* buf = (const char*) buffer; 261 262 while (len > 0) { 263 int ret = socket_send(channel->fd, buf, len); 264 if (ret < 0) { 265 if (errno == EINTR) 266 continue; 267 if (errno == EWOULDBLOCK) 268 break; 269 D( "%s: send() returned error %d: %s\n", 270 __FUNCTION__, errno, errno_str); 271 return -1; 272 } else if (ret == 0) { 273 break; 274 } else { 275 buf += ret; 276 len -= ret; 277 } 278 } 279 return size - len; 280} 281 282void sys_channel_close( SysChannel channel ) 283{ 284 qemu_set_fd_handler( channel->fd, NULL, NULL, NULL ); 285 sys_channel_free( channel ); 286} 287 288void sys_main_init( void ) 289{ 290 sys_init_channels(); 291 sys_init_timers(); 292} 293 294 295int sys_main_loop( void ) 296{ 297 /* no looping, qemu has its own event loop */ 298 return 0; 299} 300 301 302 303 304SysChannel 305sys_channel_create_tcp_server( int port ) 306{ 307 SysChannel channel = sys_channel_alloc(); 308 309 channel->fd = socket_anyaddr_server( port, SOCKET_STREAM ); 310 if (channel->fd < 0) { 311 D( "%s: failed to created network socket on TCP:%d\n", 312 __FUNCTION__, port ); 313 sys_channel_free( channel ); 314 return NULL; 315 } 316 317 D( "%s: server channel %p:%d now listening on port %d\n", 318 __FUNCTION__, channel, channel->fd, port ); 319 320 return channel; 321} 322 323 324SysChannel 325sys_channel_create_tcp_handler( SysChannel server_channel ) 326{ 327 SysChannel channel = sys_channel_alloc(); 328 329 D( "%s: creating handler from server channel %p:%d\n", __FUNCTION__, 330 server_channel, server_channel->fd ); 331 332 channel->fd = socket_accept_any( server_channel->fd ); 333 if (channel->fd < 0) { 334 perror( "accept" ); 335 sys_channel_free( channel ); 336 return NULL; 337 } 338 339 /* disable Nagle algorithm */ 340 socket_set_lowlatency( channel->fd ); 341 342 D( "%s: handler %p:%d created from server %p:%d\n", __FUNCTION__, 343 server_channel, server_channel->fd, channel, channel->fd ); 344 345 return channel; 346} 347 348 349SysChannel 350sys_channel_create_tcp_client( const char* hostname, int port ) 351{ 352 SysChannel channel = sys_channel_alloc(); 353 354 channel->fd = socket_network_client( hostname, port, SOCKET_STREAM ); 355 if (channel->fd < 0) { 356 sys_channel_free(channel); 357 return NULL; 358 }; 359 360 /* set to non-blocking and disable Nagle algorithm */ 361 socket_set_nonblock( channel->fd ); 362 socket_set_lowlatency( channel->fd ); 363 364 return channel; 365} 366 367