Changeset 1870d81 in mainline
- Timestamp:
- 2012-01-11T16:25:44Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 787b65b
- Parents:
- 7c2bb2c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/remcons/remcons.c
r7c2bb2c r1870d81 76 76 size_t socket_buffer_pos; 77 77 78 /* Destruction CV with guard. */ 79 int refcount; 78 task_id_t task_id; 79 80 /* Reference counting. */ 80 81 fibril_condvar_t refcount_cv; 81 82 fibril_mutex_t refcount_mutex; 83 bool task_finished; 84 int locsrv_connection_count; 85 bool socket_closed; 82 86 } client_t; 83 87 … … 125 129 fibril_condvar_initialize(&client->refcount_cv); 126 130 fibril_mutex_initialize(&client->refcount_mutex); 127 client->refcount = 0; 131 client->task_finished = false; 132 client->socket_closed = false; 133 client->locsrv_connection_count = 0; 128 134 129 135 … … 146 152 } 147 153 148 static client_t *client_ find(service_id_t id)154 static client_t *client_get_for_client_connection(service_id_t id) 149 155 { 150 156 client_t *client = NULL; … … 158 164 } 159 165 } 166 if (client == NULL) { 167 fibril_mutex_unlock(&clients_guard); 168 return NULL; 169 } 170 171 client_t *tmp = client; 172 fibril_mutex_lock(&tmp->refcount_mutex); 173 client->locsrv_connection_count++; 174 175 /* 176 * Refuse to return client whose task already finished or when 177 * the socket is already closed(). 178 */ 179 if (client->task_finished || client->socket_closed) { 180 client = NULL; 181 client->locsrv_connection_count--; 182 } 183 184 fibril_mutex_unlock(&tmp->refcount_mutex); 185 186 160 187 fibril_mutex_unlock(&clients_guard); 161 188 … … 182 209 while (true) { 183 210 ipc_call_t call; 184 ipc_callid_t callid = async_get_call(&call); 211 ipc_callid_t callid = 0; 212 while (callid == 0) { 213 callid = async_get_call_timeout(&call, 1000); 214 215 fibril_mutex_lock(&client->refcount_mutex); 216 bool bail_out = client->socket_closed || client->task_finished; 217 fibril_mutex_unlock(&client->refcount_mutex); 218 219 if (bail_out) { 220 if (callid != 0) { 221 async_answer_0(callid, EINTR); 222 } 223 return; 224 } 225 } 185 226 186 227 if (!IPC_GET_IMETHOD(call)) { … … 201 242 if (client->socket_buffer_len <= client->socket_buffer_pos) { 202 243 int recv_length = recv(client->socket, client->socket_buffer, BUFFER_SIZE, 0); 203 if (recv_length == 0) { 244 if ((recv_length == 0) || (recv_length == ENOTCONN)) { 245 fibril_mutex_lock(&client->refcount_mutex); 246 client->socket_closed = true; 247 fibril_mutex_unlock(&client->refcount_mutex); 204 248 async_answer_0(callid, ENOENT); 205 249 return; … … 207 251 if (recv_length < 0) { 208 252 async_answer_0(callid, EINVAL); 209 break;253 return; 210 254 } 211 255 client->socket_buffer_len = recv_length; … … 309 353 { 310 354 /* Find the client. */ 311 client_t *client = client_ find(IPC_GET_ARG1(*icall));355 client_t *client = client_get_for_client_connection(IPC_GET_ARG1(*icall)); 312 356 if (client == NULL) { 313 357 async_answer_0(iid, ENOENT); … … 319 363 /* Accept the connection, increment reference. */ 320 364 async_answer_0(iid, EOK); 321 fibril_mutex_lock(&client->refcount_mutex);322 client->refcount++;323 fibril_mutex_unlock(&client->refcount_mutex);324 365 325 366 /* Force character mode. */ … … 331 372 /* Announce client disconnection. */ 332 373 fibril_mutex_lock(&client->refcount_mutex); 333 client-> refcount--;374 client->locsrv_connection_count--; 334 375 fibril_condvar_signal(&client->refcount_cv); 335 376 fibril_mutex_unlock(&client->refcount_mutex); … … 350 391 APP_GETTERM, term, "/app/bdsh", str_error(rc)); 351 392 fibril_mutex_lock(&client->refcount_mutex); 352 client-> refcount--;393 client->task_finished = true; 353 394 fibril_condvar_signal(&client->refcount_cv); 354 395 fibril_mutex_unlock(&client->refcount_mutex); 355 396 return EOK; 356 397 } 398 399 fibril_mutex_lock(&client->refcount_mutex); 400 client->task_id = task; 401 fibril_mutex_unlock(&client->refcount_mutex); 357 402 358 403 task_exit_t task_exit; … … 363 408 /* Announce destruction. */ 364 409 fibril_mutex_lock(&client->refcount_mutex); 365 client-> refcount--;410 client->task_finished = true; 366 411 fibril_condvar_signal(&client->refcount_cv); 367 412 fibril_mutex_unlock(&client->refcount_mutex); … … 370 415 } 371 416 417 static bool client_can_be_destroyed_no_lock(client_t *client) 418 { 419 return client->task_finished && client->socket_closed && 420 (client->locsrv_connection_count == 0); 421 } 372 422 373 423 static int network_client_fibril(void *arg) … … 385 435 client->service_id); 386 436 387 fibril_mutex_lock(&client->refcount_mutex);388 client->refcount++;389 fibril_mutex_unlock(&client->refcount_mutex);390 391 437 fid_t spawn_fibril = fibril_create(spawn_task_fibril, client); 392 438 assert(spawn_fibril); … … 395 441 /* Wait for all clients to exit. */ 396 442 fibril_mutex_lock(&client->refcount_mutex); 397 while (client->refcount > 0) { 398 fibril_condvar_wait(&client->refcount_cv, &client->refcount_mutex); 443 while (!client_can_be_destroyed_no_lock(client)) { 444 if (client->task_finished) { 445 closesocket(client->socket); 446 client->socket_closed = true; 447 continue; 448 } else if (client->socket_closed) { 449 if (client->task_id != 0) { 450 task_kill(client->task_id); 451 } 452 } 453 fibril_condvar_wait_timeout(&client->refcount_cv, &client->refcount_mutex, 1000); 399 454 } 400 455 fibril_mutex_unlock(&client->refcount_mutex); 401 456 402 closesocket(client->socket);403 457 rc = loc_service_unregister(client->service_id); 404 458 if (rc != EOK) {
Note:
See TracChangeset
for help on using the changeset viewer.