628 {
632}
633
634Status VMem::init(
int fd) {
636 for (
int i = 0;
i < MAX_SEGMENTS;
i++)
637 segments[
i] = VSeg(
NULL);
638 for (
int i = 0;
i < MAX_PROCESS;
i++) {
641 for (
int j = 0;
j <
i;
j++) {
642 close(channels[
j].fd_read);
643 close(channels[
j].fd_write);
644 }
645 return Status(ErrOS);
646 }
649 }
653 freelist = metapage->freelist;
654 return Status(ErrNone);
655}
656
657Status VMem::init() {
662 current_process = 0;
664 metapage->process_info[0].pid =
getpid();
665 return Status(ErrNone);
666}
667
668Status VMem::init(
const char *
path) {
671 return Status(ErrFile);
674
676 return Status(ErrNone);
677}
678
679void VMem::deinit() {
680 if (file_handle) {
683 } else {
685 }
686 munmap(metapage, METABLOCK_SIZE);
688 current_process = -1;
690 for (
int i = 0;
i < MAX_SEGMENTS;
i++) {
691 if (!segments[
i].is_free())
692 munmap(segments[
i].base, SEGMENT_SIZE);
693 segments[
i] = VSeg(
NULL);
694 }
695 for (
int i = 0;
i < MAX_PROCESS;
i++) {
696 close(channels[
i].fd_read);
697 close(channels[
i].fd_write);
698 }
699}
700
701void *VMem::mmap_segment(
int seg) {
704 METABLOCK_SIZE +
seg * SEGMENT_SIZE);
706
707
709 abort();
710 }
713}
714
715void VMem::add_segment() {
716 int seg = metapage->segment_count++;
717 ftruncate(
fd, METABLOCK_SIZE + metapage->segment_count * SEGMENT_SIZE);
721 top->next = freelist[LOG2_SEGMENT_SIZE];
723 freelist[LOG2_SEGMENT_SIZE] =
seg * SEGMENT_SIZE;
724}
725
726void FastLock::lock() {
727#ifdef HAVE_CPP_THREADS
728 while (_lock.test_and_set()) {
729 }
730 bool empty = _owner < 0;
731 if (empty) {
732 _owner = vmem.current_process;
733 } else {
734 int p = vmem.current_process;
735 vmem.metapage->process_info[
p].next = -1;
736 if (_head < 0)
738 else
739 vmem.metapage->process_info[_tail].next =
p;
741 }
742 _lock.clear();
743 if (!empty)
745#else
747#endif
748}
749
750void FastLock::unlock() {
751#ifdef HAVE_CPP_THREADS
752 while (_lock.test_and_set()) {
753 }
754 _owner = _head;
755 if (_owner >= 0)
756 _head = vmem.metapage->process_info[_head].next;
757 _lock.clear();
758 if (_owner >= 0)
760#else
762#endif
763}
764
766 vmem.metapage->allocator_lock.lock();
767}
768
770 vmem.metapage->allocator_lock.unlock();
771}
772
774 for (
int i = 0;
i <= LOG2_SEGMENT_SIZE;
i++) {
776 if (vaddr != VADDR_NULL) {
777 std::printf(
"%2d: %ld",
i, (
long)vaddr);
779 if (prev != VADDR_NULL) {
780 std::printf("(%ld)", (long)prev);
781 }
783 for (;;) {
787 if (vaddr == VADDR_NULL)
788 break;
789 std::printf(" -> %ld", (long)vaddr);
792 std::printf("(%ld)", (long)prev);
793 }
794 }
795 std::printf("\n");
796 }
797 }
799}
800
803 #if defined(__GNUC__) && (__GNUC__>11)
805 #else
807 #endif
808 vmem.ensure_is_mapped(vaddr);
809 size_t segno = vmem.segment_no(vaddr);
810 VSeg
seg = vmem.segment(vaddr);
812 int level =
seg.block_ptr(addr)->level();
814 while (
level < LOG2_SEGMENT_SIZE) {
817
819 break;
820
821 Block *prev = vmem.block_ptr(
block->prev);
822 Block *
next = vmem.block_ptr(
block->next);
824 if (prev) {
826 prev->next =
block->next;
827 } else {
828
831 }
835 }
836
840 }
841
847 if (
block->next != VADDR_NULL)
851}
852
855 #if defined(__GNUC__) && (__GNUC__>11)
857 #else
859 #endif
862 while (
flevel < LOG2_SEGMENT_SIZE && vmem.freelist[
flevel] == VADDR_NULL)
864 if (vmem.freelist[
flevel] == VADDR_NULL) {
865 vmem.add_segment();
866 }
867 vmem.ensure_is_mapped(vmem.freelist[
flevel]);
869
874 if (vmem.freelist[
flevel] != VADDR_NULL)
883
885 }
887 Block *
block = vmem.block_ptr(vmem.freelist[
level]);
889 #if defined(__GNUC__) && (__GNUC__>11)
891 #else
893 #endif
895 if (
block->next != VADDR_NULL)
901}
902
910}
911
916}
917
922}
923
926}
927
930}
931
935 vmem.metapage = (MetaPage *)
mmap(
938 std::memcpy(vmem.metapage->config_header, config, sizeof(config));
939 for (
int i = 0;
i <= LOG2_SEGMENT_SIZE;
i++) {
941 }
942 vmem.metapage->segment_count = 0;
944 } else {
945 assert(std::memcmp(vmem.metapage->config_header, config,
946 sizeof(config)) != 0);
947 }
948}
949
953 + sizeof(ProcessInfo) * vmem.current_process);
954}
955
959 + sizeof(ProcessInfo) * vmem.current_process);
960}
961
963 return vmem.metapage->process_info[
processno];
964}
965
967 if (lock)
971 return false;
972 }
976 } else {
981 while (write(
fd,
buf, 1) != 1) {
982 }
983 }
984 if (lock)
986 return true;
987}
988
991 if (lock)
994 switch (sigstate) {
997 int fd = vmem.channels[vmem.current_process].fd_read;
999 if (lock && sigstate == Waiting) {
1002 {
1003 #if defined(HAVE_POLL) && !defined(__APPLE__)
1004
1009 #else
1010
1018 #endif
1019 if (
rv== -1)
continue;
1022 break;
1023 }
1025 } else {
1027 {
1028 #if defined(HAVE_POLL) && !defined(__APPLE__)
1029
1034 #else
1035
1043 #endif
1044 if (
rv== -1)
continue;
1047 break;
1048 }
1049 }
1053 if (lock)
1055 break;
1056 }
1061 if (lock)
1063 break;
1064 }
1066}
1067
1072}
1073
1076}
1077
1078}
1079
1081 using namespace internals;
1083 for (
int p = 0;
p < MAX_PROCESS;
p++) {
1084 if (vmem.metapage->process_info[
p].pid == 0) {
1086 if (pid < 0) {
1087
1088 return -1;
1089 } else if (pid == 0) {
1090
1091 int parent = vmem.current_process;
1092 vmem.current_process =
p;
1094 vmem.metapage->process_info[
p].pid =
getpid();
1097 } else {
1098
1101
1102 }
1103 return pid;
1104 }
1105 }
1107 return -1;
1108}
1109
1112 internals::ipc_signal_t sig;
1113 _lock.lock();
1114 if (_head == _tail) {
1115 _value++;
1116 } else {
1117
1118 wakeup = _waiting[_head];
1119 sig = _signals[_head];
1121 }
1122 _lock.unlock();
1124 internals::send_signal(
wakeup, sig);
1125 }
1126}
1127
1128bool Semaphore::try_wait() {
1130 _lock.lock();
1131 if (_value > 0) {
1132 _value--;
1134 }
1135 _lock.unlock();
1137}
1138
1140 _lock.lock();
1141 if (_value > 0) {
1142 _value--;
1143 _lock.unlock();
1144 return;
1145 }
1146 _waiting[_tail] = internals::vmem.current_process;
1147 _signals[_tail] = 0;
1149 _lock.unlock();
1150 internals::wait_signal();
1151}
1152
1153bool Semaphore::start_wait(internals::ipc_signal_t sig) {
1154 _lock.lock();
1155 if (_value > 0) {
1156 if (internals::send_signal(internals::vmem.current_process, sig))
1157 _value--;
1158 _lock.unlock();
1159 return false;
1160 }
1161 _waiting[_tail] = internals::vmem.current_process;
1162 _signals[_tail] = sig;
1164 _lock.unlock();
1165 return true;
1166}
1167
1168bool Semaphore::stop_wait() {
1170 _lock.lock();
1171 for (
int i = _head;
i != _tail;
next(
i)) {
1172 if (_waiting[
i] == internals::vmem.current_process) {
1175 while (
i != _tail) {
1176 _waiting[
last] = _waiting[
i];
1177 _signals[
last] = _signals[
i];
1180 }
1183 break;
1184 }
1185 }
1186 _lock.unlock();
1188}
1189
1190void EventSet::add(Event *
event) {
1191 event->_next =
NULL;
1192 if (_head ==
NULL) {
1193 _head = _tail =
event;
1194 } else {
1195 _tail->_next =
event;
1197 }
1198}
1199
1200int EventSet::wait() {
1201 size_t n = 0;
1202 for (Event *
event = _head;
event;
event =
event->_next) {
1203 if (!
event->start_listen((
int) (n++))) {
1204 break;
1205 }
1206 }
1207 internals::ipc_signal_t
result = internals::check_signal();
1208 for (Event *
event = _head;
event;
event =
event->_next) {
1209 event->stop_listen();
1210 }
1211 internals::accept_signals();
1213}
1214
1215}
1216#endif
1217#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)