| 607 | } |
| 608 | |
| 609 | int bthread_id_unlock_and_destroy(bthread_id_t id) { |
| 610 | bthread::Id* const meta = address_resource(bthread::get_slot(id)); |
| 611 | if (!meta) { |
| 612 | return EINVAL; |
| 613 | } |
| 614 | uint32_t* butex = meta->butex; |
| 615 | uint32_t* join_butex = meta->join_butex; |
| 616 | const uint32_t id_ver = bthread::get_version(id); |
| 617 | meta->mutex.lock(); |
| 618 | if (!meta->has_version(id_ver)) { |
| 619 | meta->mutex.unlock(); |
| 620 | LOG(FATAL) << "Invalid bthread_id=" << id.value; |
| 621 | return EINVAL; |
| 622 | } |
| 623 | if (*butex == meta->first_ver) { |
| 624 | meta->mutex.unlock(); |
| 625 | LOG(FATAL) << "bthread_id=" << id.value << " is not locked!"; |
| 626 | return EPERM; |
| 627 | } |
| 628 | const uint32_t next_ver = meta->end_ver(); |
| 629 | *butex = next_ver; |
| 630 | *join_butex = next_ver; |
| 631 | meta->first_ver = next_ver; |
| 632 | meta->locked_ver = next_ver; |
| 633 | meta->pending_q.clear(); |
| 634 | meta->mutex.unlock(); |
| 635 | // Notice that butex_wake* returns # of woken-up, not successful or not. |
| 636 | bthread::butex_wake_except(butex, 0); |
| 637 | bthread::butex_wake_all(join_butex); |
| 638 | return_resource(bthread::get_slot(id)); |
| 639 | return 0; |
| 640 | } |
| 641 | |
| 642 | int bthread_id_list_init(bthread_id_list_t* list, |
| 643 | unsigned /*size*/, |