Changeset 7c23af9 in mainline for generic/src/mm/as.c
- Timestamp:
- 2006-05-14T17:16:52Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 14b502e2
- Parents:
- 68965ec5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/as.c
r68965ec5 r7c23af9 365 365 } 366 366 367 /** Send address space area to another task. 368 * 369 * Address space area is sent to the specified task. 370 * If the destination task is willing to accept the 371 * area, a new area is created according to the 372 * source area. Moreover, any existing mapping 367 /** Steal address space area from another task. 368 * 369 * Address space area is stolen from another task 370 * Moreover, any existing mapping 373 371 * is copied as well, providing thus a mechanism 374 372 * for sharing group of pages. The source address 375 373 * space area and any associated mapping is preserved. 376 374 * 377 * @param dst_id Task ID of the accepting task.375 * @param src_task Pointer of source task 378 376 * @param src_base Base address of the source address space area. 377 * @param acc_size Expected size of the source area 378 * @param dst_base Target base address 379 379 * 380 380 * @return Zero on success or ENOENT if there is no such task or … … 384 384 * address space area. 385 385 */ 386 int as_area_send(task_id_t dst_id, __address src_base) 386 int as_area_steal(task_t *src_task, __address src_base, size_t acc_size, 387 __address dst_base) 387 388 { 388 389 ipl_t ipl; 389 task_t *t;390 390 count_t i; 391 as_t *dst_as; 392 __address dst_base; 391 as_t *src_as; 393 392 int src_flags; 394 393 size_t src_size; 395 394 as_area_t *src_area, *dst_area; 396 395 397 396 ipl = interrupts_disable(); 398 spinlock_lock(&tasks_lock); 399 400 t = task_find_by_id(dst_id); 401 if (!NULL) { 402 spinlock_unlock(&tasks_lock); 403 interrupts_restore(ipl); 404 return ENOENT; 405 } 406 407 spinlock_lock(&t->lock); 408 spinlock_unlock(&tasks_lock); 409 410 dst_as = t->as; 411 dst_base = (__address) t->accept_arg.base; 412 413 if (dst_as == AS) { 414 /* 415 * The two tasks share the entire address space. 416 * Return error since there is no point in continuing. 417 */ 418 spinlock_unlock(&t->lock); 419 interrupts_restore(ipl); 420 return EPERM; 421 } 422 423 spinlock_lock(&AS->lock); 424 src_area = find_area_and_lock(AS, src_base); 397 spinlock_lock(&src_task->lock); 398 src_as = src_task->as; 399 400 spinlock_lock(&src_as->lock); 401 src_area = find_area_and_lock(src_as, src_base); 425 402 if (!src_area) { 426 403 /* 427 404 * Could not find the source address space area. 428 405 */ 429 spinlock_unlock(& t->lock);430 spinlock_unlock(& AS->lock);406 spinlock_unlock(&src_task->lock); 407 spinlock_unlock(&src_as->lock); 431 408 interrupts_restore(ipl); 432 409 return ENOENT; … … 435 412 src_flags = src_area->flags; 436 413 spinlock_unlock(&src_area->lock); 437 spinlock_unlock(&AS->lock); 438 439 if ((t->accept_arg.task_id != TASK->taskid) || (t->accept_arg.size != src_size) || 440 (t->accept_arg.flags != src_flags)) { 441 /* 442 * Discrepancy in either task ID, size or flags. 443 */ 444 spinlock_unlock(&t->lock); 414 spinlock_unlock(&src_as->lock); 415 416 417 if (src_size != acc_size) { 418 spinlock_unlock(&src_task->lock); 445 419 interrupts_restore(ipl); 446 420 return EPERM; 447 421 } 448 449 422 /* 450 423 * Create copy of the source address space area. … … 453 426 * preliminary as_page_fault() calls. 454 427 */ 455 dst_area = as_area_create( dst_as, src_flags, src_size, dst_base, AS_AREA_ATTR_PARTIAL);428 dst_area = as_area_create(AS, src_flags, src_size, dst_base, AS_AREA_ATTR_PARTIAL); 456 429 if (!dst_area) { 457 430 /* 458 431 * Destination address space area could not be created. 459 432 */ 460 spinlock_unlock(& t->lock);433 spinlock_unlock(&src_task->lock); 461 434 interrupts_restore(ipl); 462 435 return ENOMEM; 463 436 } 464 437 465 memsetb((__address) &t->accept_arg, sizeof(as_area_acptsnd_arg_t), 0); 466 spinlock_unlock(&t->lock); 438 spinlock_unlock(&src_task->lock); 467 439 468 440 /* 469 441 * Avoid deadlock by first locking the address space with lower address. 470 442 */ 471 if (dst_as < AS) { 472 spinlock_lock(&dst_as->lock); 443 if (AS < src_as) { 473 444 spinlock_lock(&AS->lock); 445 spinlock_lock(&src_as->lock); 474 446 } else { 475 447 spinlock_lock(&AS->lock); 476 spinlock_lock(& dst_as->lock);448 spinlock_lock(&src_as->lock); 477 449 } 478 450 … … 481 453 __address frame; 482 454 483 page_table_lock( AS, false);484 pte = page_mapping_find( AS, src_base + i*PAGE_SIZE);455 page_table_lock(src_as, false); 456 pte = page_mapping_find(src_as, src_base + i*PAGE_SIZE); 485 457 if (pte && PTE_VALID(pte)) { 486 458 ASSERT(PTE_PRESENT(pte)); … … 488 460 if (!(src_flags & AS_AREA_DEVICE)) 489 461 frame_reference_add(ADDR2PFN(frame)); 490 page_table_unlock( AS, false);462 page_table_unlock(src_as, false); 491 463 } else { 492 page_table_unlock( AS, false);464 page_table_unlock(src_as, false); 493 465 continue; 494 466 } 495 467 496 page_table_lock( dst_as, false);497 page_mapping_insert( dst_as, dst_base + i*PAGE_SIZE, frame, area_flags_to_page_flags(src_flags));498 page_table_unlock( dst_as, false);468 page_table_lock(AS, false); 469 page_mapping_insert(AS, dst_base + i*PAGE_SIZE, frame, area_flags_to_page_flags(src_flags)); 470 page_table_unlock(AS, false); 499 471 } 500 472 … … 509 481 510 482 spinlock_unlock(&AS->lock); 511 spinlock_unlock(& dst_as->lock);483 spinlock_unlock(&src_as->lock); 512 484 interrupts_restore(ipl); 513 485 … … 946 918 } 947 919 920 /** Return size of address space of current task pointed to by base */ 921 size_t as_get_size(__address base) 922 { 923 ipl_t ipl; 924 as_area_t *src_area; 925 size_t size; 926 927 ipl = interrupts_disable(); 928 src_area = find_area_and_lock(AS, base); 929 if (src_area){ 930 size = src_area->pages * PAGE_SIZE; 931 spinlock_unlock(&src_area->lock); 932 } else { 933 size = 0; 934 } 935 interrupts_restore(ipl); 936 return size; 937 } 938 948 939 /* 949 940 * Address space related syscalls. … … 971 962 } 972 963 973 /** Prepare task for accepting address space area from another task.974 *975 * @param uspace_accept_arg Accept structure passed from userspace.976 *977 * @return EPERM if the task ID encapsulated in @uspace_accept_arg references978 * TASK. Otherwise zero is returned.979 */980 __native sys_as_area_accept(as_area_acptsnd_arg_t *uspace_accept_arg)981 {982 as_area_acptsnd_arg_t arg;983 int rc;984 985 rc = copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t));986 if (rc != 0)987 return rc;988 989 if (!arg.size)990 return (__native) EPERM;991 992 if (arg.task_id == TASK->taskid) {993 /*994 * Accepting from itself is not allowed.995 */996 return (__native) EPERM;997 }998 999 memcpy(&TASK->accept_arg, &arg, sizeof(as_area_acptsnd_arg_t));1000 1001 return 0;1002 }1003 1004 /** Wrapper for as_area_send. */1005 __native sys_as_area_send(as_area_acptsnd_arg_t *uspace_send_arg)1006 {1007 as_area_acptsnd_arg_t arg;1008 int rc;1009 1010 rc = copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t));1011 if (rc != 0)1012 return rc;1013 1014 if (!arg.size)1015 return (__native) EPERM;1016 1017 if (arg.task_id == TASK->taskid) {1018 /*1019 * Sending to itself is not allowed.1020 */1021 return (__native) EPERM;1022 }1023 1024 return (__native) as_area_send(arg.task_id, (__address) arg.base);1025 }
Note:
See TracChangeset
for help on using the changeset viewer.