syscall_emul.hh (13650:93efc0143eb7) | syscall_emul.hh (13651:b33db942f760) |
---|---|
1/* 2 * Copyright (c) 2012-2013, 2015 ARM Limited 3 * Copyright (c) 2015 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating --- 441 unchanged lines hidden (view full) --- 450 int mem_val = *(int*)buf.bufferPtr(); 451 /* 452 * For CMP_REQUEUE, the whole operation is only started only if 453 * val3 is still the value of the futex pointed to by uaddr. 454 */ 455 if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val) 456 return -OS::TGT_EWOULDBLOCK; 457 return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2); | 1/* 2 * Copyright (c) 2012-2013, 2015 ARM Limited 3 * Copyright (c) 2015 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating --- 441 unchanged lines hidden (view full) --- 450 int mem_val = *(int*)buf.bufferPtr(); 451 /* 452 * For CMP_REQUEUE, the whole operation is only started only if 453 * val3 is still the value of the futex pointed to by uaddr. 454 */ 455 if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val) 456 return -OS::TGT_EWOULDBLOCK; 457 return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2); |
458 } else if (OS::TGT_FUTEX_WAKE_OP == op) { 459 /* 460 * The FUTEX_WAKE_OP operation is equivalent to executing the 461 * following code atomically and totally ordered with respect to 462 * other futex operations on any of the two supplied futex words: 463 * 464 * int oldval = *(int *) addr2; 465 * *(int *) addr2 = oldval op oparg; 466 * futex(addr1, FUTEX_WAKE, val, 0, 0, 0); 467 * if (oldval cmp cmparg) 468 * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0); 469 * 470 * (op, oparg, cmp, cmparg are encoded in val3) 471 * 472 * +---+---+-----------+-----------+ 473 * |op |cmp| oparg | cmparg | 474 * +---+---+-----------+-----------+ 475 * 4 4 12 12 <== # of bits 476 * 477 * reference: http://man7.org/linux/man-pages/man2/futex.2.html 478 * 479 */ 480 // get value from simulated-space 481 BufferArg buf(uaddr2, sizeof(int)); 482 buf.copyIn(tc->getMemProxy()); 483 int oldval = *(int*)buf.bufferPtr(); 484 int newval = oldval; 485 // extract op, oparg, cmp, cmparg from val3 486 int wake_cmparg = val3 & 0xfff; 487 int wake_oparg = (val3 & 0xfff000) >> 12; 488 int wake_cmp = (val3 & 0xf000000) >> 24; 489 int wake_op = (val3 & 0xf0000000) >> 28; 490 if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1) 491 wake_oparg = (1 << wake_oparg); 492 wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT; 493 // perform operation on the value of the second futex 494 if (wake_op == OS::TGT_FUTEX_OP_SET) 495 newval = wake_oparg; 496 else if (wake_op == OS::TGT_FUTEX_OP_ADD) 497 newval += wake_oparg; 498 else if (wake_op == OS::TGT_FUTEX_OP_OR) 499 newval |= wake_oparg; 500 else if (wake_op == OS::TGT_FUTEX_OP_ANDN) 501 newval &= ~wake_oparg; 502 else if (wake_op == OS::TGT_FUTEX_OP_XOR) 503 newval ^= wake_oparg; 504 // copy updated value back to simulated-space 505 *(int*)buf.bufferPtr() = newval; 506 buf.copyOut(tc->getMemProxy()); 507 // perform the first wake-up 508 int woken1 = futex_map.wakeup(uaddr, process->tgid(), val); 509 int woken2 = 0; 510 // calculate the condition of the second wake-up 511 bool is_wake2 = false; 512 if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ) 513 is_wake2 = oldval == wake_cmparg; 514 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE) 515 is_wake2 = oldval != wake_cmparg; 516 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT) 517 is_wake2 = oldval < wake_cmparg; 518 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE) 519 is_wake2 = oldval <= wake_cmparg; 520 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT) 521 is_wake2 = oldval > wake_cmparg; 522 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE) 523 is_wake2 = oldval >= wake_cmparg; 524 // perform the second wake-up 525 if (is_wake2) 526 woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout); 527 528 return woken1 + woken2; |
|
458 } 459 warn("futex: op %d not implemented; ignoring.", op); 460 return -ENOSYS; 461} 462 463 464/// Pseudo Funcs - These functions use a different return convension, 465/// returning a second value in a register other than the normal return register --- 2241 unchanged lines hidden --- | 529 } 530 warn("futex: op %d not implemented; ignoring.", op); 531 return -ENOSYS; 532} 533 534 535/// Pseudo Funcs - These functions use a different return convension, 536/// returning a second value in a register other than the normal return register --- 2241 unchanged lines hidden --- |