582 {
586}
587
588Status VMem::init(
int fd) {
590 for (
int i = 0;
i < MAX_SEGMENTS;
i++)
591 segments[
i] = VSeg(
NULL);
592 for (
int i = 0;
i < MAX_PROCESS;
i++) {
595 for (
int j = 0;
j <
i;
j++) {
596 close(channels[
j].fd_read);
597 close(channels[
j].fd_write);
598 }
599 return Status(ErrOS);
600 }
603 }
607 freelist = metapage->freelist;
608 return Status(ErrNone);
609}
610
611Status VMem::init() {
616 current_process = 0;
618 metapage->process_info[0].pid =
getpid();
619 return Status(ErrNone);
620}
621
622Status VMem::init(
const char *
path) {
625 return Status(ErrFile);
628
630 return Status(ErrNone);
631}
632
633void VMem::deinit() {
634 if (file_handle) {
637 } else {
639 }
640 munmap(metapage, METABLOCK_SIZE);
642 current_process = -1;
644 for (
int i = 0;
i < MAX_SEGMENTS;
i++) {
645 if (!segments[
i].is_free())
646 munmap(segments[
i].base, SEGMENT_SIZE);
647 segments[
i] = VSeg(
NULL);
648 }
649 for (
int i = 0;
i < MAX_PROCESS;
i++) {
650 close(channels[
i].fd_read);
651 close(channels[
i].fd_write);
652 }
653}
654
655void *VMem::mmap_segment(
int seg) {
658 METABLOCK_SIZE +
seg * SEGMENT_SIZE);
660
661
663 abort();
664 }
667}
668
669void VMem::add_segment() {
670 int seg = metapage->segment_count++;
671 ftruncate(
fd, METABLOCK_SIZE + metapage->segment_count * SEGMENT_SIZE);
675 top->next = freelist[LOG2_SEGMENT_SIZE];
677 freelist[LOG2_SEGMENT_SIZE] =
seg * SEGMENT_SIZE;
678}
679
680void FastLock::lock() {
681#ifdef HAVE_CPP_THREADS
682 while (_lock.test_and_set()) {
683 }
684 bool empty = _owner < 0;
685 if (empty) {
686 _owner = vmem.current_process;
687 } else {
688 int p = vmem.current_process;
689 vmem.metapage->process_info[
p].next = -1;
690 if (_head < 0)
692 else
693 vmem.metapage->process_info[_tail].next =
p;
695 }
696 _lock.clear();
697 if (!empty)
699#else
701#endif
702}
703
704void FastLock::unlock() {
705#ifdef HAVE_CPP_THREADS
706 while (_lock.test_and_set()) {
707 }
708 _owner = _head;
709 if (_owner >= 0)
710 _head = vmem.metapage->process_info[_head].next;
711 _lock.clear();
712 if (_owner >= 0)
714#else
716#endif
717}
718
720 vmem.metapage->allocator_lock.lock();
721}
722
724 vmem.metapage->allocator_lock.unlock();
725}
726
728 for (
int i = 0;
i <= LOG2_SEGMENT_SIZE;
i++) {
730 if (vaddr != VADDR_NULL) {
731 std::printf(
"%2d: %ld",
i, (
long)vaddr);
733 if (prev != VADDR_NULL) {
734 std::printf("(%ld)", (long)prev);
735 }
737 for (;;) {
741 if (vaddr == VADDR_NULL)
742 break;
743 std::printf(" -> %ld", (long)vaddr);
746 std::printf("(%ld)", (long)prev);
747 }
748 }
749 std::printf("\n");
750 }
751 }
753}
754
757 #if defined(__GNUC__) && (__GNUC__>11)
759 #else
761 #endif
762 vmem.ensure_is_mapped(vaddr);
763 size_t segno = vmem.segment_no(vaddr);
764 VSeg
seg = vmem.segment(vaddr);
766 int level =
seg.block_ptr(addr)->level();
768 while (
level < LOG2_SEGMENT_SIZE) {
771
773 break;
774
775 Block *prev = vmem.block_ptr(
block->prev);
776 Block *
next = vmem.block_ptr(
block->next);
778 if (prev) {
780 prev->next =
block->next;
781 } else {
782
785 }
789 }
790
794 }
795
801 if (
block->next != VADDR_NULL)
805}
806
809 #if defined(__GNUC__) && (__GNUC__>11)
811 #else
813 #endif
816 while (
flevel < LOG2_SEGMENT_SIZE && vmem.freelist[
flevel] == VADDR_NULL)
818 if (vmem.freelist[
flevel] == VADDR_NULL) {
819 vmem.add_segment();
820 }
821 vmem.ensure_is_mapped(vmem.freelist[
flevel]);
823
828 if (vmem.freelist[
flevel] != VADDR_NULL)
837
839 }
841 Block *
block = vmem.block_ptr(vmem.freelist[
level]);
843 #if defined(__GNUC__) && (__GNUC__>11)
845 #else
847 #endif
849 if (
block->next != VADDR_NULL)
855}
856
864}
865
870}
871
876}
877
880}
881
884}
885
889 vmem.metapage = (MetaPage *)
mmap(
892 std::memcpy(vmem.metapage->config_header, config, sizeof(config));
893 for (
int i = 0;
i <= LOG2_SEGMENT_SIZE;
i++) {
895 }
896 vmem.metapage->segment_count = 0;
898 } else {
899 assert(std::memcmp(vmem.metapage->config_header, config,
900 sizeof(config)) != 0);
901 }
902}
903
907 + sizeof(ProcessInfo) * vmem.current_process);
908}
909
913 + sizeof(ProcessInfo) * vmem.current_process);
914}
915
917 return vmem.metapage->process_info[
processno];
918}
919
921 if (lock)
925 return false;
926 }
930 } else {
935 while (write(
fd,
buf, 1) != 1) {
936 }
937 }
938 if (lock)
940 return true;
941}
942
945 if (lock)
948 switch (sigstate) {
951 int fd = vmem.channels[vmem.current_process].fd_read;
953 if (lock && sigstate == Waiting) {
956 }
958 } else {
960 }
961 }
965 if (lock)
967 break;
968 }
973 if (lock)
975 break;
976 }
978}
979
984}
985
988}
989
990}
991
993 using namespace internals;
995 for (
int p = 0;
p < MAX_PROCESS;
p++) {
996 if (vmem.metapage->process_info[
p].pid == 0) {
998 if (pid < 0) {
999
1000 return -1;
1001 } else if (pid == 0) {
1002
1003 int parent = vmem.current_process;
1004 vmem.current_process =
p;
1006 vmem.metapage->process_info[
p].pid =
getpid();
1009 } else {
1010
1013
1014 }
1015 return pid;
1016 }
1017 }
1019 return -1;
1020}
1021
1024 internals::ipc_signal_t sig;
1025 _lock.lock();
1026 if (_head == _tail) {
1027 _value++;
1028 } else {
1029
1030 wakeup = _waiting[_head];
1031 sig = _signals[_head];
1033 }
1034 _lock.unlock();
1036 internals::send_signal(
wakeup, sig);
1037 }
1038}
1039
1040bool Semaphore::try_wait() {
1042 _lock.lock();
1043 if (_value > 0) {
1044 _value--;
1046 }
1047 _lock.unlock();
1049}
1050
1052 _lock.lock();
1053 if (_value > 0) {
1054 _value--;
1055 _lock.unlock();
1056 return;
1057 }
1058 _waiting[_tail] = internals::vmem.current_process;
1059 _signals[_tail] = 0;
1061 _lock.unlock();
1062 internals::wait_signal();
1063}
1064
1065bool Semaphore::start_wait(internals::ipc_signal_t sig) {
1066 _lock.lock();
1067 if (_value > 0) {
1068 if (internals::send_signal(internals::vmem.current_process, sig))
1069 _value--;
1070 _lock.unlock();
1071 return false;
1072 }
1073 _waiting[_tail] = internals::vmem.current_process;
1074 _signals[_tail] = sig;
1076 _lock.unlock();
1077 return true;
1078}
1079
1080bool Semaphore::stop_wait() {
1082 _lock.lock();
1083 for (
int i = _head;
i != _tail;
next(
i)) {
1084 if (_waiting[
i] == internals::vmem.current_process) {
1087 while (
i != _tail) {
1088 _waiting[
last] = _waiting[
i];
1089 _signals[
last] = _signals[
i];
1092 }
1095 break;
1096 }
1097 }
1098 _lock.unlock();
1100}
1101
1102void EventSet::add(Event *
event) {
1103 event->_next =
NULL;
1104 if (_head ==
NULL) {
1105 _head = _tail =
event;
1106 } else {
1107 _tail->_next =
event;
1109 }
1110}
1111
1112int EventSet::wait() {
1113 size_t n = 0;
1114 for (Event *
event = _head;
event;
event =
event->_next) {
1115 if (!
event->start_listen((
int) (n++))) {
1116 break;
1117 }
1118 }
1119 internals::ipc_signal_t
result = internals::check_signal();
1120 for (Event *
event = _head;
event;
event =
event->_next) {
1121 event->stop_listen();
1122 }
1123 internals::accept_signals();
1125}
1126
1127}
1128#endif
1129#endif
CanonicalForm map(const CanonicalForm &primElem, const Variable &alpha, const CanonicalForm &F, const Variable &beta)
map from to such that is mapped onto
void init_flock_struct(struct flock &lock_info, size_t offset, size_t len, bool lock)
static ProcessInfo & process_info(int processno)
void lock_file(int fd, size_t offset, size_t len)
void vmem_free(vaddr_t vaddr)
Block * block_ptr(vaddr_t vaddr)
vaddr_t vmem_alloc(size_t size)
static void unlock_process(int processno)
static void lock_process(int processno)
ipc_signal_t wait_signal(bool lock)
static void lock_allocator()
ipc_signal_t check_signal(bool resume, bool lock)
void init_metapage(bool create)
void unlock_file(int fd, size_t offset, size_t len)
bool send_signal(int processno, ipc_signal_t sig, bool lock)
static void unlock_allocator()
static void print_freelists()
internals::Mutex FastLock
int status int void size_t count open
int status int void * buf
#define metapageaddr(field)