14#if defined(__GNUC__) && (__GNUC__<9) &&!defined(__clang__)
27#define metapageaddr(field) \
28 ((char *) &vmem.metapage->field - (char *) vmem.metapage)
42 if (pipe(channel) < 0) {
43 for (
int j = 0;
j <
i;
j++) {
66 metapage->process_info[0].pid = getpid();
71 int fd =
open(path, O_RDWR | O_CREAT, 0600);
106 if (
map == MAP_FAILED) {
117 int seg =
metapage->segment_count++;
128#ifdef HAVE_CPP_THREADS
129 while (
_lock.test_and_set()) {
152#ifdef HAVE_CPP_THREADS
153 while (
_lock.test_and_set()) {
167 vmem.metapage->allocator_lock.lock();
171 vmem.metapage->allocator_lock.unlock();
178 printf(
"%2d: %ld",
i, (
long)vaddr);
181 printf(
"(%ld)", (
long)prev);
190 printf(
" -> %ld", (
long)vaddr);
192 if (prev != last_vaddr) {
193 printf(
"(%ld)", (
long)prev);
204 vaddr -= offsetof(
Block, data);
205 vmem.ensure_is_mapped(vaddr);
206 size_t segno =
vmem.segment_no(vaddr);
209 int level = seg.block_ptr(addr)->level();
210 assert(!seg.is_free(addr));
222 assert(prev->next ==
vmem.vaddr(segno, buddy));
223 prev->next =
block->next;
245 vmem.block_ptr(
block->next)->prev = blockaddr;
252 size_t alloc_size =
size + offsetof(
Block, data);
260 vmem.ensure_is_mapped(
vmem.freelist[flevel]);
261 while (flevel >
level) {
264 assert((blockaddr & ((1 << flevel) - 1)) == 0);
269 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
270 Block *block2 =
vmem.block_ptr(blockaddr2);
272 block2->next =
vmem.freelist[flevel];
273 block2->prev = blockaddr;
274 block->next = blockaddr2;
277 vmem.freelist[flevel] = blockaddr;
282 #if defined(__GNUC__) && (__GNUC__>11)
297 struct flock &lock_info,
size_t offset,
size_t len,
bool lock) {
298 lock_info.l_start =
offset;
299 lock_info.l_len = len;
301 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
306 struct flock lock_info;
308 fcntl(
fd, F_SETLKW, &lock_info);
312 struct flock lock_info;
314 fcntl(
fd, F_SETLKW, &lock_info);
335 vmem.metapage->segment_count = 0;
355 return vmem.metapage->process_info[processno];
365 if (processno ==
vmem.current_process) {
371 int fd =
vmem.channels[processno].fd_write;
373 while (write(
fd,
buf, 1) != 1) {
389 int fd =
vmem.channels[
vmem.current_process].fd_read;
391 if (lock && sigstate ==
Waiting) {
395 #if defined(HAVE_POLL) && !defined(__APPLE__)
400 int rv = poll(&pfd, 1, 500000);
406 struct timeval timeout;
407 timeout.tv_sec = 500;
409 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
411 if (rv== -1)
continue;
420 #if defined(HAVE_POLL) && !defined(__APPLE__)
425 int rv = poll(&pfd, 1, 500000);
431 struct timeval timeout;
432 timeout.tv_sec = 500;
434 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
436 if (rv== -1)
continue;
475 for (
int p = 0;
p < MAX_PROCESS;
p++) {
476 if (vmem.metapage->process_info[
p].pid == 0) {
481 }
else if (pid == 0) {
483 int parent = vmem.current_process;
484 vmem.current_process =
p;
486 vmem.metapage->process_info[
p].pid = getpid();
587 _tail->_next = event;
594 for (Event *event =
_head; event;
event =
event->_next) {
595 if (!event->start_listen((
int) (n++))) {
600 for (Event *event =
_head; event;
event =
event->_next) {
601 event->stop_listen();
626#define metapageaddr(field) \
627 ((char *) &vmem.metapage->field - (char *) vmem.metapage)
641 if (pipe(channel) < 0) {
642 for (
int j = 0;
j <
i;
j++) {
659 FILE *
fp = tmpfile();
665 metapage->process_info[0].pid = getpid();
670 int fd =
open(path, O_RDWR | O_CREAT, 0600);
706 if (
map == MAP_FAILED) {
717 int seg =
metapage->segment_count++;
728#ifdef HAVE_CPP_THREADS
729 while (_lock.test_and_set()) {
731 bool empty = _owner < 0;
733 _owner =
vmem.current_process;
735 int p =
vmem.current_process;
736 vmem.metapage->process_info[
p].next = -1;
740 vmem.metapage->process_info[_tail].next =
p;
752#ifdef HAVE_CPP_THREADS
753 while (_lock.test_and_set()) {
757 _head =
vmem.metapage->process_info[_head].next;
767 vmem.metapage->allocator_lock.lock();
771 vmem.metapage->allocator_lock.unlock();
778 std::printf(
"%2d: %ld",
i, (
long)vaddr);
781 std::printf(
"(%ld)", (
long)prev);
790 std::printf(
" -> %ld", (
long)vaddr);
792 if (prev != last_vaddr) {
793 std::printf(
"(%ld)", (
long)prev);
804 #if defined(__GNUC__) && (__GNUC__>11)
807 vaddr -= offsetof(
Block, data);
809 vmem.ensure_is_mapped(vaddr);
810 size_t segno =
vmem.segment_no(vaddr);
849 vmem.block_ptr(
block->next)->prev = blockaddr;
856 #if defined(__GNUC__) && (__GNUC__>11)
859 size_t alloc_size =
size + offsetof(
Block, data);
868 vmem.ensure_is_mapped(
vmem.freelist[flevel]);
869 while (flevel >
level) {
872 assert((blockaddr & ((1 << flevel) - 1)) == 0);
877 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
878 Block *block2 =
vmem.block_ptr(blockaddr2);
880 block2->next =
vmem.freelist[flevel];
881 block2->prev = blockaddr;
882 block->next = blockaddr2;
885 vmem.freelist[flevel] = blockaddr;
890 #if defined(__GNUC__) && (__GNUC__>11)
905 struct flock &lock_info,
size_t offset,
size_t len,
bool lock) {
906 lock_info.l_start =
offset;
907 lock_info.l_len = len;
909 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
914 struct flock lock_info;
916 fcntl(
fd, F_SETLKW, &lock_info);
920 struct flock lock_info;
922 fcntl(
fd, F_SETLKW, &lock_info);
943 vmem.metapage->segment_count = 0;
964 return vmem.metapage->process_info[processno];
974 if (processno ==
vmem.current_process) {
980 int fd =
vmem.channels[processno].fd_write;
982 while (write(
fd,
buf, 1) != 1) {
998 int fd =
vmem.channels[
vmem.current_process].fd_read;
1000 if (lock && sigstate ==
Waiting) {
1004 #if defined(HAVE_POLL) && !defined(__APPLE__)
1008 pfd.events = POLLIN;
1009 int rv = poll(&pfd, 1, 500000);
1015 struct timeval timeout;
1016 timeout.tv_sec = 500;
1017 timeout.tv_usec = 0;
1018 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
1020 if (rv== -1)
continue;
1029 #if defined(HAVE_POLL) && !defined(__APPLE__)
1033 pfd.events = POLLIN;
1034 int rv = poll(&pfd, 1, 500000);
1040 struct timeval timeout;
1041 timeout.tv_sec = 500;
1042 timeout.tv_usec = 0;
1043 int rv = si_select(
fd + 1, &set,
NULL,
NULL, &timeout);
1045 if (rv== -1)
continue;
1084 for (
int p = 0;
p < MAX_PROCESS;
p++) {
1085 if (vmem.metapage->process_info[
p].pid == 0) {
1090 }
else if (pid == 0) {
1092 int parent = vmem.current_process;
1093 vmem.current_process =
p;
1095 vmem.metapage->process_info[
p].pid = getpid();
1097 send_signal(parent);
1192 event->_next =
NULL;
1196 _tail->_next = event;
1203 for (
Event *event =
_head; event;
event =
event->_next) {
1204 if (!event->start_listen((
int) (n++))) {
1209 for (
Event *event =
_head; event;
event =
event->_next) {
1210 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 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)