10#if defined(__GNUC__) && (__GNUC__<9) &&!defined(__clang__)
23#define metapageaddr(field) \
24 ((char *) &vmem.metapage->field - (char *) vmem.metapage)
38 if (pipe(channel) < 0) {
39 for (
int j = 0;
j <
i;
j++) {
62 metapage->process_info[0].pid = getpid();
67 int fd =
open(path, O_RDWR | O_CREAT, 0600);
102 if (
map == MAP_FAILED) {
113 int seg =
metapage->segment_count++;
124#ifdef HAVE_CPP_THREADS
125 while (
_lock.test_and_set()) {
148#ifdef HAVE_CPP_THREADS
149 while (
_lock.test_and_set()) {
163 vmem.metapage->allocator_lock.lock();
167 vmem.metapage->allocator_lock.unlock();
174 printf(
"%2d: %ld",
i, (
long)vaddr);
177 printf(
"(%ld)", (
long)prev);
186 printf(
" -> %ld", (
long)vaddr);
188 if (prev != last_vaddr) {
189 printf(
"(%ld)", (
long)prev);
200 vaddr -= offsetof(
Block, data);
201 vmem.ensure_is_mapped(vaddr);
202 size_t segno =
vmem.segment_no(vaddr);
205 int level = seg.block_ptr(addr)->level();
206 assert(!seg.is_free(addr));
218 assert(prev->next ==
vmem.vaddr(segno, buddy));
219 prev->next =
block->next;
241 vmem.block_ptr(
block->next)->prev = blockaddr;
248 size_t alloc_size =
size + offsetof(
Block, data);
256 vmem.ensure_is_mapped(
vmem.freelist[flevel]);
257 while (flevel >
level) {
260 assert((blockaddr & ((1 << flevel) - 1)) == 0);
265 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
266 Block *block2 =
vmem.block_ptr(blockaddr2);
268 block2->next =
vmem.freelist[flevel];
269 block2->prev = blockaddr;
270 block->next = blockaddr2;
273 vmem.freelist[flevel] = blockaddr;
278 #if defined(__GNUC__) && (__GNUC__>11)
293 struct flock &lock_info,
size_t offset,
size_t len,
bool lock) {
294 lock_info.l_start =
offset;
295 lock_info.l_len = len;
297 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
302 struct flock lock_info;
304 fcntl(
fd, F_SETLKW, &lock_info);
308 struct flock lock_info;
310 fcntl(
fd, F_SETLKW, &lock_info);
331 vmem.metapage->segment_count = 0;
351 return vmem.metapage->process_info[processno];
361 if (processno ==
vmem.current_process) {
367 int fd =
vmem.channels[processno].fd_write;
369 while (write(
fd,
buf, 1) != 1) {
385 int fd =
vmem.channels[
vmem.current_process].fd_read;
387 if (lock && sigstate ==
Waiting) {
429 for (
int p = 0;
p < MAX_PROCESS;
p++) {
430 if (vmem.metapage->process_info[
p].pid == 0) {
435 }
else if (pid == 0) {
437 int parent = vmem.current_process;
438 vmem.current_process =
p;
440 vmem.metapage->process_info[
p].pid = getpid();
541 _tail->_next = event;
548 for (Event *event =
_head; event;
event =
event->_next) {
549 if (!event->start_listen((
int) (n++))) {
554 for (Event *event =
_head; event;
event =
event->_next) {
555 event->stop_listen();
580#define metapageaddr(field) \
581 ((char *) &vmem.metapage->field - (char *) vmem.metapage)
595 if (pipe(channel) < 0) {
596 for (
int j = 0;
j <
i;
j++) {
613 FILE *
fp = tmpfile();
619 metapage->process_info[0].pid = getpid();
624 int fd =
open(path, O_RDWR | O_CREAT, 0600);
660 if (
map == MAP_FAILED) {
671 int seg =
metapage->segment_count++;
682#ifdef HAVE_CPP_THREADS
683 while (_lock.test_and_set()) {
685 bool empty = _owner < 0;
687 _owner =
vmem.current_process;
689 int p =
vmem.current_process;
690 vmem.metapage->process_info[
p].next = -1;
694 vmem.metapage->process_info[_tail].next =
p;
706#ifdef HAVE_CPP_THREADS
707 while (_lock.test_and_set()) {
711 _head =
vmem.metapage->process_info[_head].next;
721 vmem.metapage->allocator_lock.lock();
725 vmem.metapage->allocator_lock.unlock();
732 std::printf(
"%2d: %ld",
i, (
long)vaddr);
735 std::printf(
"(%ld)", (
long)prev);
744 std::printf(
" -> %ld", (
long)vaddr);
746 if (prev != last_vaddr) {
747 std::printf(
"(%ld)", (
long)prev);
758 #if defined(__GNUC__) && (__GNUC__>11)
761 vaddr -= offsetof(
Block, data);
763 vmem.ensure_is_mapped(vaddr);
764 size_t segno =
vmem.segment_no(vaddr);
803 vmem.block_ptr(
block->next)->prev = blockaddr;
810 #if defined(__GNUC__) && (__GNUC__>11)
813 size_t alloc_size =
size + offsetof(
Block, data);
822 vmem.ensure_is_mapped(
vmem.freelist[flevel]);
823 while (flevel >
level) {
826 assert((blockaddr & ((1 << flevel) - 1)) == 0);
831 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
832 Block *block2 =
vmem.block_ptr(blockaddr2);
834 block2->next =
vmem.freelist[flevel];
835 block2->prev = blockaddr;
836 block->next = blockaddr2;
839 vmem.freelist[flevel] = blockaddr;
844 #if defined(__GNUC__) && (__GNUC__>11)
859 struct flock &lock_info,
size_t offset,
size_t len,
bool lock) {
860 lock_info.l_start =
offset;
861 lock_info.l_len = len;
863 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
868 struct flock lock_info;
870 fcntl(
fd, F_SETLKW, &lock_info);
874 struct flock lock_info;
876 fcntl(
fd, F_SETLKW, &lock_info);
897 vmem.metapage->segment_count = 0;
918 return vmem.metapage->process_info[processno];
928 if (processno ==
vmem.current_process) {
934 int fd =
vmem.channels[processno].fd_write;
936 while (write(
fd,
buf, 1) != 1) {
952 int fd =
vmem.channels[
vmem.current_process].fd_read;
954 if (lock && sigstate ==
Waiting) {
996 for (
int p = 0;
p < MAX_PROCESS;
p++) {
997 if (vmem.metapage->process_info[
p].pid == 0) {
1002 }
else if (pid == 0) {
1004 int parent = vmem.current_process;
1005 vmem.current_process =
p;
1007 vmem.metapage->process_info[
p].pid = getpid();
1009 send_signal(parent);
1104 event->_next =
NULL;
1108 _tail->_next = event;
1115 for (
Event *event =
_head; event;
event =
event->_next) {
1116 if (!event->start_listen((
int) (n++))) {
1121 for (
Event *event =
_head; event;
event =
event->_next) {
1122 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)