Changeset 9956fad9 in mainline for kernel/generic/src/ipc/sysipc.c
- Timestamp:
- 2012-08-15T09:53:19Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9a82ac1
- Parents:
- 1cb75de
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/sysipc.c
r1cb75de r9956fad9 174 174 } 175 175 176 static int a_preprocess_m_connection_clone(call_t *answer, ipc_data_t *olddata) 177 { 178 int phoneid = (int) IPC_GET_ARG1(*olddata); 179 phone_t *phone = &TASK->phones[phoneid]; 180 181 if (IPC_GET_RETVAL(answer->data) != EOK) { 182 /* 183 * The recipient of the cloned phone rejected the offer. In 184 * this case, the connection was established at the request 185 * time and therefore we need to slam the phone. We don't 186 * merely hangup as that would result in sending IPC_M_HUNGUP 187 * to the third party on the other side of the cloned phone. 188 */ 189 mutex_lock(&phone->lock); 190 if (phone->state == IPC_PHONE_CONNECTED) { 191 irq_spinlock_lock(&phone->callee->lock, true); 192 list_remove(&phone->link); 193 phone->state = IPC_PHONE_SLAMMED; 194 irq_spinlock_unlock(&phone->callee->lock, true); 195 } 196 mutex_unlock(&phone->lock); 197 } 198 199 return EOK; 200 } 201 202 static int a_preprocess_m_clone_establish(call_t *answer, ipc_data_t *olddata) 203 { 204 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 205 206 if (IPC_GET_RETVAL(answer->data) != EOK) { 207 /* 208 * The other party on the cloned phoned rejected our request 209 * for connection on the protocol level. We need to break the 210 * connection without sending IPC_M_HUNGUP back. 211 */ 212 mutex_lock(&phone->lock); 213 if (phone->state == IPC_PHONE_CONNECTED) { 214 irq_spinlock_lock(&phone->callee->lock, true); 215 list_remove(&phone->link); 216 phone->state = IPC_PHONE_SLAMMED; 217 irq_spinlock_unlock(&phone->callee->lock, true); 218 } 219 mutex_unlock(&phone->lock); 220 } 221 222 return EOK; 223 } 224 225 static int a_preprocess_m_connect_to_me(call_t *answer, ipc_data_t *olddata) 226 { 227 int phoneid = (int) IPC_GET_ARG5(*olddata); 228 229 if (IPC_GET_RETVAL(answer->data) != EOK) { 230 /* The connection was not accepted */ 231 phone_dealloc(phoneid); 232 } else { 233 /* The connection was accepted */ 234 phone_connect(phoneid, &answer->sender->answerbox); 235 /* Set 'phone hash' as arg5 of response */ 236 IPC_SET_ARG5(answer->data, (sysarg_t) &TASK->phones[phoneid]); 237 } 238 239 return EOK; 240 } 241 242 static int a_preprocess_m_connect_me_to(call_t *answer, ipc_data_t *olddata) 243 { 244 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 245 246 /* If the users accepted call, connect */ 247 if (IPC_GET_RETVAL(answer->data) == EOK) 248 ipc_phone_connect(phone, &TASK->answerbox); 249 250 return EOK; 251 } 252 253 static int a_preprocess_m_share_out(call_t *answer, ipc_data_t *olddata) 254 { 255 int rc = EOK; 256 257 if (!IPC_GET_RETVAL(answer->data)) { 258 /* Accepted, handle as_area receipt */ 259 260 irq_spinlock_lock(&answer->sender->lock, true); 261 as_t *as = answer->sender->as; 262 irq_spinlock_unlock(&answer->sender->lock, true); 263 264 uintptr_t dst_base = (uintptr_t) -1; 265 rc = as_area_share(as, IPC_GET_ARG1(*olddata), 266 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata), 267 &dst_base, IPC_GET_ARG1(answer->data)); 268 269 if (rc == EOK) { 270 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data), 271 &dst_base, sizeof(dst_base)); 272 } 273 274 IPC_SET_RETVAL(answer->data, rc); 275 } 276 277 return rc; 278 } 279 280 static int a_preprocess_m_share_in(call_t *answer, ipc_data_t *olddata) 281 { 282 if (!IPC_GET_RETVAL(answer->data)) { 283 irq_spinlock_lock(&answer->sender->lock, true); 284 as_t *as = answer->sender->as; 285 irq_spinlock_unlock(&answer->sender->lock, true); 286 287 uintptr_t dst_base = (uintptr_t) -1; 288 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 289 IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data), 290 &dst_base, IPC_GET_ARG3(answer->data)); 291 IPC_SET_ARG4(answer->data, dst_base); 292 IPC_SET_RETVAL(answer->data, rc); 293 } 294 295 return EOK; 296 } 297 298 static int a_preprocess_m_data_read(call_t *answer, ipc_data_t *olddata) 299 { 300 ASSERT(!answer->buffer); 301 if (!IPC_GET_RETVAL(answer->data)) { 302 /* The recipient agreed to send data. */ 303 uintptr_t src = IPC_GET_ARG1(answer->data); 304 uintptr_t dst = IPC_GET_ARG1(*olddata); 305 size_t max_size = IPC_GET_ARG2(*olddata); 306 size_t size = IPC_GET_ARG2(answer->data); 307 if (size && size <= max_size) { 308 /* 309 * Copy the destination VA so that this piece of 310 * information is not lost. 311 */ 312 IPC_SET_ARG1(answer->data, dst); 313 314 answer->buffer = malloc(size, 0); 315 int rc = copy_from_uspace(answer->buffer, 316 (void *) src, size); 317 if (rc) { 318 IPC_SET_RETVAL(answer->data, rc); 319 free(answer->buffer); 320 answer->buffer = NULL; 321 } 322 } else if (!size) { 323 IPC_SET_RETVAL(answer->data, EOK); 324 } else { 325 IPC_SET_RETVAL(answer->data, ELIMIT); 326 } 327 } 328 329 return EOK; 330 } 331 332 static int a_preprocess_m_data_write(call_t *answer, ipc_data_t *olddata) 333 { 334 ASSERT(answer->buffer); 335 if (!IPC_GET_RETVAL(answer->data)) { 336 /* The recipient agreed to receive data. */ 337 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data); 338 size_t size = (size_t)IPC_GET_ARG2(answer->data); 339 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 340 341 if (size <= max_size) { 342 int rc = copy_to_uspace((void *) dst, 343 answer->buffer, size); 344 if (rc) 345 IPC_SET_RETVAL(answer->data, rc); 346 } else { 347 IPC_SET_RETVAL(answer->data, ELIMIT); 348 } 349 } 350 free(answer->buffer); 351 answer->buffer = NULL; 352 353 return EOK; 354 } 355 356 static int 357 a_preprocess_m_state_change_authorize(call_t *answer, ipc_data_t *olddata) 358 { 359 int rc = EOK; 360 361 if (!IPC_GET_RETVAL(answer->data)) { 362 /* The recipient authorized the change of state. */ 363 phone_t *recipient_phone; 364 task_t *other_task_s; 365 task_t *other_task_r; 366 367 rc = phone_get(IPC_GET_ARG1(answer->data), 368 &recipient_phone); 369 if (rc != EOK) { 370 IPC_SET_RETVAL(answer->data, ENOENT); 371 return ENOENT; 372 } 373 374 mutex_lock(&recipient_phone->lock); 375 if (recipient_phone->state != IPC_PHONE_CONNECTED) { 376 mutex_unlock(&recipient_phone->lock); 377 IPC_SET_RETVAL(answer->data, EINVAL); 378 return EINVAL; 379 } 380 381 other_task_r = recipient_phone->callee->task; 382 other_task_s = (task_t *) IPC_GET_ARG5(*olddata); 383 384 /* 385 * See if both the sender and the recipient meant the 386 * same third party task. 387 */ 388 if (other_task_r != other_task_s) { 389 IPC_SET_RETVAL(answer->data, EINVAL); 390 rc = EINVAL; 391 } else { 392 rc = event_task_notify_5(other_task_r, 393 EVENT_TASK_STATE_CHANGE, false, 394 IPC_GET_ARG1(*olddata), 395 IPC_GET_ARG2(*olddata), 396 IPC_GET_ARG3(*olddata), 397 LOWER32(olddata->task_id), 398 UPPER32(olddata->task_id)); 399 IPC_SET_RETVAL(answer->data, rc); 400 } 401 402 mutex_unlock(&recipient_phone->lock); 403 } 404 405 return rc; 406 } 407 176 408 /** Interpret process answer as control information. 177 409 * … … 181 413 * @param olddata Saved data of the request. 182 414 * 183 * @return Return 0 on success or an error code. 184 * 185 */ 186 static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata) 187 { 415 * @return Return EOK on success or a negative error code. 416 * 417 */ 418 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 419 { 420 int rc = EOK; 421 188 422 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { 189 423 /* In case of forward, hangup the forwared phone, … … 201 435 202 436 if (!olddata) 203 return 0; 204 205 if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECTION_CLONE) { 206 int phoneid = IPC_GET_ARG1(*olddata); 207 phone_t *phone = &TASK->phones[phoneid]; 208 209 if (IPC_GET_RETVAL(answer->data) != EOK) { 210 /* 211 * The recipient of the cloned phone rejected the offer. 212 * In this case, the connection was established at the 213 * request time and therefore we need to slam the phone. 214 * We don't merely hangup as that would result in 215 * sending IPC_M_HUNGUP to the third party on the 216 * other side of the cloned phone. 217 */ 218 mutex_lock(&phone->lock); 219 if (phone->state == IPC_PHONE_CONNECTED) { 220 irq_spinlock_lock(&phone->callee->lock, true); 221 list_remove(&phone->link); 222 phone->state = IPC_PHONE_SLAMMED; 223 irq_spinlock_unlock(&phone->callee->lock, true); 224 } 225 mutex_unlock(&phone->lock); 226 } 227 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CLONE_ESTABLISH) { 228 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 229 230 if (IPC_GET_RETVAL(answer->data) != EOK) { 231 /* 232 * The other party on the cloned phoned rejected our 233 * request for connection on the protocol level. 234 * We need to break the connection without sending 235 * IPC_M_HUNGUP back. 236 */ 237 mutex_lock(&phone->lock); 238 if (phone->state == IPC_PHONE_CONNECTED) { 239 irq_spinlock_lock(&phone->callee->lock, true); 240 list_remove(&phone->link); 241 phone->state = IPC_PHONE_SLAMMED; 242 irq_spinlock_unlock(&phone->callee->lock, true); 243 } 244 mutex_unlock(&phone->lock); 245 } 246 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_TO_ME) { 247 int phoneid = IPC_GET_ARG5(*olddata); 248 249 if (IPC_GET_RETVAL(answer->data) != EOK) { 250 /* The connection was not accepted */ 251 phone_dealloc(phoneid); 252 } else { 253 /* The connection was accepted */ 254 phone_connect(phoneid, &answer->sender->answerbox); 255 /* Set 'phone hash' as arg5 of response */ 256 IPC_SET_ARG5(answer->data, 257 (sysarg_t) &TASK->phones[phoneid]); 258 } 259 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME_TO) { 260 /* If the users accepted call, connect */ 261 if (IPC_GET_RETVAL(answer->data) == EOK) { 262 ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata), 263 &TASK->answerbox); 264 } 265 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_OUT) { 266 if (!IPC_GET_RETVAL(answer->data)) { 267 /* Accepted, handle as_area receipt */ 268 269 irq_spinlock_lock(&answer->sender->lock, true); 270 as_t *as = answer->sender->as; 271 irq_spinlock_unlock(&answer->sender->lock, true); 272 273 uintptr_t dst_base = (uintptr_t) -1; 274 int rc = as_area_share(as, IPC_GET_ARG1(*olddata), 275 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata), 276 &dst_base, IPC_GET_ARG1(answer->data)); 277 278 if (rc == EOK) 279 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data), 280 &dst_base, sizeof(dst_base)); 281 282 IPC_SET_RETVAL(answer->data, rc); 283 return rc; 284 } 285 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) { 286 if (!IPC_GET_RETVAL(answer->data)) { 287 irq_spinlock_lock(&answer->sender->lock, true); 288 as_t *as = answer->sender->as; 289 irq_spinlock_unlock(&answer->sender->lock, true); 290 291 uintptr_t dst_base = (uintptr_t) -1; 292 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 293 IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data), 294 &dst_base, IPC_GET_ARG3(answer->data)); 295 IPC_SET_ARG4(answer->data, dst_base); 296 IPC_SET_RETVAL(answer->data, rc); 297 } 298 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_READ) { 299 ASSERT(!answer->buffer); 300 if (!IPC_GET_RETVAL(answer->data)) { 301 /* The recipient agreed to send data. */ 302 uintptr_t src = IPC_GET_ARG1(answer->data); 303 uintptr_t dst = IPC_GET_ARG1(*olddata); 304 size_t max_size = IPC_GET_ARG2(*olddata); 305 size_t size = IPC_GET_ARG2(answer->data); 306 if (size && size <= max_size) { 307 /* 308 * Copy the destination VA so that this piece of 309 * information is not lost. 310 */ 311 IPC_SET_ARG1(answer->data, dst); 312 313 answer->buffer = malloc(size, 0); 314 int rc = copy_from_uspace(answer->buffer, 315 (void *) src, size); 316 if (rc) { 317 IPC_SET_RETVAL(answer->data, rc); 318 free(answer->buffer); 319 answer->buffer = NULL; 320 } 321 } else if (!size) { 322 IPC_SET_RETVAL(answer->data, EOK); 323 } else { 324 IPC_SET_RETVAL(answer->data, ELIMIT); 325 } 326 } 327 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_WRITE) { 328 ASSERT(answer->buffer); 329 if (!IPC_GET_RETVAL(answer->data)) { 330 /* The recipient agreed to receive data. */ 331 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data); 332 size_t size = (size_t)IPC_GET_ARG2(answer->data); 333 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 334 335 if (size <= max_size) { 336 int rc = copy_to_uspace((void *) dst, 337 answer->buffer, size); 338 if (rc) 339 IPC_SET_RETVAL(answer->data, rc); 340 } else { 341 IPC_SET_RETVAL(answer->data, ELIMIT); 342 } 343 } 344 free(answer->buffer); 345 answer->buffer = NULL; 346 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_STATE_CHANGE_AUTHORIZE) { 347 if (!IPC_GET_RETVAL(answer->data)) { 348 /* The recipient authorized the change of state. */ 349 phone_t *recipient_phone; 350 task_t *other_task_s; 351 task_t *other_task_r; 352 int rc; 353 354 rc = phone_get(IPC_GET_ARG1(answer->data), 355 &recipient_phone); 356 if (rc != EOK) { 357 IPC_SET_RETVAL(answer->data, ENOENT); 358 return ENOENT; 359 } 360 361 mutex_lock(&recipient_phone->lock); 362 if (recipient_phone->state != IPC_PHONE_CONNECTED) { 363 mutex_unlock(&recipient_phone->lock); 364 IPC_SET_RETVAL(answer->data, EINVAL); 365 return EINVAL; 366 } 367 368 other_task_r = recipient_phone->callee->task; 369 other_task_s = (task_t *) IPC_GET_ARG5(*olddata); 370 371 /* 372 * See if both the sender and the recipient meant the 373 * same third party task. 374 */ 375 if (other_task_r != other_task_s) { 376 IPC_SET_RETVAL(answer->data, EINVAL); 377 rc = EINVAL; 378 } else { 379 rc = event_task_notify_5(other_task_r, 380 EVENT_TASK_STATE_CHANGE, false, 381 IPC_GET_ARG1(*olddata), 382 IPC_GET_ARG2(*olddata), 383 IPC_GET_ARG3(*olddata), 384 LOWER32(olddata->task_id), 385 UPPER32(olddata->task_id)); 386 IPC_SET_RETVAL(answer->data, rc); 387 } 388 389 mutex_unlock(&recipient_phone->lock); 390 return rc; 391 } 392 } 393 394 return 0; 437 return rc; 438 439 switch (IPC_GET_IMETHOD(*olddata)) { 440 case IPC_M_CONNECTION_CLONE: 441 rc = a_preprocess_m_connection_clone(answer, olddata); 442 break; 443 case IPC_M_CLONE_ESTABLISH: 444 rc = a_preprocess_m_clone_establish(answer, olddata); 445 break; 446 case IPC_M_CONNECT_TO_ME: 447 rc = a_preprocess_m_connect_to_me(answer, olddata); 448 break; 449 case IPC_M_CONNECT_ME_TO: 450 rc = a_preprocess_m_connect_me_to(answer, olddata); 451 break; 452 case IPC_M_SHARE_OUT: 453 rc = a_preprocess_m_share_out(answer, olddata); 454 break; 455 case IPC_M_SHARE_IN: 456 rc = a_preprocess_m_share_in(answer, olddata); 457 break; 458 case IPC_M_DATA_READ: 459 rc = a_preprocess_m_data_read(answer, olddata); 460 break; 461 case IPC_M_DATA_WRITE: 462 rc = a_preprocess_m_data_write(answer, olddata); 463 break; 464 case IPC_M_STATE_CHANGE_AUTHORIZE: 465 rc = a_preprocess_m_state_change_authorize(answer, olddata); 466 break; 467 } 468 469 return rc; 395 470 } 396 471
Note:
See TracChangeset
for help on using the changeset viewer.