17#if defined(__GNUC__) && (__GNUC__<9) &&!defined(__clang__)
30#define metapageaddr(field) \
31 ((char *) &vmem.metapage->field - (char *) vmem.metapage)
45 if (pipe(channel) < 0) {
46 for (
int j = 0;
j <
i;
j++) {
69 metapage->process_info[0].pid = getpid();
74 int fd =
open(path, O_RDWR | O_CREAT, 0600);
109 if (
map == MAP_FAILED) {
120 int seg =
metapage->segment_count++;
124 snprintf(err_msg,
sizeof(err_msg),
"out of memory in vspace:add_segment: %s", strerror(errno));
137#ifdef HAVE_CPP_THREADS
138 while (
_lock.test_and_set()) {
161#ifdef HAVE_CPP_THREADS
162 while (
_lock.test_and_set()) {
176 vmem.metapage->allocator_lock.lock();
180 vmem.metapage->allocator_lock.unlock();
187 printf(
"%2d: %ld",
i, (
long)vaddr);
190 printf(
"(%ld)", (
long)prev);
199 printf(
" -> %ld", (
long)vaddr);
201 if (prev != last_vaddr) {
202 printf(
"(%ld)", (
long)prev);
213 vaddr -= offsetof(
Block, data);
214 vmem.ensure_is_mapped(vaddr);
215 size_t segno =
vmem.segment_no(vaddr);
218 int level = seg.block_ptr(addr)->level();
219 assert(!seg.is_free(addr));
231 assert(prev->next ==
vmem.vaddr(segno, buddy));
232 prev->next =
block->next;
254 vmem.block_ptr(
block->next)->prev = blockaddr;
261 size_t alloc_size =
size + offsetof(
Block, data);
269 vmem.ensure_is_mapped(
vmem.freelist[flevel]);
270 while (flevel >
level) {
273 assert((blockaddr & ((1 << flevel) - 1)) == 0);
278 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
279 Block *block2 =
vmem.block_ptr(blockaddr2);
281 block2->next =
vmem.freelist[flevel];
282 block2->prev = blockaddr;
283 block->next = blockaddr2;
286 vmem.freelist[flevel] = blockaddr;
291 #if defined(__GNUC__) && (__GNUC__>11)
306 struct flock &lock_info,
size_t offset,
size_t len,
bool lock) {
307 lock_info.l_start =
offset;
308 lock_info.l_len = len;
310 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
315 struct flock lock_info;
317 fcntl(
fd, F_SETLKW, &lock_info);
321 struct flock lock_info;
323 fcntl(
fd, F_SETLKW, &lock_info);
338 snprintf(err_msg,
sizeof(err_msg),
"out of memory in vspace:init_metapage: %s", strerror(errno));
350 vmem.metapage->segment_count = 0;
370 return vmem.metapage->process_info[processno];
380 if (processno ==
vmem.current_process) {
386 int fd =
vmem.channels[processno].fd_write;
388 while (write(
fd,
buf, 1) != 1) {
404 int fd =
vmem.channels[
vmem.current_process].fd_read;
406 if (lock && sigstate ==
Waiting) {
410 #if defined(HAVE_POLL) && !defined(__APPLE__)
415 int rv = poll(&pfd, 1, 500000);
421 struct timeval timeout;
422 timeout.tv_sec = 500;
424 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
426 if (rv== -1)
continue;
435 #if defined(HAVE_POLL) && !defined(__APPLE__)
440 int rv = poll(&pfd, 1, 500000);
446 struct timeval timeout;
447 timeout.tv_sec = 500;
449 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
451 if (rv== -1)
continue;
490 for (
int p = 0;
p < MAX_PROCESS;
p++) {
491 if (vmem.metapage->process_info[
p].pid == 0) {
496 }
else if (pid == 0) {
498 int parent = vmem.current_process;
499 vmem.current_process =
p;
501 vmem.metapage->process_info[
p].pid = getpid();
602 _tail->_next = event;
609 for (Event *event =
_head; event;
event =
event->_next) {
610 if (!event->start_listen((
int) (n++))) {
615 for (Event *event =
_head; event;
event =
event->_next) {
616 event->stop_listen();
641#define metapageaddr(field) \
642 ((char *) &vmem.metapage->field - (char *) vmem.metapage)
656 if (pipe(channel) < 0) {
657 for (
int j = 0;
j <
i;
j++) {
674 FILE *
fp = tmpfile();
680 metapage->process_info[0].pid = getpid();
685 int fd =
open(path, O_RDWR | O_CREAT, 0600);
721 if (
map == MAP_FAILED) {
732 int seg =
metapage->segment_count++;
736 snprintf(err_msg,
sizeof(err_msg),
"out of memory in vspace:add_segment: %s", strerror(errno));
749#ifdef HAVE_CPP_THREADS
750 while (_lock.test_and_set()) {
752 bool empty = _owner < 0;
754 _owner =
vmem.current_process;
756 int p =
vmem.current_process;
757 vmem.metapage->process_info[
p].next = -1;
761 vmem.metapage->process_info[_tail].next =
p;
773#ifdef HAVE_CPP_THREADS
774 while (_lock.test_and_set()) {
778 _head =
vmem.metapage->process_info[_head].next;
788 vmem.metapage->allocator_lock.lock();
792 vmem.metapage->allocator_lock.unlock();
799 std::printf(
"%2d: %ld",
i, (
long)vaddr);
802 std::printf(
"(%ld)", (
long)prev);
811 std::printf(
" -> %ld", (
long)vaddr);
813 if (prev != last_vaddr) {
814 std::printf(
"(%ld)", (
long)prev);
825 #if defined(__GNUC__) && (__GNUC__>11)
828 vaddr -= offsetof(
Block, data);
830 vmem.ensure_is_mapped(vaddr);
831 size_t segno =
vmem.segment_no(vaddr);
870 vmem.block_ptr(
block->next)->prev = blockaddr;
877 #if defined(__GNUC__) && (__GNUC__>11)
880 size_t alloc_size =
size + offsetof(
Block, data);
889 vmem.ensure_is_mapped(
vmem.freelist[flevel]);
890 while (flevel >
level) {
893 assert((blockaddr & ((1 << flevel) - 1)) == 0);
898 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
899 Block *block2 =
vmem.block_ptr(blockaddr2);
901 block2->next =
vmem.freelist[flevel];
902 block2->prev = blockaddr;
903 block->next = blockaddr2;
906 vmem.freelist[flevel] = blockaddr;
911 #if defined(__GNUC__) && (__GNUC__>11)
926 struct flock &lock_info,
size_t offset,
size_t len,
bool lock) {
927 lock_info.l_start =
offset;
928 lock_info.l_len = len;
930 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
935 struct flock lock_info;
937 fcntl(
fd, F_SETLKW, &lock_info);
941 struct flock lock_info;
943 fcntl(
fd, F_SETLKW, &lock_info);
958 snprintf(err_msg,
sizeof(err_msg),
"out of memory in vspace:init_metapage: %s", strerror(errno));
970 vmem.metapage->segment_count = 0;
991 return vmem.metapage->process_info[processno];
1001 if (processno ==
vmem.current_process) {
1007 int fd =
vmem.channels[processno].fd_write;
1008 char buf[1] = { 0 };
1009 while (write(
fd,
buf, 1) != 1) {
1025 int fd =
vmem.channels[
vmem.current_process].fd_read;
1027 if (lock && sigstate ==
Waiting) {
1031 #if defined(HAVE_POLL) && !defined(__APPLE__)
1035 pfd.events = POLLIN;
1036 int rv = poll(&pfd, 1, 500000);
1042 struct timeval timeout;
1043 timeout.tv_sec = 500;
1044 timeout.tv_usec = 0;
1045 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
1047 if (rv== -1)
continue;
1056 #if defined(HAVE_POLL) && !defined(__APPLE__)
1060 pfd.events = POLLIN;
1061 int rv = poll(&pfd, 1, 500000);
1067 struct timeval timeout;
1068 timeout.tv_sec = 500;
1069 timeout.tv_usec = 0;
1070 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
1072 if (rv== -1)
continue;
1111 for (
int p = 0;
p < MAX_PROCESS;
p++) {
1112 if (vmem.metapage->process_info[
p].pid == 0) {
1117 }
else if (pid == 0) {
1119 int parent = vmem.current_process;
1120 vmem.current_process =
p;
1122 vmem.metapage->process_info[
p].pid = getpid();
1124 send_signal(parent);
1219 event->_next =
NULL;
1223 _tail->_next = event;
1230 for (
Event *event =
_head; event;
event =
event->_next) {
1231 if (!event->start_listen((
int) (n++))) {
1236 for (
Event *event =
_head; event;
event =
event->_next) {
1237 event->stop_listen();
CanonicalForm map(const CanonicalForm &primElem, const Variable &alpha, const CanonicalForm &F, const Variable &beta)
map from to such that is mapped onto
int _waiting[internals::MAX_PROCESS+1]
bool start_wait(internals::ipc_signal_t sig=0)
internals::ipc_signal_t _signals[internals::MAX_PROCESS+1]
void WerrorS(const char *s)
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 const size_t MAX_SEGMENTS
static const size_t SEGMENT_SIZE
static const size_t METABLOCK_SIZE
static void lock_process(int processno)
static const int LOG2_SEGMENT_SIZE
ipc_signal_t wait_signal(bool lock)
static const int MAX_PROCESS
ProcessInfo process_info[MAX_PROCESS]
static void lock_allocator()
static segaddr_t find_buddy(segaddr_t addr, int level)
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 int find_level(size_t size)
static void unlock_allocator()
static void print_freelists()
internals::Mutex FastLock
int status int void size_t count open
int status int void * buf
Block * block_ptr(vaddr_t vaddr)
void * mmap_segment(int seg)
VSeg segments[MAX_SEGMENTS]
ProcessChannel channels[MAX_PROCESS]
Block * block_ptr(segaddr_t addr)
#define metapageaddr(field)